fixed up qm and added types to BaseHandler for typesafety
This commit is contained in:
parent
87b1cad4f5
commit
2e86598262
20 changed files with 164 additions and 109 deletions
|
|
@ -75,7 +75,7 @@ export async function getChannels(this: CeoHandler, payload: number | undefined)
|
|||
|
||||
this.logger.info(`Fetched CEO channels for page ${page}/${totalPages}`);
|
||||
return { page, totalPages };
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Error fetching CEO channels for page ${page} with proxy ${proxy}:`, error);
|
||||
throw new Error(`Failed to fetch CEO channels: ${error.message}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import {
|
|||
ScheduledOperation,
|
||||
} from '@stock-bot/handlers';
|
||||
import { getChannels, getPosts, getShorts, updateUniqueSymbols } from './actions';
|
||||
import type { DataIngestionServices } from '../../types';
|
||||
|
||||
@Handler('ceo')
|
||||
@Disabled()
|
||||
export class CeoHandler extends BaseHandler {
|
||||
export class CeoHandler extends BaseHandler<DataIngestionServices> {
|
||||
constructor(services: any) {
|
||||
super(services); // Handler name read from @Handler decorator
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { IServiceContainer } from '@stock-bot/handlers';
|
||||
import { fetchExchanges } from './fetch-exchanges.action';
|
||||
import { fetchSession } from './fetch-session.action';
|
||||
import { fetchSymbols } from './fetch-symbols.action';
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Corporate Actions - Fetch and update dividends, splits, and earnings together
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* Single API call returns all three data types
|
||||
*/
|
||||
export async function updateCorporateActions(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
symbolId: number;
|
||||
|
|
@ -191,7 +192,7 @@ export async function updateCorporateActions(
|
|||
* Schedule corporate actions updates for symbols that need refreshing
|
||||
*/
|
||||
export async function scheduleCorporateActionsUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
forceUpdate?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Filings Actions - Fetch and update SEC filings
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* Update filings for a single symbol
|
||||
*/
|
||||
export async function updateFilings(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
symbolId: number;
|
||||
|
|
@ -160,7 +161,7 @@ export async function updateFilings(
|
|||
* Schedule filings updates for symbols that need refreshing
|
||||
*/
|
||||
export async function scheduleFilingsUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
forceUpdate?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Financials Actions - Fetch and update financial statements
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* Update financials for a single symbol
|
||||
*/
|
||||
export async function updateFinancials(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
symbolId: number;
|
||||
|
|
@ -136,7 +137,6 @@ export async function updateFinancials(
|
|||
const tracker = await getOperationTracker(this);
|
||||
await tracker.updateSymbolOperation(symbol, 'financials_update', {
|
||||
status: 'failure',
|
||||
lastRunAt: new Date()
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
@ -151,7 +151,7 @@ export async function updateFinancials(
|
|||
* Schedule financial updates for symbols that need refreshing
|
||||
*/
|
||||
export async function scheduleFinancialsUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
forceUpdate?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Intraday Actions - Fetch and update intraday price bars
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* This handles both initial crawl and incremental updates
|
||||
*/
|
||||
export async function updateIntradayBars(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
symbolId: number;
|
||||
|
|
@ -66,7 +67,7 @@ export async function updateIntradayBars(
|
|||
webmasterId: '500',
|
||||
date: targetDate.toISOString().split('T')[0],
|
||||
interval: '1' // 1-minute bars
|
||||
});
|
||||
} as Record<string, string>);
|
||||
|
||||
// TODO: Update with correct intraday endpoint
|
||||
const apiUrl = `${QM_CONFIG.BASE_URL}/datatool/intraday.json?${searchParams.toString()}`;
|
||||
|
|
@ -157,7 +158,7 @@ export async function updateIntradayBars(
|
|||
* This handles both initial crawls and regular updates
|
||||
*/
|
||||
export async function scheduleIntradayUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
mode?: 'crawl' | 'update'; // crawl for historical, update for recent
|
||||
|
|
@ -259,7 +260,6 @@ export async function scheduleIntradayUpdates(
|
|||
crawlState: {
|
||||
finished: false,
|
||||
oldestDateReached: new Date(startDate.getTime() - daysToFetch * 24 * 60 * 60 * 1000),
|
||||
lastCrawlDirection: 'backward'
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Prices Actions - Fetch and update daily price data
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* Update daily prices for a single symbol
|
||||
*/
|
||||
export async function updatePrices(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
symbolId: number;
|
||||
|
|
@ -164,7 +165,7 @@ export async function updatePrices(
|
|||
* Schedule price updates for symbols that need refreshing
|
||||
*/
|
||||
export async function schedulePriceUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
forceUpdate?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@
|
|||
* QM Session Actions - Session management and creation
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import { BunRequestInit } from '@stock-bot/utils';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { getQmHeaders, QM_CONFIG, QM_SESSION_IDS, SESSION_CONFIG } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMSession } from '../shared/types';
|
||||
import { type QMSession } from '../shared/types';
|
||||
|
||||
/**
|
||||
* Check existing sessions and queue creation jobs for needed sessions
|
||||
* This is the main session management function that handles cleanup, maintenance, and initialization
|
||||
*/
|
||||
export async function checkSessions(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
_input: unknown,
|
||||
_context: ExecutionContext
|
||||
): Promise<{
|
||||
|
|
@ -80,7 +80,7 @@ interface CreateSessionInput {
|
|||
}
|
||||
|
||||
export async function createSession(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: CreateSessionInput
|
||||
): Promise<{ sessionId: string; status: string; sessionType: string, session?: QMSession }> {
|
||||
const { sessionId, sessionType = 'LOOKUP' } = input || {};
|
||||
|
|
@ -108,7 +108,7 @@ export async function createSession(
|
|||
const sessionUrl = `${QM_CONFIG.BASE_URL}${QM_CONFIG.SESSION_PATH}/${sessionId}`;
|
||||
|
||||
// Build request options
|
||||
const sessionRequest: BunRequestInit = {
|
||||
const sessionRequest = {
|
||||
proxy: proxyUrl || undefined,
|
||||
headers: getQmHeaders(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* QM Symbol Info Actions - Fetch and update symbol metadata
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
|
||||
// Cache tracker instance
|
||||
let operationTracker: QMOperationTracker | null = null;
|
||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
|||
/**
|
||||
* Get or initialize the operation tracker
|
||||
*/
|
||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
||||
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||
if (!operationTracker) {
|
||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
|||
* This is a simple API fetch operation - no tracking logic here
|
||||
*/
|
||||
export async function updateSymbolInfo(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
symbol: string;
|
||||
qmSearchCode: string;
|
||||
|
|
@ -144,7 +145,7 @@ export async function updateSymbolInfo(
|
|||
* This is the scheduled job that finds stale symbols and queues individual updates
|
||||
*/
|
||||
export async function scheduleSymbolInfoUpdates(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: {
|
||||
limit?: number;
|
||||
forceUpdate?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
* QM Symbol Actions - Symbol search and spider operations
|
||||
*/
|
||||
|
||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
||||
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||
import { QMSessionManager } from '../shared/session-manager';
|
||||
// import { QMOperationTracker } from '../shared/operation-tracker';
|
||||
// import { initializeQMOperations } from '../shared/operation-registry';
|
||||
import type { QMHandler } from '../qm.handler';
|
||||
import type { Exchange, SymbolSpiderJob } from '../shared/types';
|
||||
|
||||
/**
|
||||
|
|
@ -15,7 +16,7 @@ import type { Exchange, SymbolSpiderJob } from '../shared/types';
|
|||
* Each job searches its prefix and creates child jobs if needed
|
||||
*/
|
||||
export async function spiderSymbol(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: SymbolSpiderJob,
|
||||
_context: ExecutionContext
|
||||
): Promise<{
|
||||
|
|
@ -62,7 +63,7 @@ export async function spiderSymbol(
|
|||
};
|
||||
}
|
||||
|
||||
await this.mongodb.batchUpsert('qmSymbols', symbols, ['qmSearchCode']);
|
||||
await this.mongodb?.batchUpsert('qmSymbols', symbols, ['qmSearchCode']);
|
||||
|
||||
this.logger.info(`Stored symbols from spider search ${prefix} - ${symbols.length}`, {
|
||||
prefix,
|
||||
|
|
@ -84,7 +85,7 @@ export async function spiderSymbol(
|
|||
}
|
||||
|
||||
if (exchanges.length > 0) {
|
||||
await this.mongodb.batchUpsert('qmExchanges', exchanges, ['exchange']);
|
||||
await this.mongodb?.batchUpsert('qmExchanges', exchanges, ['exchange']);
|
||||
this.logger.debug('Stored exchanges from spider search', {
|
||||
count: exchanges.length
|
||||
});
|
||||
|
|
@ -136,7 +137,7 @@ export async function spiderSymbol(
|
|||
* Search QM symbols API directly
|
||||
*/
|
||||
export async function searchSymbols(
|
||||
this: BaseHandler,
|
||||
this: QMHandler,
|
||||
input: { query: string },
|
||||
_context?: ExecutionContext
|
||||
): Promise<any[]> {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
Operation,
|
||||
ScheduledOperation,
|
||||
} from '@stock-bot/handlers';
|
||||
import type { DataIngestionServices } from '../../types';
|
||||
import {
|
||||
checkSessions,
|
||||
createSession,
|
||||
|
|
@ -25,7 +26,7 @@ import {
|
|||
import { initializeQMOperations } from './shared/operation-registry';
|
||||
|
||||
@Handler('qm')
|
||||
export class QMHandler extends BaseHandler {
|
||||
export class QMHandler extends BaseHandler<DataIngestionServices> {
|
||||
constructor(services: any) {
|
||||
super(services); // Handler name read from @Handler decorator
|
||||
// Initialize operations after super() so services are available
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Supports dynamic operation registration with auto-indexing
|
||||
*/
|
||||
|
||||
import type { MongoDBClient, Logger } from '@stock-bot/types';
|
||||
import type { Logger, MongoDBClient } from '@stock-bot/types';
|
||||
import type { IntradayCrawlSymbol, QMOperationConfig } from './types';
|
||||
|
||||
export class QMOperationTracker {
|
||||
|
|
@ -118,7 +118,7 @@ export class QMOperationTracker {
|
|||
|
||||
await this.mongodb.updateOne(this.collectionName, { symbol }, update);
|
||||
|
||||
this.logger.trace('Updated symbol operation', {
|
||||
this.logger.debug('Updated symbol operation', {
|
||||
symbol,
|
||||
operation: operationName,
|
||||
status: data.status
|
||||
|
|
|
|||
25
apps/stock/data-ingestion/src/types.ts
Normal file
25
apps/stock/data-ingestion/src/types.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Data Ingestion Service Types
|
||||
* Defines required services for data ingestion handlers
|
||||
*/
|
||||
|
||||
import type { ServiceTypes } from '@stock-bot/types';
|
||||
|
||||
/**
|
||||
* Services required by data ingestion handlers
|
||||
* Makes specific services non-nullable since they're always enabled
|
||||
*/
|
||||
export type DataIngestionServices = ServiceTypes & {
|
||||
// Always required services
|
||||
logger: NonNullable<ServiceTypes['logger']>;
|
||||
mongodb: NonNullable<ServiceTypes['mongodb']>;
|
||||
cache: NonNullable<ServiceTypes['cache']>;
|
||||
queue: NonNullable<ServiceTypes['queue']>;
|
||||
queueManager: NonNullable<ServiceTypes['queueManager']>;
|
||||
browser: NonNullable<ServiceTypes['browser']>;
|
||||
proxy: NonNullable<ServiceTypes['proxy']>;
|
||||
// Optional services remain optional
|
||||
postgres: ServiceTypes['postgres'];
|
||||
questdb: ServiceTypes['questdb'];
|
||||
globalCache: ServiceTypes['globalCache'];
|
||||
};
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"extends": "../../tsconfig.app.json",
|
||||
"extends": "../../../tsconfig.app.json",
|
||||
"references": [
|
||||
{ "path": "../../libs/core/types" },
|
||||
{ "path": "../../libs/core/config" },
|
||||
{ "path": "../../libs/core/logger" },
|
||||
{ "path": "../../libs/core/di" },
|
||||
{ "path": "../../libs/core/handlers" },
|
||||
{ "path": "../../libs/data/cache" },
|
||||
{ "path": "../../libs/data/mongodb" },
|
||||
{ "path": "../../libs/data/postgres" },
|
||||
{ "path": "../../libs/data/questdb" },
|
||||
{ "path": "../../libs/services/queue" },
|
||||
{ "path": "../../libs/services/shutdown" },
|
||||
{ "path": "../../libs/utils" },
|
||||
{ "path": "../../../libs/core/types" },
|
||||
{ "path": "../../../libs/core/config" },
|
||||
{ "path": "../../../libs/core/logger" },
|
||||
{ "path": "../../../libs/core/di" },
|
||||
{ "path": "../../../libs/core/handlers" },
|
||||
{ "path": "../../../libs/core/cache" },
|
||||
{ "path": "../../../libs/data/mongodb" },
|
||||
{ "path": "../../../libs/data/postgres" },
|
||||
{ "path": "../../../libs/data/questdb" },
|
||||
{ "path": "../../../libs/core/queue" },
|
||||
{ "path": "../../../libs/core/shutdown" },
|
||||
{ "path": "../../../libs/utils" },
|
||||
{ "path": "../config" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.app.json",
|
||||
"extends": "../../../tsconfig.app.json",
|
||||
"references": [
|
||||
{ "path": "../../libs/core/types" },
|
||||
{ "path": "../../libs/core/config" },
|
||||
{ "path": "../../libs/core/logger" },
|
||||
{ "path": "../../libs/data/cache" },
|
||||
{ "path": "../../libs/services/queue" },
|
||||
{ "path": "../../libs/data/mongodb" },
|
||||
{ "path": "../../libs/data/postgres" },
|
||||
{ "path": "../../libs/data/questdb" },
|
||||
{ "path": "../../libs/services/shutdown" }
|
||||
{ "path": "../../../libs/core/types" },
|
||||
{ "path": "../../../libs/core/config" },
|
||||
{ "path": "../../../libs/core/logger" },
|
||||
{ "path": "../../../libs/core/cache" },
|
||||
{ "path": "../../../libs/core/queue" },
|
||||
{ "path": "../../../libs/data/mongodb" },
|
||||
{ "path": "../../../libs/data/postgres" },
|
||||
{ "path": "../../../libs/data/questdb" },
|
||||
{ "path": "../../../libs/core/shutdown" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
25
apps/stock/web-api/src/types.ts
Normal file
25
apps/stock/web-api/src/types.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Web API Service Types
|
||||
* Defines required services for web API handlers
|
||||
*/
|
||||
|
||||
import type { ServiceTypes } from '@stock-bot/types';
|
||||
|
||||
/**
|
||||
* Services required by web API handlers
|
||||
* Makes specific services non-nullable since they're always enabled
|
||||
*/
|
||||
export type WebApiServices = ServiceTypes & {
|
||||
// Always required services
|
||||
logger: NonNullable<ServiceTypes['logger']>;
|
||||
mongodb: NonNullable<ServiceTypes['mongodb']>;
|
||||
postgres: NonNullable<ServiceTypes['postgres']>;
|
||||
cache: NonNullable<ServiceTypes['cache']>;
|
||||
queue: NonNullable<ServiceTypes['queue']>;
|
||||
queueManager: NonNullable<ServiceTypes['queueManager']>;
|
||||
// Optional services remain optional
|
||||
browser: ServiceTypes['browser'];
|
||||
proxy: ServiceTypes['proxy'];
|
||||
questdb: ServiceTypes['questdb'];
|
||||
globalCache: ServiceTypes['globalCache'];
|
||||
};
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.app.json",
|
||||
"extends": "../../../tsconfig.app.json",
|
||||
"references": [
|
||||
{ "path": "../../libs/core/types" },
|
||||
{ "path": "../../libs/core/config" },
|
||||
{ "path": "../../libs/core/logger" },
|
||||
{ "path": "../../libs/data/cache" },
|
||||
{ "path": "../../libs/services/queue" },
|
||||
{ "path": "../../libs/data/mongodb" },
|
||||
{ "path": "../../libs/data/postgres" },
|
||||
{ "path": "../../libs/data/questdb" },
|
||||
{ "path": "../../libs/services/shutdown" }
|
||||
{ "path": "../../../libs/core/types" },
|
||||
{ "path": "../../../libs/core/config" },
|
||||
{ "path": "../../../libs/core/logger" },
|
||||
{ "path": "../../../libs/core/cache" },
|
||||
{ "path": "../../../libs/core/queue" },
|
||||
{ "path": "../../../libs/data/mongodb" },
|
||||
{ "path": "../../../libs/data/postgres" },
|
||||
{ "path": "../../../libs/data/questdb" },
|
||||
{ "path": "../../../libs/core/shutdown" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,41 +40,41 @@ export interface JobScheduleOptions {
|
|||
* Abstract base class for all handlers with improved DI
|
||||
* Provides common functionality and structure for queue/event operations
|
||||
*/
|
||||
export abstract class BaseHandler implements IHandler {
|
||||
export abstract class BaseHandler<TServices extends ServiceTypes = ServiceTypes> implements IHandler {
|
||||
// Direct service properties - flattened for cleaner access with proper types
|
||||
readonly logger: ServiceTypes['logger'];
|
||||
readonly cache: ServiceTypes['cache'];
|
||||
readonly globalCache: ServiceTypes['globalCache'];
|
||||
readonly queueManager: ServiceTypes['queueManager'];
|
||||
readonly queue: ServiceTypes['queue']; // Specific queue for this handler
|
||||
readonly proxy: ServiceTypes['proxy'];
|
||||
readonly browser: ServiceTypes['browser'];
|
||||
readonly mongodb: ServiceTypes['mongodb'];
|
||||
readonly postgres: ServiceTypes['postgres'];
|
||||
readonly questdb: ServiceTypes['questdb'];
|
||||
readonly logger: TServices['logger'];
|
||||
readonly cache: TServices['cache'];
|
||||
readonly globalCache: TServices['globalCache'];
|
||||
readonly queueManager: TServices['queueManager'];
|
||||
readonly queue!: TServices['queue']; // Specific queue for this handler - initialized if queueManager exists
|
||||
readonly proxy: TServices['proxy'];
|
||||
readonly browser: TServices['browser'];
|
||||
readonly mongodb: TServices['mongodb'];
|
||||
readonly postgres: TServices['postgres'];
|
||||
readonly questdb: TServices['questdb'];
|
||||
|
||||
private handlerName: string;
|
||||
|
||||
constructor(services: IServiceContainer, handlerName?: string) {
|
||||
constructor(services: TServices, handlerName?: string) {
|
||||
// Read handler name from decorator first, then fallback to parameter or class name
|
||||
const constructor = this.constructor as any;
|
||||
this.handlerName =
|
||||
constructor.__handlerName || handlerName || this.constructor.name.toLowerCase();
|
||||
|
||||
// Flatten all services onto the handler instance
|
||||
this.logger = getLogger(this.constructor.name);
|
||||
this.cache = services.cache;
|
||||
this.globalCache = services.globalCache;
|
||||
this.queueManager = services.queueManager;
|
||||
this.proxy = services.proxy;
|
||||
this.browser = services.browser;
|
||||
this.mongodb = services.mongodb;
|
||||
this.postgres = services.postgres;
|
||||
this.questdb = services.questdb;
|
||||
this.logger = getLogger(this.constructor.name) as TServices['logger'];
|
||||
this.cache = services.cache as TServices['cache'];
|
||||
this.globalCache = services.globalCache as TServices['globalCache'];
|
||||
this.queueManager = services.queueManager as TServices['queueManager'];
|
||||
this.proxy = services.proxy as TServices['proxy'];
|
||||
this.browser = services.browser as TServices['browser'];
|
||||
this.mongodb = services.mongodb as TServices['mongodb'];
|
||||
this.postgres = services.postgres as TServices['postgres'];
|
||||
this.questdb = services.questdb as TServices['questdb'];
|
||||
|
||||
// Get the specific queue for this handler
|
||||
if (this.queueManager) {
|
||||
this.queue = this.queueManager.getQueue(this.handlerName);
|
||||
this.queue = this.queueManager.getQueue(this.handlerName) as TServices['queue'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
"composite": true,
|
||||
"incremental": true,
|
||||
"types": ["bun-types"],
|
||||
// Modern TC39 Stage 3 decorators (TypeScript 5+ default)
|
||||
"experimentalDecorators": false,
|
||||
// Use legacy decorators for compatibility with the handler system
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
// Suppress decorator-related type checking issues due to Bun's hybrid implementation
|
||||
"skipLibCheck": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue