fixed format issues

This commit is contained in:
Boki 2025-06-26 16:12:27 -04:00
parent a700818a06
commit 08f713d98b
55 changed files with 5680 additions and 5533 deletions

View file

@ -1,71 +1,76 @@
import { describe, it, expect } from 'bun:test';
import type { ServiceDefinitions, ServiceContainer, ServiceCradle, ServiceContainerOptions } from '../src/awilix-container';
describe('Awilix Container Types', () => {
it('should export ServiceDefinitions interface', () => {
// Type test - if this compiles, the type exists
const testDefinitions: Partial<ServiceDefinitions> = {
config: {} as any,
logger: {} as any,
cache: null,
proxyManager: null,
browser: {} as any,
queueManager: null,
mongoClient: null,
postgresClient: null,
questdbClient: null,
serviceContainer: {} as any,
};
expect(testDefinitions).toBeDefined();
});
it('should export ServiceContainer type', () => {
// Type test - if this compiles, the type exists
const testContainer: ServiceContainer | null = null;
expect(testContainer).toBeNull();
});
it('should export ServiceCradle type', () => {
// Type test - if this compiles, the type exists
const testCradle: Partial<ServiceCradle> = {
config: {} as any,
logger: {} as any,
};
expect(testCradle).toBeDefined();
});
it('should export ServiceContainerOptions interface', () => {
// Type test - if this compiles, the type exists
const testOptions: ServiceContainerOptions = {
enableQuestDB: true,
enableMongoDB: true,
enablePostgres: true,
enableCache: true,
enableQueue: true,
enableBrowser: true,
enableProxy: true,
};
expect(testOptions).toBeDefined();
expect(testOptions.enableQuestDB).toBe(true);
expect(testOptions.enableMongoDB).toBe(true);
expect(testOptions.enablePostgres).toBe(true);
expect(testOptions.enableCache).toBe(true);
expect(testOptions.enableQueue).toBe(true);
expect(testOptions.enableBrowser).toBe(true);
expect(testOptions.enableProxy).toBe(true);
});
it('should allow partial ServiceContainerOptions', () => {
const partialOptions: ServiceContainerOptions = {
enableCache: true,
enableQueue: false,
};
expect(partialOptions.enableCache).toBe(true);
expect(partialOptions.enableQueue).toBe(false);
expect(partialOptions.enableQuestDB).toBeUndefined();
});
});
import { describe, expect, it } from 'bun:test';
import type {
ServiceContainer,
ServiceContainerOptions,
ServiceCradle,
ServiceDefinitions,
} from '../src/awilix-container';
describe('Awilix Container Types', () => {
it('should export ServiceDefinitions interface', () => {
// Type test - if this compiles, the type exists
const testDefinitions: Partial<ServiceDefinitions> = {
config: {} as any,
logger: {} as any,
cache: null,
proxyManager: null,
browser: {} as any,
queueManager: null,
mongoClient: null,
postgresClient: null,
questdbClient: null,
serviceContainer: {} as any,
};
expect(testDefinitions).toBeDefined();
});
it('should export ServiceContainer type', () => {
// Type test - if this compiles, the type exists
const testContainer: ServiceContainer | null = null;
expect(testContainer).toBeNull();
});
it('should export ServiceCradle type', () => {
// Type test - if this compiles, the type exists
const testCradle: Partial<ServiceCradle> = {
config: {} as any,
logger: {} as any,
};
expect(testCradle).toBeDefined();
});
it('should export ServiceContainerOptions interface', () => {
// Type test - if this compiles, the type exists
const testOptions: ServiceContainerOptions = {
enableQuestDB: true,
enableMongoDB: true,
enablePostgres: true,
enableCache: true,
enableQueue: true,
enableBrowser: true,
enableProxy: true,
};
expect(testOptions).toBeDefined();
expect(testOptions.enableQuestDB).toBe(true);
expect(testOptions.enableMongoDB).toBe(true);
expect(testOptions.enablePostgres).toBe(true);
expect(testOptions.enableCache).toBe(true);
expect(testOptions.enableQueue).toBe(true);
expect(testOptions.enableBrowser).toBe(true);
expect(testOptions.enableProxy).toBe(true);
});
it('should allow partial ServiceContainerOptions', () => {
const partialOptions: ServiceContainerOptions = {
enableCache: true,
enableQueue: false,
};
expect(partialOptions.enableCache).toBe(true);
expect(partialOptions.enableQueue).toBe(false);
expect(partialOptions.enableQuestDB).toBeUndefined();
});
});

