removed old di fully and replaced with awilix

This commit is contained in:
Boki 2025-06-22 13:01:12 -04:00
parent d8ae0cb3c5
commit c6c55e2979
9 changed files with 200 additions and 747 deletions

View file

@ -6,59 +6,89 @@
import { Browser } from '@stock-bot/browser';
import { createCache, type CacheProvider } from '@stock-bot/cache';
import type { IServiceContainer } from '@stock-bot/handlers';
import { getLogger } from '@stock-bot/logger';
import { getLogger, type Logger } from '@stock-bot/logger';
import { MongoDBClient } from '@stock-bot/mongodb';
import { createPostgreSQLClient } from '@stock-bot/postgres';
import { createPostgreSQLClient, type PostgreSQLClient } from '@stock-bot/postgres';
import { ProxyManager } from '@stock-bot/proxy';
import { createQuestDBClient } from '@stock-bot/questdb';
import { createQuestDBClient, type QuestDBClient } from '@stock-bot/questdb';
import { type QueueManager } from '@stock-bot/queue';
import { asFunction, asValue, createContainer, InjectionMode, type AwilixContainer } from 'awilix';
import { z } from 'zod';
// Configuration types
export interface AppConfig {
redis: {
enabled?: boolean;
host: string;
port: number;
password?: string;
username?: string;
db?: number;
};
mongodb: {
enabled?: boolean;
uri: string;
database: string;
};
postgres: {
enabled?: boolean;
host: string;
port: number;
database: string;
user: string;
password: string;
};
questdb?: {
enabled?: boolean;
host: string;
httpPort?: number;
pgPort?: number;
influxPort?: number;
database?: string;
};
proxy?: {
cachePrefix?: string;
ttl?: number;
};
browser?: {
headless?: boolean;
timeout?: number;
};
// Configuration schema with validation
const appConfigSchema = z.object({
redis: z.object({
enabled: z.boolean().optional(),
host: z.string(),
port: z.number(),
password: z.string().optional(),
username: z.string().optional(),
db: z.number().optional(),
}),
mongodb: z.object({
enabled: z.boolean().optional(),
uri: z.string(),
database: z.string(),
}),
postgres: z.object({
enabled: z.boolean().optional(),
host: z.string(),
port: z.number(),
database: z.string(),
user: z.string(),
password: z.string(),
}),
questdb: z.object({
enabled: z.boolean().optional(),
host: z.string(),
httpPort: z.number().optional(),
pgPort: z.number().optional(),
influxPort: z.number().optional(),
database: z.string().optional(),
}).optional(),
proxy: z.object({
cachePrefix: z.string().optional(),
ttl: z.number().optional(),
}).optional(),
browser: z.object({
headless: z.boolean().optional(),
timeout: z.number().optional(),
}).optional(),
});
export type AppConfig = z.infer<typeof appConfigSchema>;
/**
* Service type definitions for type-safe resolution
*/
export interface ServiceDefinitions {
// Configuration
config: AppConfig;
logger: Logger;
// Core services
cache: CacheProvider | null;
proxyManager: ProxyManager | null;
browser: Browser;
queueManager: QueueManager | null;
// Database clients
mongoClient: MongoDBClient | null;
postgresClient: PostgreSQLClient | null;
questdbClient: QuestDBClient | null;
// Aggregate service container
serviceContainer: IServiceContainer;
}
/**
* Create and configure the DI container
* Create and configure the DI container with type safety
*/
export function createServiceContainer(config: AppConfig): AwilixContainer {
const container = createContainer({
export function createServiceContainer(rawConfig: unknown): AwilixContainer<ServiceDefinitions> {
// Validate configuration
const config = appConfigSchema.parse(rawConfig);
const container = createContainer<ServiceDefinitions>({
injectionMode: InjectionMode.PROXY,
});
@ -153,10 +183,22 @@ export function createServiceContainer(config: AppConfig): AwilixContainer {
registrations.questdbClient = asValue(null);
}
// Queue manager - placeholder
registrations.queueManager = asFunction(() => {
// TODO: Create queue manager when decoupled
return null;
// Queue manager - placeholder until decoupled from singleton
registrations.queueManager = asFunction(({ redisConfig, cache, logger }) => {
// Import dynamically to avoid circular dependency
const { QueueManager } = require('@stock-bot/queue');
// Check if already initialized (singleton pattern)
if (QueueManager.isInitialized()) {
return QueueManager.getInstance();
}
// Initialize if not already done
return QueueManager.initialize({
redis: { host: redisConfig.host, port: redisConfig.port, db: redisConfig.db },
enableScheduledJobs: true,
delayWorkerStart: true // We'll start workers manually
});
}).singleton();
// Browser automation
@ -247,19 +289,6 @@ export async function initializeServices(container: AwilixContainer): Promise<vo
}
}
// Type definitions for container resolution
export interface ServiceCradle {
config: AppConfig;
logger: any;
cache: CacheProvider;
proxyManager: ProxyManager;
browser: any;
mongoClient: any;
postgresClient: any;
questdbClient: any;
queueManager: any;
serviceContainer: IServiceContainer;
}
// Export typed container
export type ServiceContainer = AwilixContainer<ServiceCradle>;
export type ServiceContainer = AwilixContainer<ServiceDefinitions>;
export type ServiceCradle = ServiceDefinitions;