From c93c03815328bd7f095c7a2251ea68c1f0615106 Mon Sep 17 00:00:00 2001 From: shockrah Date: Tue, 26 May 2026 22:12:16 -0700 Subject: [PATCH] New data structures for handling configuration load --- collector/scraper/config.json | 4 +-- collector/scraper/src/data/config.ts | 49 ++++++++++++++++++++++++---- collector/scraper/src/data/error.ts | 15 +++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 collector/scraper/src/data/error.ts diff --git a/collector/scraper/config.json b/collector/scraper/config.json index b8c7427..6ee38d8 100644 --- a/collector/scraper/config.json +++ b/collector/scraper/config.json @@ -2,8 +2,8 @@ "stores": [ { "name": "kroger", - "base_url": "https://shockrah.xyz", - "roducts": [] + "base_url": "https://api-ce.kroger.com/v1/", + "products": [] } ] } diff --git a/collector/scraper/src/data/config.ts b/collector/scraper/src/data/config.ts index 00a65b3..0546ef6 100644 --- a/collector/scraper/src/data/config.ts +++ b/collector/scraper/src/data/config.ts @@ -1,4 +1,4 @@ -import fsPromises from 'fs/promises'; +import fsPromises from 'fs/promises' interface Product { name: string, @@ -14,25 +14,59 @@ export interface Store { /* + * NOTE: ConentConfig defines what content we actually want; it has + * almost nothing to do with key definitions and is meant to be fully public. + * * Here we control what stores and what products we are going to query * from the configuration since the collector is basically just a oneshot * tool */ -export interface Config { +export interface ContentConfig { stores: Array } +/* + * Sets up the API keys that we pull in from the environment + * WARN: this should never mix wth the Config type to keep things + * from leaking out into a plaintext file. Config's are considered to be + * expendable and public facing and as such can be committed ( for my + * purposes ) +*/ +export interface Keys { + kroger_id: string|undefined + kroger_secret: string|undefined +} + +/* + * Environment variable names to look out for for key values + */ +export const EnvVars = { + kroger_id: 'KROGER_CLIENT_ID', + kroger_secret: 'KROGER_SECRET' +} + +/** + * Loads the values from the env const +* +*/ +export function LoadKeys() : Keys { + return { + kroger_id: process.env.KROGER_CLIENT_ID, + kroger_secret: process.env.KROGER_SECRET, + } +} + /* * Handling the validation of our configuration * */ -function valid(data: any) : data is Config { +function valid(data: any) : data is ContentConfig { if('stores' in data) { if(!(data['stores'] instanceof Array)) { console.error('stores is not an array!') return false } - for(const store in data['stores']) { + for(const store of data['stores']) { // TODO: i don't like this check but it's fine for now :thinking: const keys = Object.keys(store); return keys.includes('name') && keys.includes('base_url') && keys.includes('products') @@ -46,13 +80,14 @@ function valid(data: any) : data is Config { * Handling the loading and generation of the Configuration that we'll use * during the run of data fetching. */ -export async function LoadConfig(path: string) : Promise { +export async function LoadConfig(path: string) : Promise { try { const file = await fsPromises.readFile(path); - const config: Config = JSON.parse(file.toString()) + const config: ContentConfig = JSON.parse(file.toString()) return valid(config) ? config : null; - } catch { + // TODO: fix this catch block to be more explicit + console.error('bro') return null; } } diff --git a/collector/scraper/src/data/error.ts b/collector/scraper/src/data/error.ts new file mode 100644 index 0000000..4c7884f --- /dev/null +++ b/collector/scraper/src/data/error.ts @@ -0,0 +1,15 @@ +export class EnvVarError extends Error { + constructor(message: string) { + super(message) + this.name = 'EnvVarError' + this.message = message + } +} + +export class ConfigurationError extends Error { + constructor(message: string) { + super(message) + this.name = 'CollectorConfigurationError' + this.message = message + } +}