@sentzunhat/zacatl
Version:
A modular, high-performance TypeScript microservice framework for Node.js, featuring layered architecture, dependency injection, and robust validation for building scalable APIs and distributed systems.
130 lines • 6.03 kB
JavaScript
import { getContainer } from '../dependency-injection/index.js';
import { InternalServerError } from '../error/index.js';
import { configureI18nNode } from '../localization/index.js';
import { Layers } from './layers/index.js';
import { Platforms } from './platforms/platforms.js';
import { DatabaseVendor } from './platforms/server/database/port.js';
import { ServiceType } from './types/index.js';
export class Service {
config;
platforms;
constructor(config) {
configureI18nNode(config.localization);
this.validateConfig(config);
this.config = config;
const { layers, platforms, run } = config;
if (platforms?.server?.databases != null) {
for (const dbConfig of platforms.server.databases) {
if (dbConfig.vendor === DatabaseVendor.MONGOOSE && dbConfig.instance != null) {
getContainer().register(dbConfig.instance.constructor, {
useValue: dbConfig.instance,
});
}
else if (dbConfig.vendor === DatabaseVendor.SEQUELIZE && dbConfig.instance != null) {
getContainer().register(dbConfig.instance.constructor, {
useValue: dbConfig.instance,
});
}
}
}
if (layers != null) {
new Layers(layers);
}
if (platforms != null) {
this.platforms = new Platforms(platforms);
}
if (run?.auto === true) {
this.start().catch((err) => {
throw new InternalServerError({
message: 'Failed to start service automatically',
reason: 'Service auto-start encountered an error during initialization',
component: 'Service',
operation: 'constructor',
error: err instanceof Error ? err : undefined,
});
});
}
}
validateConfig(config) {
const { type, layers, platforms } = config;
const configType = type ?? undefined;
if (configType == null) {
throw new InternalServerError({
message: "Service configuration must specify a 'type' field",
reason: 'Missing service type',
component: 'Service',
operation: 'constructor',
});
}
switch (configType) {
case ServiceType.SERVER:
if (platforms?.server == null) {
throw new InternalServerError({
message: "ServiceType.SERVER requires 'platforms.server' configuration",
reason: 'Server platform configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
if (layers?.application == null || layers.application.entryPoints?.rest == null) {
throw new InternalServerError({
message: "ServiceType.SERVER requires 'layers.application.entryPoints.rest' configuration",
reason: 'REST entry points configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
break;
case ServiceType.CLI:
if (platforms?.cli == null) {
throw new InternalServerError({
message: "ServiceType.CLI requires 'platforms.cli' configuration",
reason: 'CLI platform configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
if (layers?.application == null || layers.application.entryPoints?.cli == null) {
throw new InternalServerError({
message: "ServiceType.CLI requires 'layers.application.entryPoints.cli' configuration",
reason: 'CLI entry points configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
break;
case ServiceType.DESKTOP:
if (platforms?.desktop == null) {
throw new InternalServerError({
message: "ServiceType.DESKTOP requires 'platforms.desktop' configuration",
reason: 'Desktop platform configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
if (layers?.application == null || layers.application.entryPoints?.ipc == null) {
throw new InternalServerError({
message: "ServiceType.DESKTOP requires 'layers.application.entryPoints.ipc' configuration",
reason: 'IPC entry points configuration is missing',
component: 'Service',
operation: 'validateConfig',
metadata: { serviceType: configType },
});
}
break;
}
}
async start(options) {
if (this.config.layers?.application?.entryPoints) {
await this.platforms?.registerEntrypoints(this.config.layers?.application?.entryPoints);
await this.platforms?.start(options);
}
}
}
export { ServiceType };
//# sourceMappingURL=service.js.map