From b501d7a2da906b5bbd1b0b79dbc02b7a0599ace1 Mon Sep 17 00:00:00 2001 From: Boki Date: Fri, 20 Jun 2025 00:04:38 -0400 Subject: [PATCH] fixed webshare --- apps/data-service/config/default.json | 6 ++- .../src/providers/webshare.provider.ts | 10 ++++- libs/config/src/loaders/env.loader.ts | 42 +++++++++++++++++++ libs/config/src/schemas/index.ts | 3 +- libs/config/src/schemas/provider.schema.ts | 11 ++++- 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/apps/data-service/config/default.json b/apps/data-service/config/default.json index df7cdac..6c46d28 100644 --- a/apps/data-service/config/default.json +++ b/apps/data-service/config/default.json @@ -16,7 +16,7 @@ "redis": { "host": "localhost", "port": 6379, - "db": 1 + "db": 0 }, "defaultJobOptions": { "attempts": 3, @@ -27,5 +27,9 @@ "removeOnComplete": true, "removeOnFail": false } + }, + "webshare": { + "apiKey": "", + "apiUrl": "https://proxy.webshare.io/api/v2/" } } \ No newline at end of file diff --git a/apps/data-service/src/providers/webshare.provider.ts b/apps/data-service/src/providers/webshare.provider.ts index 6360b06..7006afd 100644 --- a/apps/data-service/src/providers/webshare.provider.ts +++ b/apps/data-service/src/providers/webshare.provider.ts @@ -95,9 +95,13 @@ export const webShareProvider = { async function fetchProxiesFromWebShare(): Promise { try { + // Get configuration from config system + const { getConfig } = await import('@stock-bot/config'); + const config = getConfig(); + // Try environment variables first, then fall back to config - const apiKey = process.env.WEBSHARE_API_KEY; - const apiUrl = process.env.WEBSHARE_API_URL; + const apiKey = process.env.WEBSHARE_API_KEY || config.webshare?.apiKey; + const apiUrl = process.env.WEBSHARE_API_URL || config.webshare?.apiUrl; if (!apiKey || !apiUrl) { logger.error('Missing WebShare configuration', { @@ -105,6 +109,8 @@ async function fetchProxiesFromWebShare(): Promise { hasApiUrl: !!apiUrl, envApiKey: process.env.WEBSHARE_API_KEY?.substring(0, 10) + '...', envApiUrl: process.env.WEBSHARE_API_URL, + configApiKey: config.webshare?.apiKey?.substring(0, 10) + '...', + configApiUrl: config.webshare?.apiUrl, }); return null; } diff --git a/libs/config/src/loaders/env.loader.ts b/libs/config/src/loaders/env.loader.ts index 3a15553..305c2de 100644 --- a/libs/config/src/loaders/env.loader.ts +++ b/libs/config/src/loaders/env.loader.ts @@ -1,5 +1,6 @@ import { ConfigLoader } from '../types'; import { ConfigLoaderError } from '../errors'; +import { readFileSync } from 'fs'; export interface EnvLoaderOptions { convertCase?: boolean; @@ -26,6 +27,9 @@ export class EnvLoader implements ConfigLoader { async load(): Promise> { try { + // Load root .env file only + this.loadEnvFile('../../.env'); // Root .env + const config: Record = {}; const envVars = process.env; @@ -137,4 +141,42 @@ export class EnvLoader implements ConfigLoader { // Return as string return value; } + + private loadEnvFile(filePath: string): void { + try { + const envContent = readFileSync(filePath, 'utf-8'); + const lines = envContent.split('\n'); + + for (const line of lines) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) { + continue; // Skip empty lines and comments + } + + const equalIndex = trimmed.indexOf('='); + if (equalIndex === -1) { + continue; // Skip lines without = + } + + const key = trimmed.substring(0, equalIndex).trim(); + let value = trimmed.substring(equalIndex + 1).trim(); + + // Remove surrounding quotes if present + if ((value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'"))) { + value = value.slice(1, -1); + } + + // Only set if not already set (allows override precedence) + if (!(key in process.env)) { + process.env[key] = value; + } + } + } catch (error: any) { + // File not found is not an error (env files are optional) + if (error.code !== 'ENOENT') { + console.warn(`Warning: Could not load env file ${filePath}:`, error.message); + } + } + } } \ No newline at end of file diff --git a/libs/config/src/schemas/index.ts b/libs/config/src/schemas/index.ts index 40fe22f..177039a 100644 --- a/libs/config/src/schemas/index.ts +++ b/libs/config/src/schemas/index.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; import { baseConfigSchema, environmentSchema } from './base.schema'; import { databaseConfigSchema } from './database.schema'; import { serviceConfigSchema, loggingConfigSchema, queueConfigSchema, httpConfigSchema } from './service.schema'; -import { providerConfigSchema } from './provider.schema'; +import { providerConfigSchema, webshareProviderConfigSchema } from './provider.schema'; // Complete application configuration schema export const appConfigSchema = baseConfigSchema.extend({ @@ -18,6 +18,7 @@ export const appConfigSchema = baseConfigSchema.extend({ queue: queueConfigSchema.optional(), http: httpConfigSchema.optional(), providers: providerConfigSchema.optional(), + webshare: webshareProviderConfigSchema.optional(), }); export type AppConfig = z.infer; \ No newline at end of file diff --git a/libs/config/src/schemas/provider.schema.ts b/libs/config/src/schemas/provider.schema.ts index 87d106b..b4bdbce 100644 --- a/libs/config/src/schemas/provider.schema.ts +++ b/libs/config/src/schemas/provider.schema.ts @@ -46,20 +46,29 @@ export const yahooProviderConfigSchema = baseProviderConfigSchema.extend({ crumb: z.string().optional(), }); +// WebShare proxy provider +export const webshareProviderConfigSchema = z.object({ + apiKey: z.string().optional(), + apiUrl: z.string().default('https://proxy.webshare.io/api/v2/'), + enabled: z.boolean().default(true), +}); + // Combined provider configuration export const providerConfigSchema = z.object({ eod: eodProviderConfigSchema.optional(), ib: ibProviderConfigSchema.optional(), qm: qmProviderConfigSchema.optional(), yahoo: yahooProviderConfigSchema.optional(), + webshare: webshareProviderConfigSchema.optional(), }); // Dynamic provider configuration type -export type ProviderName = 'eod' | 'ib' | 'qm' | 'yahoo'; +export type ProviderName = 'eod' | 'ib' | 'qm' | 'yahoo' | 'webshare'; export const providerSchemas = { eod: eodProviderConfigSchema, ib: ibProviderConfigSchema, qm: qmProviderConfigSchema, yahoo: yahooProviderConfigSchema, + webshare: webshareProviderConfigSchema, } as const; \ No newline at end of file