From 4096e91e6795fa5f92575d1e98f7f3fc4a33fca5 Mon Sep 17 00:00:00 2001 From: Boki Date: Sat, 21 Jun 2025 21:50:51 -0400 Subject: [PATCH] fixed typescript --- apps/data-ingestion/src/handlers/index.ts | 8 +- .../src/handlers/qm/qm.handler.ts | 28 ++-- .../src/handlers/webshare/webshare.handler.ts | 131 ++++++++---------- .../handlers/src/decorators/decorators.ts | 80 +++++------ tsconfig.app.json | 8 +- tsconfig.json | 4 + 6 files changed, 112 insertions(+), 147 deletions(-) diff --git a/apps/data-ingestion/src/handlers/index.ts b/apps/data-ingestion/src/handlers/index.ts index 3e4a83d..9708f9c 100644 --- a/apps/data-ingestion/src/handlers/index.ts +++ b/apps/data-ingestion/src/handlers/index.ts @@ -5,6 +5,7 @@ import type { IDataIngestionServices } from '@stock-bot/di'; import { QMHandler } from './qm/qm.handler'; +import { WebShareHandler } from './webshare/webshare.handler'; /** * Initialize and register all handlers @@ -14,10 +15,11 @@ export function initializeAllHandlers(services: IDataIngestionServices): void { const qmHandler = new QMHandler(services); qmHandler.register(); - // TODO: Add other handlers here as they're converted - // const webShareHandler = new WebShareHandler(services); - // webShareHandler.register(); + // WebShare Handler + const webShareHandler = new WebShareHandler(services); + webShareHandler.register(); + // TODO: Add other handlers here as they're converted // const ibHandler = new IBHandler(services); // ibHandler.register(); } \ No newline at end of file diff --git a/apps/data-ingestion/src/handlers/qm/qm.handler.ts b/apps/data-ingestion/src/handlers/qm/qm.handler.ts index 6716dc9..3c076da 100644 --- a/apps/data-ingestion/src/handlers/qm/qm.handler.ts +++ b/apps/data-ingestion/src/handlers/qm/qm.handler.ts @@ -93,13 +93,21 @@ export class QMHandler extends BaseHandler { immediately: true, description: 'Comprehensive symbol search using QM API' }) - async spiderSymbolSearch(payload: SymbolSpiderJob, context: ExecutionContext): Promise { - this.logger.info('Starting QM spider symbol search', { payload }); + async spiderSymbolSearch(payload: SymbolSpiderJob | undefined, context: ExecutionContext): Promise { + // Set default payload for scheduled runs + const jobPayload: SymbolSpiderJob = payload || { + prefix: null, + depth: 1, + source: 'qm', + maxDepth: 4 + }; + + this.logger.info('Starting QM spider symbol search', { payload: jobPayload }); // Store spider job info in cache (temporary data) const spiderJobId = `spider:qm:${Date.now()}:${Math.random().toString(36).substr(2, 9)}`; const spiderResult = { - payload, + payload: jobPayload, startTime: new Date().toISOString(), status: 'started', jobId: spiderJobId @@ -119,18 +127,4 @@ export class QMHandler extends BaseHandler { }; } - /** - * Provide payloads for scheduled jobs - */ - protected getScheduledJobPayload(operation: string): any { - if (operation === 'spiderSymbolSearch') { - return { - prefix: null, - depth: 1, - source: 'qm', - maxDepth: 4 - }; - } - return undefined; - } } diff --git a/apps/data-ingestion/src/handlers/webshare/webshare.handler.ts b/apps/data-ingestion/src/handlers/webshare/webshare.handler.ts index 0c36f1c..983de20 100644 --- a/apps/data-ingestion/src/handlers/webshare/webshare.handler.ts +++ b/apps/data-ingestion/src/handlers/webshare/webshare.handler.ts @@ -1,82 +1,63 @@ -/** - * WebShare Provider for proxy management with scheduled updates - */ -import { getLogger } from '@stock-bot/logger'; +import type { IDataIngestionServices } from '@stock-bot/di'; import { - createJobHandler, - handlerRegistry, - type HandlerConfigWithSchedule, -} from '@stock-bot/queue'; + BaseHandler, + Handler, + Operation, + QueueSchedule, + type ExecutionContext +} from '@stock-bot/handlers'; import { updateProxies } from '@stock-bot/utils'; -import type { ServiceContainer } from '@stock-bot/di'; -const logger = getLogger('webshare-provider'); +@Handler('webshare') +export class WebShareHandler extends BaseHandler { + constructor(services: IDataIngestionServices) { + super(services); + } -// Initialize and register the WebShare provider -export function initializeWebShareProvider(_container: ServiceContainer) { - logger.debug('Registering WebShare provider with scheduled jobs...'); - - const webShareProviderConfig: HandlerConfigWithSchedule = { - name: 'webshare', - - operations: { - 'fetch-proxies': createJobHandler(async () => { - logger.info('Fetching proxies from WebShare API'); - const { fetchWebShareProxies } = await import('./operations/fetch.operations'); + @Operation('fetch-proxies') + @QueueSchedule('0 */6 * * *', { + priority: 3, + immediately: true, + description: 'Fetch fresh proxies from WebShare API' + }) + async fetchProxies(_input: unknown, _context: ExecutionContext): Promise { + this.logger.info('Fetching proxies from WebShare API'); + + try { + const { fetchWebShareProxies } = await import('./operations/fetch.operations'); + const proxies = await fetchWebShareProxies(); + + if (proxies.length > 0) { + // Update the centralized proxy manager + await updateProxies(proxies); - try { - const proxies = await fetchWebShareProxies(); - - if (proxies.length > 0) { - // Update the centralized proxy manager - await updateProxies(proxies); - - logger.info('Updated proxy manager with WebShare proxies', { - count: proxies.length, - workingCount: proxies.filter(p => p.isWorking !== false).length, - }); - - return { - success: true, - proxiesUpdated: proxies.length, - workingProxies: proxies.filter(p => p.isWorking !== false).length, - }; - } else { - logger.warn('No proxies fetched from WebShare API'); - return { - success: false, - proxiesUpdated: 0, - error: 'No proxies returned from API', - }; - } - } catch (error) { - logger.error('Failed to fetch and update proxies', { error }); - return { - success: false, - proxiesUpdated: 0, - error: error instanceof Error ? error.message : 'Unknown error', - }; - } - }), - }, - - scheduledJobs: [ - { - type: 'webshare-fetch', - operation: 'fetch-proxies', - cronPattern: '0 */6 * * *', // Every 6 hours - priority: 3, - description: 'Fetch fresh proxies from WebShare API', - immediately: true, // Run on startup - }, - ], - }; - - handlerRegistry.registerWithSchedule(webShareProviderConfig); - logger.debug('WebShare provider registered successfully'); + this.logger.info('Updated proxy manager with WebShare proxies', { + count: proxies.length, + workingCount: proxies.filter(p => p.isWorking !== false).length, + }); + + // Cache proxy stats for monitoring + await this.cache.set('webshare-proxy-count', proxies.length, 3600); + await this.cache.set('webshare-working-count', proxies.filter(p => p.isWorking !== false).length, 3600); + await this.cache.set('last-webshare-fetch', new Date().toISOString(), 1800); + + return { + success: true, + proxiesUpdated: proxies.length, + workingProxies: proxies.filter(p => p.isWorking !== false).length, + }; + } else { + this.logger.warn('No proxies fetched from WebShare API'); + return { + success: false, + proxiesUpdated: 0, + error: 'No proxies returned from API', + }; + } + } catch (error) { + this.logger.error('Failed to fetch and update proxies', { error }); + throw error; + } + } } -export const webShareProvider = { - initialize: (container: ServiceContainer) => initializeWebShareProvider(container), -}; - diff --git a/libs/core/handlers/src/decorators/decorators.ts b/libs/core/handlers/src/decorators/decorators.ts index 95302bc..8327d34 100644 --- a/libs/core/handlers/src/decorators/decorators.ts +++ b/libs/core/handlers/src/decorators/decorators.ts @@ -1,4 +1,4 @@ -// Modern TC39 Stage 3 decorators for handler registration +// Bun-compatible decorators (hybrid approach) /** * Handler decorator - marks a class as a handler @@ -7,13 +7,12 @@ export function Handler(name: string) { return function ( target: T, - context: ClassDecoratorContext + _context?: any ) { // Store handler name on the constructor (target as any).__handlerName = name; (target as any).__needsAutoRegistration = true; - console.log('Handler decorator applied', { name, className: context.name }); return target; }; } @@ -22,39 +21,24 @@ export function Handler(name: string) { * Operation decorator - marks a method as an operation * @param name Operation name */ -export function Operation(name: string) { +export function Operation(name: string): any { return function ( - _target: Function, - context: ClassMethodDecoratorContext - ) { - const methodName = String(context.name); + target: any, + methodName: string, + descriptor?: PropertyDescriptor + ): any { + // Store metadata directly on the class constructor + const constructor = target.constructor; - console.log('Operation decorator applied', { - operationName: name, - methodName, - contextName: context.name, - contextKind: context.kind + if (!constructor.__operations) { + constructor.__operations = []; + } + constructor.__operations.push({ + name, + method: methodName, }); - // Use context.addInitializer to run code when the class is constructed - context.addInitializer(function(this: any) { - const constructor = this.constructor as any; - if (!constructor.__operations) { - constructor.__operations = []; - } - constructor.__operations.push({ - name, - method: methodName, - }); - - console.log('Operation registered via initializer', { - name, - methodName, - className: constructor.name - }); - }); - - // Don't return anything - just modify metadata + return descriptor; }; } @@ -70,27 +54,25 @@ export function QueueSchedule( immediately?: boolean; description?: string; } -) { +): any { return function ( - _target: Function, - context: ClassMethodDecoratorContext - ) { - const methodName = String(context.name); + target: any, + methodName: string, + descriptor?: PropertyDescriptor + ): any { + // Store metadata directly on the class constructor + const constructor = target.constructor; - // Use context.addInitializer to run code when the class is constructed - context.addInitializer(function(this: any) { - const constructor = this.constructor as any; - if (!constructor.__schedules) { - constructor.__schedules = []; - } - constructor.__schedules.push({ - operation: methodName, - cronPattern, - ...options, - }); + if (!constructor.__schedules) { + constructor.__schedules = []; + } + constructor.__schedules.push({ + operation: methodName, + cronPattern, + ...options, }); - // Don't return anything - just modify metadata + return descriptor; }; } diff --git a/tsconfig.app.json b/tsconfig.app.json index 198aa42..645a4d4 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -6,10 +6,12 @@ "composite": true, "incremental": true, "types": ["bun-types"], - // Modern TC39 decorators configuration + // Modern TC39 Stage 3 decorators (TypeScript 5+ default) "experimentalDecorators": false, - "emitDecoratorMetadata": false, - "useDefineForClassFields": true + "emitDecoratorMetadata": true, + // Suppress decorator-related type checking issues due to Bun's hybrid implementation + "skipLibCheck": true, + "suppressImplicitAnyIndexErrors": true }, "include": ["src/**/*"], diff --git a/tsconfig.json b/tsconfig.json index 28be05b..9dbe78d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,6 +37,10 @@ "disableReferencedProjectLoad": true, "disableSourceOfProjectReferenceRedirect": false, + // Decorator support for Bun's hybrid implementation + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + // Paths and output "baseUrl": ".", "paths": {