View file

@ -31,10 +31,18 @@ mock.module('@stock-bot/config', () => ({
}
// Copy flat configs to nested if they exist
if (result.redis) {result.database.dragonfly = result.redis;}
if (result.mongodb) {result.database.mongodb = result.mongodb;}
if (result.postgres) {result.database.postgres = result.postgres;}
if (result.questdb) {result.database.questdb = result.questdb;}
if (result.redis) {
result.database.dragonfly = result.redis;
}
if (result.mongodb) {
result.database.mongodb = result.mongodb;
}
if (result.postgres) {
result.database.postgres = result.postgres;
}
if (result.questdb) {
result.database.questdb = result.questdb;
}
return result;
},

View file

@ -1,52 +1,52 @@
import { describe, it, expect } from 'bun:test';
import * as diExports from '../src/index';
describe('DI Package Exports', () => {
it('should export OperationContext', () => {
expect(diExports.OperationContext).toBeDefined();
});
it('should export pool size calculator', () => {
expect(diExports.calculatePoolSize).toBeDefined();
expect(diExports.getServicePoolSize).toBeDefined();
expect(diExports.getHandlerPoolSize).toBeDefined();
});
it('should export ServiceContainerBuilder', () => {
expect(diExports.ServiceContainerBuilder).toBeDefined();
});
it('should export ServiceLifecycleManager', () => {
expect(diExports.ServiceLifecycleManager).toBeDefined();
});
it('should export ServiceApplication', () => {
expect(diExports.ServiceApplication).toBeDefined();
});
it('should export HandlerScanner', () => {
expect(diExports.HandlerScanner).toBeDefined();
});
it('should export factories', () => {
expect(diExports.CacheFactory).toBeDefined();
});
it('should export schemas', () => {
expect(diExports.appConfigSchema).toBeDefined();
expect(diExports.redisConfigSchema).toBeDefined();
expect(diExports.mongodbConfigSchema).toBeDefined();
expect(diExports.postgresConfigSchema).toBeDefined();
expect(diExports.questdbConfigSchema).toBeDefined();
expect(diExports.proxyConfigSchema).toBeDefined();
expect(diExports.browserConfigSchema).toBeDefined();
expect(diExports.queueConfigSchema).toBeDefined();
});
it('should export type definitions', () => {
// These are type exports - check that the awilix-container module is re-exported
expect(diExports).toBeDefined();
// The types AppConfig, ServiceCradle, etc. are TypeScript types and not runtime values
// We can't test them directly, but we've verified they're exported in the source
});
});
import { describe, expect, it } from 'bun:test';
import * as diExports from '../src/index';
describe('DI Package Exports', () => {
it('should export OperationContext', () => {
expect(diExports.OperationContext).toBeDefined();
});
it('should export pool size calculator', () => {
expect(diExports.calculatePoolSize).toBeDefined();
expect(diExports.getServicePoolSize).toBeDefined();
expect(diExports.getHandlerPoolSize).toBeDefined();
});
it('should export ServiceContainerBuilder', () => {
expect(diExports.ServiceContainerBuilder).toBeDefined();
});
it('should export ServiceLifecycleManager', () => {
expect(diExports.ServiceLifecycleManager).toBeDefined();
});
it('should export ServiceApplication', () => {
expect(diExports.ServiceApplication).toBeDefined();
});
it('should export HandlerScanner', () => {
expect(diExports.HandlerScanner).toBeDefined();
});
it('should export factories', () => {
expect(diExports.CacheFactory).toBeDefined();
});
it('should export schemas', () => {
expect(diExports.appConfigSchema).toBeDefined();
expect(diExports.redisConfigSchema).toBeDefined();
expect(diExports.mongodbConfigSchema).toBeDefined();
expect(diExports.postgresConfigSchema).toBeDefined();
expect(diExports.questdbConfigSchema).toBeDefined();
expect(diExports.proxyConfigSchema).toBeDefined();
expect(diExports.browserConfigSchema).toBeDefined();
expect(diExports.queueConfigSchema).toBeDefined();
});
it('should export type definitions', () => {
// These are type exports - check that the awilix-container module is re-exported
expect(diExports).toBeDefined();
// The types AppConfig, ServiceCradle, etc. are TypeScript types and not runtime values
// We can't test them directly, but we've verified they're exported in the source
});
});

View file

@ -107,14 +107,14 @@ describe('DI Registrations', () => {
describe('registerDatabaseServices', () => {
it('should register MongoDB when config exists', () => {
const container = createContainer();
// Mock MongoDB client
const mockMongoClient = {
connect: mock(() => Promise.resolve()),
disconnect: mock(() => Promise.resolve()),
getDb: mock(() => ({})),
};
// Mock the MongoDB factory
mock.module('@stock-bot/mongodb', () => ({
MongoDBClient: class {
@ -123,7 +123,7 @@ describe('DI Registrations', () => {
}
},
}));
const config = {
mongodb: {
enabled: true,
@ -139,14 +139,14 @@ describe('DI Registrations', () => {
it('should register PostgreSQL when config exists', () => {
const container = createContainer();
// Mock Postgres client
const mockPostgresClient = {
connect: mock(() => Promise.resolve()),
disconnect: mock(() => Promise.resolve()),
query: mock(() => Promise.resolve({ rows: [] })),
};
// Mock the Postgres factory
mock.module('@stock-bot/postgres', () => ({
PostgresClient: class {
@ -155,7 +155,7 @@ describe('DI Registrations', () => {
}
},
}));
const config = {
postgres: {
enabled: true,
@ -174,14 +174,14 @@ describe('DI Registrations', () => {
it('should register QuestDB when config exists', () => {
const container = createContainer();
// Mock QuestDB client
const mockQuestdbClient = {
connect: mock(() => Promise.resolve()),
disconnect: mock(() => Promise.resolve()),
query: mock(() => Promise.resolve({ data: [] })),
};
// Mock the QuestDB factory
mock.module('@stock-bot/questdb', () => ({
QuestDBClient: class {
@ -190,7 +190,7 @@ describe('DI Registrations', () => {
}
},
}));
const config = {
questdb: {
enabled: true,
@ -209,7 +209,7 @@ describe('DI Registrations', () => {
it('should not register disabled databases', () => {
const container = createContainer();
const config = {
mongodb: { enabled: false },
postgres: { enabled: false },
@ -222,7 +222,7 @@ describe('DI Registrations', () => {
expect(container.hasRegistration('mongoClient')).toBe(true);
expect(container.hasRegistration('postgresClient')).toBe(true);
expect(container.hasRegistration('questdbClient')).toBe(true);
// Verify they resolve to null
expect(container.resolve('mongoClient')).toBeNull();
expect(container.resolve('postgresClient')).toBeNull();
@ -233,17 +233,17 @@ describe('DI Registrations', () => {
describe('registerApplicationServices', () => {
it('should register browser when config exists', () => {
const container = createContainer();
// Mock browser factory
const mockBrowser = {
launch: mock(() => Promise.resolve()),
close: mock(() => Promise.resolve()),
};
mock.module('@stock-bot/browser', () => ({
createBrowser: () => mockBrowser,
}));
const config = {
browser: {
headless: true,
@ -258,16 +258,16 @@ describe('DI Registrations', () => {
it('should register proxy when config exists', () => {
const container = createContainer();
// Mock proxy factory
const mockProxy = {
getProxy: mock(() => 'http://proxy:8080'),
};
mock.module('@stock-bot/proxy', () => ({
createProxyManager: () => mockProxy,
}));
const config = {
proxy: {
enabled: true,
@ -282,7 +282,7 @@ describe('DI Registrations', () => {
it('should register queue manager when queue config exists', () => {
const container = createContainer();
// Mock dependencies
container.register({
cache: asValue({
@ -300,14 +300,14 @@ describe('DI Registrations', () => {
debug: mock(() => {}),
}),
});
// Mock queue manager
const mockQueueManager = {
getQueue: mock(() => ({})),
startAllWorkers: mock(() => {}),
shutdown: mock(() => Promise.resolve()),
};
mock.module('@stock-bot/queue', () => ({
QueueManager: class {
constructor() {
@ -315,7 +315,7 @@ describe('DI Registrations', () => {
}
},
}));
const config = {
service: {
name: 'test-service',
@ -335,7 +335,7 @@ describe('DI Registrations', () => {
it('should not register services when configs are missing', () => {
const container = createContainer();
const config = {} as any;
registerApplicationServices(container, config);
@ -343,12 +343,12 @@ describe('DI Registrations', () => {
expect(container.hasRegistration('browser')).toBe(true);
expect(container.hasRegistration('proxyManager')).toBe(true);
expect(container.hasRegistration('queueManager')).toBe(true);
// They should be registered as null
const browser = container.resolve('browser');
const proxyManager = container.resolve('proxyManager');
const queueManager = container.resolve('queueManager');
expect(browser).toBe(null);
expect(proxyManager).toBe(null);
expect(queueManager).toBe(null);
@ -358,7 +358,7 @@ describe('DI Registrations', () => {
describe('dependency resolution', () => {
it('should properly resolve cache dependencies', () => {
const container = createContainer();
const config = {
service: {
name: 'test-service',
@ -373,7 +373,7 @@ describe('DI Registrations', () => {
} as any;
registerCacheServices(container, config);
// Should have registered cache
expect(container.hasRegistration('cache')).toBe(true);
expect(container.hasRegistration('globalCache')).toBe(true);
@ -381,13 +381,13 @@ describe('DI Registrations', () => {
it('should handle circular dependencies gracefully', () => {
const container = createContainer();
// Register services with potential circular deps
container.register({
serviceA: asFunction(({ serviceB }) => ({ b: serviceB })).singleton(),
serviceB: asFunction(({ serviceA }) => ({ a: serviceA })).singleton(),
});
// This should throw or handle gracefully
expect(() => container.resolve('serviceA')).toThrow();
});
@ -396,7 +396,7 @@ describe('DI Registrations', () => {
describe('registration options', () => {
it('should register services as singletons', () => {
const container = createContainer();
const config = {
browser: {
headless: true,
@ -405,7 +405,7 @@ describe('DI Registrations', () => {
} as any;
registerApplicationServices(container, config);
// Check that browser was registered as singleton
const registration = container.getRegistration('browser');
expect(registration).toBeDefined();

View file

@ -1,7 +1,7 @@
import { describe, it, expect, beforeEach, afterEach, mock } from 'bun:test';
import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
import type { BaseAppConfig } from '@stock-bot/config';
import { ServiceApplication } from '../src/service-application';
import type { ServiceApplicationConfig, ServiceLifecycleHooks } from '../src/service-application';
import type { BaseAppConfig } from '@stock-bot/config';
// Mock logger module
const mockLogger = {
@ -18,7 +18,7 @@ mock.module('@stock-bot/logger', () => ({
shutdownLoggers: mock(() => Promise.resolve()),
}));
// Mock shutdown module
// Mock shutdown module
const mockShutdownInstance = {
onShutdown: mock(() => {}),
onShutdownHigh: mock(() => {}),
@ -89,7 +89,7 @@ describe.skip('ServiceApplication', () => {
mockShutdownInstance.registerAsync.mockReset();
mockShutdownInstance.handleTermination.mockReset();
mockShutdownInstance.executeCallbacks.mockReset();
// Clean up app if it exists
if (app) {
app.stop().catch(() => {});
@ -193,7 +193,6 @@ describe.skip('ServiceApplication', () => {
app = new ServiceApplication(configWithoutServiceName as any, serviceConfig);
expect(app).toBeDefined();
});
});
describe('start method', () => {
@ -228,7 +227,7 @@ describe.skip('ServiceApplication', () => {
const { Hono } = require('hono');
const routes = new Hono();
// Add a simple test route
routes.get('/test', (c) => c.json({ test: true }));
routes.get('/test', c => c.json({ test: true }));
return routes;
});
const mockHandlerInitializer = mock(() => Promise.resolve());
@ -240,12 +239,14 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig);
await app.start(mockContainerFactory, mockRouteFactory);
expect(mockContainerFactory).toHaveBeenCalledWith(expect.objectContaining({
service: expect.objectContaining({ serviceName: 'test-service' }),
}));
expect(mockContainerFactory).toHaveBeenCalledWith(
expect.objectContaining({
service: expect.objectContaining({ serviceName: 'test-service' }),
})
);
expect(mockRouteFactory).toHaveBeenCalledWith({ test: 'container' });
expect(mockLogger.info).toHaveBeenCalledWith('test-service service started on port 3000');
});
@ -257,13 +258,15 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig);
await app.start(mockContainerFactory, mockRouteFactory, mockHandlerInitializer);
expect(mockHandlerInitializer).toHaveBeenCalledWith(expect.objectContaining({
test: 'container',
_diContainer: mockContainer,
}));
expect(mockHandlerInitializer).toHaveBeenCalledWith(
expect.objectContaining({
test: 'container',
_diContainer: mockContainer,
})
);
expect(mockLogger.info).toHaveBeenCalledWith('Handlers initialized');
});
@ -280,7 +283,7 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig, hooks);
await app.start(mockContainerFactory, mockRouteFactory);
expect(hooks.onContainerReady).toHaveBeenCalledWith({ test: 'container' });
@ -299,8 +302,10 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig);
await expect(app.start(errorFactory, mockRouteFactory)).rejects.toThrow('Container creation failed');
await expect(app.start(errorFactory, mockRouteFactory)).rejects.toThrow(
'Container creation failed'
);
expect(mockLogger.error).toHaveBeenCalledWith('DETAILED ERROR:', expect.any(Error));
});
@ -311,17 +316,23 @@ describe.skip('ServiceApplication', () => {
};
const mockHandlerRegistry = {
getAllHandlersWithSchedule: () => new Map([
['testHandler', {
scheduledJobs: [{
operation: 'processData',
cronPattern: '0 * * * *',
priority: 5,
immediately: false,
payload: { test: true },
}],
}],
]),
getAllHandlersWithSchedule: () =>
new Map([
[
'testHandler',
{
scheduledJobs: [
{
operation: 'processData',
cronPattern: '0 * * * *',
priority: 5,
immediately: false,
payload: { test: true },
},
],
},
],
]),
getHandlerService: () => 'test-service',
getHandlerNames: () => ['testHandler'],
getOperation: () => ({ name: 'processData' }),
@ -339,9 +350,15 @@ describe.skip('ServiceApplication', () => {
const containerWithJobs = {
resolve: mock((name: string) => {
if (name === 'serviceContainer') {return { test: 'container' };}
if (name === 'handlerRegistry') {return mockHandlerRegistry;}
if (name === 'queueManager') {return mockQueueManager;}
if (name === 'serviceContainer') {
return { test: 'container' };
}
if (name === 'handlerRegistry') {
return mockHandlerRegistry;
}
if (name === 'queueManager') {
return mockQueueManager;
}
return null;
}),
};
@ -349,7 +366,7 @@ describe.skip('ServiceApplication', () => {
const jobContainerFactory = mock(async () => containerWithJobs);
app = new ServiceApplication(mockConfig, serviceConfig);
await app.start(jobContainerFactory, mockRouteFactory);
expect(mockQueueManager.getQueue).toHaveBeenCalledWith('testHandler', {
@ -359,7 +376,7 @@ describe.skip('ServiceApplication', () => {
'processData',
{ handler: 'testHandler', operation: 'processData', payload: { test: true } },
'0 * * * *',
expect.objectContaining({ priority: 5, repeat: { immediately: false } }),
expect.objectContaining({ priority: 5, repeat: { immediately: false } })
);
expect(mockQueueManager.startAllWorkers).toHaveBeenCalled();
expect(mockLogger.info).toHaveBeenCalledWith('Scheduled jobs created', { totalJobs: 1 });
@ -386,7 +403,7 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig);
await app.stop();
expect(mockShutdownInstance.shutdown).toHaveBeenCalled();
@ -401,7 +418,7 @@ describe.skip('ServiceApplication', () => {
};
app = new ServiceApplication(mockConfig, serviceConfig);
// Before start
expect(app.getServiceContainer()).toBeNull();
expect(app.getApp()).toBeNull();
@ -451,18 +468,30 @@ describe.skip('ServiceApplication', () => {
const mockContainer = {
resolve: mock((name: string) => {
if (name === 'serviceContainer') {return { test: 'container' };}
if (name === 'handlerRegistry') {return {
getAllHandlersWithSchedule: () => new Map(),
getHandlerNames: () => [],
};}
if (name === 'queueManager') {return {
shutdown: mock(() => Promise.resolve()),
startAllWorkers: mock(() => {}),
};}
if (name === 'mongoClient') {return { disconnect: mock(() => Promise.resolve()) };}
if (name === 'postgresClient') {return { disconnect: mock(() => Promise.resolve()) };}
if (name === 'questdbClient') {return { disconnect: mock(() => Promise.resolve()) };}
if (name === 'serviceContainer') {
return { test: 'container' };
}
if (name === 'handlerRegistry') {
return {
getAllHandlersWithSchedule: () => new Map(),
getHandlerNames: () => [],
};
}
if (name === 'queueManager') {
return {
shutdown: mock(() => Promise.resolve()),
startAllWorkers: mock(() => {}),
};
}
if (name === 'mongoClient') {
return { disconnect: mock(() => Promise.resolve()) };
}
if (name === 'postgresClient') {
return { disconnect: mock(() => Promise.resolve()) };
}
if (name === 'questdbClient') {
return { disconnect: mock(() => Promise.resolve()) };
}
return null;
}),
};
@ -486,7 +515,7 @@ describe.skip('ServiceApplication', () => {
await highHandlers[0][0]();
expect(mockContainer.resolve).toHaveBeenCalledWith('queueManager');
// Execute services shutdown handler
// Execute services shutdown handler
await mediumHandlers[0][0]();
expect(mockContainer.resolve).toHaveBeenCalledWith('mongoClient');
expect(mockContainer.resolve).toHaveBeenCalledWith('postgresClient');
@ -566,4 +595,4 @@ describe.skip('ServiceApplication', () => {
expect(response.status).toBe(404);
});
});
});
});

View file

@ -1,270 +1,270 @@
import { describe, it, expect } from 'bun:test';
import type {
GenericClientConfig,
ConnectionPoolConfig,
MongoDBPoolConfig,
PostgreSQLPoolConfig,
CachePoolConfig,
QueuePoolConfig,
ConnectionFactoryConfig,
ConnectionPool,
PoolMetrics,
ConnectionFactory,
} from '../src/types';
describe('DI Types', () => {
describe('GenericClientConfig', () => {
it('should allow any key-value pairs', () => {
const config: GenericClientConfig = {
host: 'localhost',
port: 5432,
username: 'test',
password: 'test',
customOption: true,
};
expect(config.host).toBe('localhost');
expect(config.port).toBe(5432);
expect(config.customOption).toBe(true);
});
});
describe('ConnectionPoolConfig', () => {
it('should have required and optional fields', () => {
const config: ConnectionPoolConfig = {
name: 'test-pool',
poolSize: 10,
minConnections: 2,
maxConnections: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
enableMetrics: true,
};
expect(config.name).toBe('test-pool');
expect(config.poolSize).toBe(10);
expect(config.enableMetrics).toBe(true);
});
it('should allow minimal configuration', () => {
const config: ConnectionPoolConfig = {
name: 'minimal-pool',
};
expect(config.name).toBe('minimal-pool');
expect(config.poolSize).toBeUndefined();
});
});
describe('Specific Pool Configs', () => {
it('should extend ConnectionPoolConfig for MongoDB', () => {
const config: MongoDBPoolConfig = {
name: 'mongo-pool',
poolSize: 5,
config: {
uri: 'mongodb://localhost:27017',
database: 'test',
},
};
expect(config.name).toBe('mongo-pool');
expect(config.config.uri).toBe('mongodb://localhost:27017');
});
it('should extend ConnectionPoolConfig for PostgreSQL', () => {
const config: PostgreSQLPoolConfig = {
name: 'postgres-pool',
config: {
host: 'localhost',
port: 5432,
database: 'test',
},
};
expect(config.name).toBe('postgres-pool');
expect(config.config.host).toBe('localhost');
});
it('should extend ConnectionPoolConfig for Cache', () => {
const config: CachePoolConfig = {
name: 'cache-pool',
config: {
host: 'localhost',
port: 6379,
},
};
expect(config.name).toBe('cache-pool');
expect(config.config.port).toBe(6379);
});
it('should extend ConnectionPoolConfig for Queue', () => {
const config: QueuePoolConfig = {
name: 'queue-pool',
config: {
redis: {
host: 'localhost',
port: 6379,
},
},
};
expect(config.name).toBe('queue-pool');
expect(config.config.redis.host).toBe('localhost');
});
});
describe('ConnectionFactoryConfig', () => {
it('should define factory configuration', () => {
const config: ConnectionFactoryConfig = {
service: 'test-service',
environment: 'development',
pools: {
mongodb: {
poolSize: 10,
},
postgres: {
maxConnections: 20,
},
cache: {
idleTimeoutMillis: 60000,
},
queue: {
enableMetrics: true,
},
},
};
expect(config.service).toBe('test-service');
expect(config.environment).toBe('development');
expect(config.pools?.mongodb?.poolSize).toBe(10);
expect(config.pools?.postgres?.maxConnections).toBe(20);
});
it('should allow minimal factory config', () => {
const config: ConnectionFactoryConfig = {
service: 'minimal-service',
environment: 'test',
};
expect(config.service).toBe('minimal-service');
expect(config.pools).toBeUndefined();
});
});
describe('ConnectionPool', () => {
it('should define connection pool interface', () => {
const mockPool: ConnectionPool<any> = {
name: 'test-pool',
client: { connected: true },
metrics: {
created: new Date(),
totalConnections: 10,
activeConnections: 5,
idleConnections: 5,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
};
expect(mockPool.name).toBe('test-pool');
expect(mockPool.client.connected).toBe(true);
expect(mockPool.metrics.totalConnections).toBe(10);
});
});
describe('PoolMetrics', () => {
it('should define pool metrics structure', () => {
const metrics: PoolMetrics = {
created: new Date('2024-01-01'),
totalConnections: 100,
activeConnections: 25,
idleConnections: 75,
waitingRequests: 2,
errors: 3,
};
expect(metrics.totalConnections).toBe(100);
expect(metrics.activeConnections).toBe(25);
expect(metrics.idleConnections).toBe(75);
expect(metrics.waitingRequests).toBe(2);
expect(metrics.errors).toBe(3);
});
});
describe('ConnectionFactory', () => {
it('should define connection factory interface', () => {
const mockFactory: ConnectionFactory = {
createMongoDB: async (config) => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createPostgreSQL: async (config) => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createCache: async (config) => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createQueue: async (config) => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
getPool: (type, name) => undefined,
listPools: () => [],
disposeAll: async () => {},
};
expect(mockFactory.createMongoDB).toBeDefined();
expect(mockFactory.createPostgreSQL).toBeDefined();
expect(mockFactory.createCache).toBeDefined();
expect(mockFactory.createQueue).toBeDefined();
expect(mockFactory.getPool).toBeDefined();
expect(mockFactory.listPools).toBeDefined();
expect(mockFactory.disposeAll).toBeDefined();
});
});
});
import { describe, expect, it } from 'bun:test';
import type {
CachePoolConfig,
ConnectionFactory,
ConnectionFactoryConfig,
ConnectionPool,
ConnectionPoolConfig,
GenericClientConfig,
MongoDBPoolConfig,
PoolMetrics,
PostgreSQLPoolConfig,
QueuePoolConfig,
} from '../src/types';
describe('DI Types', () => {
describe('GenericClientConfig', () => {
it('should allow any key-value pairs', () => {
const config: GenericClientConfig = {
host: 'localhost',
port: 5432,
username: 'test',
password: 'test',
customOption: true,
};
expect(config.host).toBe('localhost');
expect(config.port).toBe(5432);
expect(config.customOption).toBe(true);
});
});
describe('ConnectionPoolConfig', () => {
it('should have required and optional fields', () => {
const config: ConnectionPoolConfig = {
name: 'test-pool',
poolSize: 10,
minConnections: 2,
maxConnections: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
enableMetrics: true,
};
expect(config.name).toBe('test-pool');
expect(config.poolSize).toBe(10);
expect(config.enableMetrics).toBe(true);
});
it('should allow minimal configuration', () => {
const config: ConnectionPoolConfig = {
name: 'minimal-pool',
};
expect(config.name).toBe('minimal-pool');
expect(config.poolSize).toBeUndefined();
});
});
describe('Specific Pool Configs', () => {
it('should extend ConnectionPoolConfig for MongoDB', () => {
const config: MongoDBPoolConfig = {
name: 'mongo-pool',
poolSize: 5,
config: {
uri: 'mongodb://localhost:27017',
database: 'test',
},
};
expect(config.name).toBe('mongo-pool');
expect(config.config.uri).toBe('mongodb://localhost:27017');
});
it('should extend ConnectionPoolConfig for PostgreSQL', () => {
const config: PostgreSQLPoolConfig = {
name: 'postgres-pool',
config: {
host: 'localhost',
port: 5432,
database: 'test',
},
};
expect(config.name).toBe('postgres-pool');
expect(config.config.host).toBe('localhost');
});
it('should extend ConnectionPoolConfig for Cache', () => {
const config: CachePoolConfig = {
name: 'cache-pool',
config: {
host: 'localhost',
port: 6379,
},
};
expect(config.name).toBe('cache-pool');
expect(config.config.port).toBe(6379);
});
it('should extend ConnectionPoolConfig for Queue', () => {
const config: QueuePoolConfig = {
name: 'queue-pool',
config: {
redis: {
host: 'localhost',
port: 6379,
},
},
};
expect(config.name).toBe('queue-pool');
expect(config.config.redis.host).toBe('localhost');
});
});
describe('ConnectionFactoryConfig', () => {
it('should define factory configuration', () => {
const config: ConnectionFactoryConfig = {
service: 'test-service',
environment: 'development',
pools: {
mongodb: {
poolSize: 10,
},
postgres: {
maxConnections: 20,
},
cache: {
idleTimeoutMillis: 60000,
},
queue: {
enableMetrics: true,
},
},
};
expect(config.service).toBe('test-service');
expect(config.environment).toBe('development');
expect(config.pools?.mongodb?.poolSize).toBe(10);
expect(config.pools?.postgres?.maxConnections).toBe(20);
});
it('should allow minimal factory config', () => {
const config: ConnectionFactoryConfig = {
service: 'minimal-service',
environment: 'test',
};
expect(config.service).toBe('minimal-service');
expect(config.pools).toBeUndefined();
});
});
describe('ConnectionPool', () => {
it('should define connection pool interface', () => {
const mockPool: ConnectionPool<any> = {
name: 'test-pool',
client: { connected: true },
metrics: {
created: new Date(),
totalConnections: 10,
activeConnections: 5,
idleConnections: 5,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
};
expect(mockPool.name).toBe('test-pool');
expect(mockPool.client.connected).toBe(true);
expect(mockPool.metrics.totalConnections).toBe(10);
});
});
describe('PoolMetrics', () => {
it('should define pool metrics structure', () => {
const metrics: PoolMetrics = {
created: new Date('2024-01-01'),
totalConnections: 100,
activeConnections: 25,
idleConnections: 75,
waitingRequests: 2,
errors: 3,
};
expect(metrics.totalConnections).toBe(100);
expect(metrics.activeConnections).toBe(25);
expect(metrics.idleConnections).toBe(75);
expect(metrics.waitingRequests).toBe(2);
expect(metrics.errors).toBe(3);
});
});
describe('ConnectionFactory', () => {
it('should define connection factory interface', () => {
const mockFactory: ConnectionFactory = {
createMongoDB: async config => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createPostgreSQL: async config => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createCache: async config => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
createQueue: async config => ({
name: config.name,
client: {},
metrics: {
created: new Date(),
totalConnections: 0,
activeConnections: 0,
idleConnections: 0,
waitingRequests: 0,
errors: 0,
},
health: async () => true,
dispose: async () => {},
}),
getPool: (type, name) => undefined,
listPools: () => [],
disposeAll: async () => {},
};
expect(mockFactory.createMongoDB).toBeDefined();
expect(mockFactory.createPostgreSQL).toBeDefined();
expect(mockFactory.createCache).toBeDefined();
expect(mockFactory.createQueue).toBeDefined();
expect(mockFactory.getPool).toBeDefined();
expect(mockFactory.listPools).toBeDefined();
expect(mockFactory.disposeAll).toBeDefined();
});
});
});