@emmett-community/emmett-google-services-bootstrap 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.cjs +9 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -106,6 +106,12 @@ const config: ServiceBootstrapConfig = {
|
|
|
106
106
|
topicPrefix: 'user-service',
|
|
107
107
|
autoCreateResources: true,
|
|
108
108
|
},
|
|
109
|
+
eventStore: {
|
|
110
|
+
collections: {
|
|
111
|
+
streams: 'user-service-streams',
|
|
112
|
+
counters: '_user-service-counters',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
109
115
|
projections: [],
|
|
110
116
|
observability: {
|
|
111
117
|
createLogger: true,
|
|
@@ -117,6 +123,11 @@ const config: ServiceBootstrapConfig = {
|
|
|
117
123
|
};
|
|
118
124
|
```
|
|
119
125
|
|
|
126
|
+
### Event store collection names
|
|
127
|
+
|
|
128
|
+
- `eventStore.collections.streams`: Firestore collection that stores stream metadata (defaults to `"streams"`).
|
|
129
|
+
- `eventStore.collections.counters`: Firestore collection for shared counters (defaults to `"_counters"`).
|
|
130
|
+
|
|
120
131
|
## API
|
|
121
132
|
|
|
122
133
|
### ServiceBootstrap
|
package/dist/index.cjs
CHANGED
|
@@ -248,9 +248,12 @@ var PubSubInitializer = class {
|
|
|
248
248
|
var import_emmett_google_firestore = require("@emmett-community/emmett-google-firestore");
|
|
249
249
|
var import_emmett_google_realtime_db = require("@emmett-community/emmett-google-realtime-db");
|
|
250
250
|
var createEventStore = (options) => {
|
|
251
|
-
const { firestore, database, projections, logger } = options;
|
|
251
|
+
const { firestore, database, projections, logger, collections } = options;
|
|
252
252
|
const observability = logger ? { logger } : void 0;
|
|
253
|
-
const baseEventStore = (0, import_emmett_google_firestore.getFirestoreEventStore)(firestore, {
|
|
253
|
+
const baseEventStore = (0, import_emmett_google_firestore.getFirestoreEventStore)(firestore, {
|
|
254
|
+
observability,
|
|
255
|
+
collections
|
|
256
|
+
});
|
|
254
257
|
if (projections && projections.length > 0) {
|
|
255
258
|
return (0, import_emmett_google_realtime_db.wireRealtimeDBProjections)({
|
|
256
259
|
eventStore: baseEventStore,
|
|
@@ -677,6 +680,7 @@ var ServiceBootstrap = class {
|
|
|
677
680
|
firestore,
|
|
678
681
|
database,
|
|
679
682
|
projections: resolvedConfig.projections,
|
|
683
|
+
collections: resolvedConfig.eventStore.collections,
|
|
680
684
|
logger
|
|
681
685
|
});
|
|
682
686
|
const messageBus = resolvedConfig._testOverrides?.messageBus ?? (0, import_emmett_google_pubsub.getPubSubMessageBus)({
|
|
@@ -846,6 +850,9 @@ var ServiceBootstrap = class {
|
|
|
846
850
|
exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,
|
|
847
851
|
exitFn: this.config.shutdown?.exitFn
|
|
848
852
|
},
|
|
853
|
+
eventStore: {
|
|
854
|
+
collections: this.config.eventStore?.collections
|
|
855
|
+
},
|
|
849
856
|
_testOverrides: this.config._testOverrides
|
|
850
857
|
};
|
|
851
858
|
return this.resolvedConfig;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/bootstrap/ServiceBootstrap.ts","../src/firebase/FirebaseInitializer.ts","../src/pubsub/PubSubInitializer.ts","../src/eventstore/EventStoreFactory.ts","../src/lifecycle/DependencyChecker.ts","../src/lifecycle/GracefulShutdown.ts","../src/lifecycle/SignalHandlers.ts"],"sourcesContent":["export * from './bootstrap';\nexport * from './types';\nexport * from './firebase';\nexport * from './pubsub';\nexport * from './lifecycle';\nexport * from './eventstore';\nexport { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';\nexport {\n ApiE2ESpecification,\n ApiSpecification,\n createFirebaseAuthSecurityHandlers,\n existingStream,\n expectNewEvents,\n expectResponse,\n NoContent,\n OK,\n on,\n type ImportedHandlerModules,\n type TestRequest,\n} from '@emmett-community/emmett-expressjs-with-openapi';\n","import path from 'node:path';\nimport type { Application } from 'express';\nimport { createLogger } from '@emmett-community/emmett-observability';\nimport {\n createOpenApiValidatorOptions,\n getApplication,\n startAPI,\n type ApplicationOptions,\n type ImportedHandlerModules,\n type OpenApiValidatorOptions,\n} from '@emmett-community/emmett-expressjs-with-openapi';\nimport {\n getPubSubMessageBus,\n type Logger as PubSubLogger,\n} from '@emmett-community/emmett-google-pubsub';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { PubSub } from '@google-cloud/pubsub';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport { FirebaseInitializer } from '../firebase/FirebaseInitializer';\nimport { PubSubInitializer } from '../pubsub/PubSubInitializer';\nimport { createEventStore } from '../eventstore/EventStoreFactory';\nimport {\n DependencyChecker,\n type DependencyCheckSummary,\n} from '../lifecycle/DependencyChecker';\nimport {\n GracefulShutdown,\n type GracefulShutdownResult,\n} from '../lifecycle/GracefulShutdown';\nimport { registerSignalHandlers } from '../lifecycle/SignalHandlers';\nimport type {\n DependencyCheck,\n Logger as BootstrapLogger,\n MessageBusWithLifecycle,\n ResolvedServiceBootstrapConfig,\n ServiceBootstrapConfig,\n} from '../types/config';\n\n/**\n * Runtime context produced by ServiceBootstrap.\n */\nexport type ServiceBootstrapContext = {\n serviceName: string;\n firebase: {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n };\n firestore: Firestore;\n database: Database;\n auth: Auth;\n pubsub: PubSub;\n eventStore: EventStore;\n messageBus: MessageBusWithLifecycle;\n logger?: BootstrapLogger;\n getCurrentTime: () => Date;\n config: ResolvedServiceBootstrapConfig;\n};\n\n/**\n * Error thrown when required dependencies fail health checks.\n */\nexport class DependencyUnavailableError extends Error {\n readonly summary: DependencyCheckSummary;\n\n constructor(summary: DependencyCheckSummary) {\n const failed = summary.results\n .filter((result) => result.required && !result.ok)\n .map((result) => result.name)\n .join(', ');\n\n super(`Dependency check failed: ${failed}`);\n this.name = 'DependencyUnavailableError';\n this.summary = summary;\n }\n}\n\nexport type CreateAppOptions = {\n openApiPath: string;\n handlersPath: string;\n initializeHandlers: (handlers?: ImportedHandlerModules) => void | Promise<void>;\n openApiOptions?: Partial<\n Omit<\n OpenApiValidatorOptions,\n 'apiSpec' | 'operationHandlers' | 'initializeHandlers'\n >\n >;\n appOptions?: Omit<ApplicationOptions, 'openApiValidator' | 'observability'>;\n};\n\nexport type StartApiOptions = Omit<CreateAppOptions, 'initializeHandlers'> & {\n initializeHandlers: (\n handlers: ImportedHandlerModules | undefined,\n ctx: ServiceBootstrapContext,\n ) => void | Promise<void>;\n port?: number;\n registerSignalHandlers?: boolean;\n beforeStart?: (ctx: ServiceBootstrapContext) => void | Promise<void>;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst createPubSubLogger = (\n logger?: BootstrapLogger,\n): PubSubLogger | undefined => {\n if (!logger) return undefined;\n // Adapter: PubSub logger expects (msg, data), canonical logger uses (context, msg).\n const canonicalLogger = logger as any;\n return {\n debug: (msg, data) => canonicalLogger.debug(normalizeContext(data), msg),\n info: (msg, data) => canonicalLogger.info(normalizeContext(data), msg),\n warn: (msg, data) => canonicalLogger.warn(normalizeContext(data), msg),\n error: (msg, error) =>\n canonicalLogger.error(normalizeErrorContext(error), msg),\n };\n};\n\nconst resolvePath = (inputPath: string): string => {\n return path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(process.cwd(), inputPath);\n};\n\n/**\n * Orchestrates Firebase, PubSub, event store, and lifecycle utilities.\n */\nexport class ServiceBootstrap {\n private readonly config: ServiceBootstrapConfig;\n private resolvedConfig?: ResolvedServiceBootstrapConfig;\n private logger?: BootstrapLogger;\n private context?: ServiceBootstrapContext;\n private dependencyChecker?: DependencyChecker;\n private shutdownManager?: GracefulShutdown;\n\n constructor(config: ServiceBootstrapConfig) {\n this.config = config;\n }\n\n /**\n * Resolve configuration with defaults and environment variables.\n */\n getConfig(): ResolvedServiceBootstrapConfig {\n return this.resolveConfig();\n }\n\n /**\n * Return the initialized context if available.\n */\n getContext(): ServiceBootstrapContext | undefined {\n return this.context;\n }\n\n /**\n * Register process signal handlers that trigger shutdown.\n */\n registerSignalHandlers(options?: {\n signals?: NodeJS.Signals[];\n exitCode?: number;\n }): () => void {\n return registerSignalHandlers({\n shutdown: async (reason, exitCode) => {\n await this.shutdown(reason, exitCode);\n },\n signals: options?.signals,\n logger: this.getLogger(),\n exitCode: options?.exitCode,\n });\n }\n\n /**\n * Create an Express app using emmett-expressjs-with-openapi defaults.\n */\n async createApp(options: CreateAppOptions) {\n const logger = this.getLogger();\n const openApiValidator = createOpenApiValidatorOptions(\n resolvePath(options.openApiPath),\n {\n ...options.openApiOptions,\n operationHandlers: resolvePath(options.handlersPath),\n initializeHandlers: options.initializeHandlers,\n },\n );\n\n return getApplication({\n ...(options.appOptions ?? {}),\n openApiValidator,\n observability: logger ? { logger } : undefined,\n });\n }\n\n /**\n * Initialize, run dependency checks, create the app, and start the HTTP server.\n */\n async startApi(options: StartApiOptions): Promise<{\n app: Application;\n server: ReturnType<typeof startAPI>;\n context: ServiceBootstrapContext;\n }> {\n const {\n port,\n registerSignalHandlers,\n beforeStart,\n initializeHandlers,\n ...createAppOptions\n } = options;\n\n const logger = this.getLogger();\n\n try {\n const ctx = await this.initialize();\n\n if (beforeStart) {\n await beforeStart(ctx);\n }\n\n if (registerSignalHandlers !== false) {\n this.registerSignalHandlers();\n }\n\n await this.start();\n\n const app = await this.createApp({\n ...createAppOptions,\n initializeHandlers: (handlers) => initializeHandlers(handlers, ctx),\n });\n\n const server = startAPI(app, { port, logger });\n\n this.getShutdownManager().register({\n name: 'httpServer',\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n }),\n });\n\n logger?.info({ port: port ?? 3000 }, 'API server started');\n\n return { app, server, context: ctx };\n } catch (error) {\n logger?.error({ err: error }, 'Startup failed');\n await this.shutdown('Startup failed');\n throw error;\n }\n }\n\n /**\n * Initialize Firebase, PubSub, and event store wiring.\n * Does not execute dependency checks.\n */\n async initialize(): Promise<ServiceBootstrapContext> {\n if (this.context) {\n return this.context;\n }\n\n const resolvedConfig = this.resolveConfig();\n const logger = this.getLogger();\n\n const firebaseInitializer = new FirebaseInitializer({\n projectId: resolvedConfig.firebase.projectId,\n databaseURL: resolvedConfig.firebase.databaseURL,\n firestoreEmulatorHost: resolvedConfig.firebase.firestoreEmulatorHost,\n databaseEmulatorHost: resolvedConfig.firebase.databaseEmulatorHost,\n logger,\n _firebaseAdmin: resolvedConfig._testOverrides?.firebaseAdmin,\n });\n\n const firebase = await firebaseInitializer.initialize();\n\n const firestore = resolvedConfig._testOverrides?.firestore ?? firebase.firestore;\n const database = resolvedConfig._testOverrides?.database ?? firebase.database;\n const auth = resolvedConfig._testOverrides?.auth ?? firebase.auth;\n\n const pubsubInitializer = new PubSubInitializer({\n projectId: resolvedConfig.pubsub.projectId,\n emulatorHost: resolvedConfig.pubsub.emulatorHost,\n logger,\n _pubsub: resolvedConfig._testOverrides?.pubsub,\n });\n\n const pubsub = await pubsubInitializer.initialize();\n\n const eventStore =\n resolvedConfig._testOverrides?.eventStore ??\n createEventStore({\n firestore,\n database,\n projections: resolvedConfig.projections,\n logger,\n });\n\n const messageBus =\n resolvedConfig._testOverrides?.messageBus ??\n getPubSubMessageBus({\n pubsub,\n useEmulator: pubsubInitializer.isEmulatorMode(),\n topicPrefix: resolvedConfig.pubsub.topicPrefix,\n subscriptionOptions: resolvedConfig.pubsub.subscriptionOptions,\n autoCreateResources: resolvedConfig.pubsub.autoCreateResources,\n cleanupOnClose: resolvedConfig.pubsub.cleanupOnClose,\n closePubSubClient: resolvedConfig.pubsub.closePubSubClient,\n observability: { logger: createPubSubLogger(logger) },\n });\n\n this.shutdownManager = new GracefulShutdown({\n ...resolvedConfig.shutdown,\n logger,\n });\n\n this.registerDefaultShutdownTasks({\n messageBus,\n firestore,\n firebaseApp: firebase.app,\n });\n\n this.dependencyChecker = new DependencyChecker({ logger });\n\n this.context = {\n serviceName: resolvedConfig.serviceName,\n firebase: {\n app: firebase.app,\n firestore,\n database,\n auth,\n },\n firestore,\n database,\n auth,\n pubsub,\n eventStore,\n messageBus,\n logger,\n getCurrentTime: resolvedConfig.getCurrentTime,\n config: resolvedConfig,\n };\n\n return this.context;\n }\n\n /**\n * Initialize and run dependency checks before returning context.\n */\n async start(): Promise<ServiceBootstrapContext> {\n const ctx = await this.initialize();\n const resolvedConfig = this.resolveConfig();\n\n const checks: DependencyCheck[] = [];\n\n if (resolvedConfig.includeDefaultDependencyChecks) {\n checks.push(...this.buildDefaultDependencyChecks(ctx));\n }\n\n if (resolvedConfig.dependencies.length > 0) {\n checks.push(...resolvedConfig.dependencies);\n }\n\n if (checks.length > 0) {\n const summary = await this.getDependencyChecker().checkAll(checks);\n\n if (!summary.ok) {\n const error = new DependencyUnavailableError(summary);\n\n this.logger?.error(\n {\n err: error,\n results: summary.results,\n },\n 'Dependency checks failed',\n );\n\n if (resolvedConfig.shutdownOnDependencyFailure) {\n await this.shutdown('Dependency check failed');\n }\n\n throw error;\n }\n }\n\n this.logger?.info(\n { serviceName: resolvedConfig.serviceName },\n 'Service is running',\n );\n\n return ctx;\n }\n\n /**\n * Execute graceful shutdown tasks and return the shutdown result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n return this.getShutdownManager().shutdown(reason, exitCode);\n }\n\n private getLogger(): BootstrapLogger | undefined {\n if (this.logger !== undefined) {\n return this.logger;\n }\n\n const resolvedConfig = this.resolveConfig();\n const observability = resolvedConfig.observability;\n\n if (observability.logger) {\n this.logger = observability.logger;\n return this.logger;\n }\n\n if (observability.createLogger === false) {\n this.logger = undefined;\n return this.logger;\n }\n\n this.logger = createLogger({\n serviceName: resolvedConfig.serviceName,\n environment: observability.environment,\n logLevel: observability.logLevel,\n });\n\n return this.logger;\n }\n\n private resolveConfig(): ResolvedServiceBootstrapConfig {\n if (this.resolvedConfig) {\n return this.resolvedConfig;\n }\n\n const missing: string[] = [];\n\n const serviceName = this.config.serviceName?.trim();\n if (!serviceName) {\n missing.push('serviceName');\n }\n\n const firestoreEmulatorHost =\n this.config.firebase?.firestoreEmulatorHost ??\n process.env.FIRESTORE_EMULATOR_HOST;\n\n const databaseEmulatorHost =\n this.config.firebase?.databaseEmulatorHost ??\n process.env.FIREBASE_DATABASE_EMULATOR_HOST;\n\n const pubsubEmulatorHost =\n this.config.pubsub?.emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST;\n\n const hasEmulator =\n Boolean(firestoreEmulatorHost) ||\n Boolean(databaseEmulatorHost) ||\n Boolean(pubsubEmulatorHost);\n\n const firebaseProjectId =\n this.config.firebase?.projectId ??\n process.env.FIRESTORE_PROJECT_ID ??\n process.env.GCLOUD_PROJECT ??\n process.env.GOOGLE_CLOUD_PROJECT ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!firebaseProjectId) {\n missing.push('firebase.projectId (or FIRESTORE_PROJECT_ID)');\n }\n\n const pubsubProjectId =\n this.config.pubsub?.projectId ??\n process.env.PUBSUB_PROJECT_ID ??\n firebaseProjectId ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!pubsubProjectId) {\n missing.push('pubsub.projectId (or PUBSUB_PROJECT_ID)');\n }\n\n if (missing.length > 0) {\n throw new Error(`Missing required configuration: ${missing.join(', ')}`);\n }\n\n const resolvedServiceName = serviceName as string;\n const resolvedFirebaseProjectId = firebaseProjectId as string;\n const resolvedPubsubProjectId = pubsubProjectId as string;\n\n const databaseURL =\n this.config.firebase?.databaseURL ??\n this.getDatabaseURL(resolvedFirebaseProjectId, databaseEmulatorHost);\n\n const observability = {\n ...this.config.observability,\n environment:\n this.config.observability?.environment ?? process.env.NODE_ENV,\n logLevel:\n this.config.observability?.logLevel ??\n (process.env.LOG_LEVEL as\n | 'fatal'\n | 'error'\n | 'warn'\n | 'info'\n | 'debug'\n | 'trace'\n | 'silent'\n | undefined),\n createLogger: this.config.observability?.createLogger ?? true,\n };\n\n const getCurrentTime = this.config.getCurrentTime ?? (() => new Date());\n\n this.resolvedConfig = {\n serviceName: resolvedServiceName,\n firebase: {\n projectId: resolvedFirebaseProjectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n },\n pubsub: {\n projectId: resolvedPubsubProjectId,\n emulatorHost: pubsubEmulatorHost,\n topicPrefix: this.config.pubsub?.topicPrefix ?? resolvedServiceName,\n subscriptionOptions: this.config.pubsub?.subscriptionOptions,\n autoCreateResources: this.config.pubsub?.autoCreateResources ?? true,\n cleanupOnClose: this.config.pubsub?.cleanupOnClose ?? false,\n closePubSubClient: this.config.pubsub?.closePubSubClient ?? true,\n },\n observability,\n projections: this.config.projections ?? [],\n getCurrentTime,\n dependencies: this.config.dependencies ?? [],\n includeDefaultDependencyChecks:\n this.config.includeDefaultDependencyChecks ?? true,\n autoStartMessageBus: this.config.autoStartMessageBus ?? true,\n shutdownOnDependencyFailure:\n this.config.shutdownOnDependencyFailure ?? true,\n shutdown: {\n timeoutMs: this.config.shutdown?.timeoutMs ?? 30000,\n exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,\n exitFn: this.config.shutdown?.exitFn,\n },\n _testOverrides: this.config._testOverrides,\n };\n\n return this.resolvedConfig;\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n\n private getDependencyChecker(): DependencyChecker {\n if (!this.dependencyChecker) {\n this.dependencyChecker = new DependencyChecker({ logger: this.getLogger() });\n }\n return this.dependencyChecker;\n }\n\n private getShutdownManager(): GracefulShutdown {\n if (!this.shutdownManager) {\n this.shutdownManager = new GracefulShutdown({\n ...this.resolveConfig().shutdown,\n logger: this.getLogger(),\n });\n }\n return this.shutdownManager;\n }\n\n private registerDefaultShutdownTasks(options: {\n messageBus: MessageBusWithLifecycle;\n firestore: Firestore;\n firebaseApp: FirebaseAppNamespace.App;\n }): void {\n const shutdownManager = this.getShutdownManager();\n\n if (options.messageBus?.close) {\n shutdownManager.register({\n name: 'messageBus',\n close: () => options.messageBus.close(),\n });\n }\n\n if (typeof options.firestore.terminate === 'function') {\n shutdownManager.register({\n name: 'firestore',\n close: () => options.firestore.terminate(),\n });\n }\n\n if (typeof options.firebaseApp.delete === 'function') {\n shutdownManager.register({\n name: 'firebaseApp',\n close: () => options.firebaseApp.delete(),\n });\n }\n }\n\n private buildDefaultDependencyChecks(\n ctx: ServiceBootstrapContext,\n ): DependencyCheck[] {\n const checks: DependencyCheck[] = [];\n\n if (this.resolveConfig().autoStartMessageBus) {\n checks.push({\n name: 'PubSub',\n check: () => ctx.messageBus.start(),\n successMessage: 'Message bus started',\n });\n }\n\n checks.push({\n name: 'Firestore',\n check: async () => {\n await ctx.firestore.doc('_healthcheck/connection').get();\n },\n });\n\n checks.push({\n name: 'Realtime Database',\n check: async () => {\n await ctx.database.ref('_healthcheck/connection').once('value');\n },\n });\n\n return checks;\n }\n}\n","import admin from 'firebase-admin';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport type { FirebaseAdminLike, Logger } from '../types/config';\n\nexport type FirebaseInitializationOptions = {\n projectId: string;\n databaseURL?: string;\n firestoreEmulatorHost?: string;\n databaseEmulatorHost?: string;\n logger?: Logger;\n _firebaseAdmin?: FirebaseAdminLike;\n};\n\nexport type FirebaseInitResult = {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes Firebase Admin SDK with emulator support.\n */\nexport class FirebaseInitializer {\n private readonly options: FirebaseInitializationOptions;\n\n constructor(options: FirebaseInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator hosts are configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.firestoreEmulatorHost ||\n this.options.databaseEmulatorHost ||\n process.env.FIRESTORE_EMULATOR_HOST ||\n process.env.FIREBASE_DATABASE_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize Firebase Admin and return service handles.\n */\n async initialize(): Promise<FirebaseInitResult> {\n const {\n projectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n logger,\n } = this.options;\n\n if (firestoreEmulatorHost && !process.env.FIRESTORE_EMULATOR_HOST) {\n process.env.FIRESTORE_EMULATOR_HOST = firestoreEmulatorHost;\n }\n\n if (databaseEmulatorHost && !process.env.FIREBASE_DATABASE_EMULATOR_HOST) {\n process.env.FIREBASE_DATABASE_EMULATOR_HOST = databaseEmulatorHost;\n }\n\n const resolvedDatabaseURL =\n databaseURL ?? this.getDatabaseURL(projectId, databaseEmulatorHost);\n\n const firebaseAdmin = this.options._firebaseAdmin ?? admin;\n const app = this.getOrCreateApp(firebaseAdmin, projectId, resolvedDatabaseURL);\n\n safeLog.info(logger, 'Firebase initialized', {\n projectId,\n databaseURL: resolvedDatabaseURL,\n emulatorMode: this.isEmulatorMode(),\n });\n\n const firestore = app.firestore();\n const database = app.database();\n const auth = app.auth();\n\n if (firestoreEmulatorHost) {\n firestore.settings({\n host: firestoreEmulatorHost,\n ssl: false,\n });\n safeLog.info(logger, 'Firestore emulator configured', {\n host: firestoreEmulatorHost,\n });\n }\n\n return { app, firestore, database, auth };\n }\n\n private getOrCreateApp(\n firebaseAdmin: FirebaseAdminLike,\n projectId: string,\n databaseURL: string,\n ): FirebaseAppNamespace.App {\n const apps = (firebaseAdmin.apps ?? []).filter(\n (app): app is FirebaseAppNamespace.App => app !== null,\n );\n\n if (apps.length > 0 && firebaseAdmin.app) {\n safeLog.debug(this.options.logger, 'Reusing existing Firebase app');\n return firebaseAdmin.app();\n }\n\n safeLog.debug(this.options.logger, 'Creating Firebase app');\n return firebaseAdmin.initializeApp(\n {\n projectId,\n databaseURL,\n },\n );\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n}\n","import { PubSub } from '@google-cloud/pubsub';\nimport type { Logger } from '../types/config';\n\nexport type PubSubInitializationOptions = {\n projectId: string;\n emulatorHost?: string;\n logger?: Logger;\n _pubsub?: PubSub;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes PubSub client with optional emulator support.\n */\nexport class PubSubInitializer {\n private readonly options: PubSubInitializationOptions;\n\n constructor(options: PubSubInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator host is configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.emulatorHost || process.env.PUBSUB_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize PubSub client or return injected instance.\n */\n async initialize(): Promise<PubSub> {\n const { projectId, emulatorHost, logger } = this.options;\n\n if (emulatorHost && !process.env.PUBSUB_EMULATOR_HOST) {\n process.env.PUBSUB_EMULATOR_HOST = emulatorHost;\n }\n\n if (this.options._pubsub) {\n safeLog.info(logger, 'Using provided PubSub client', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n });\n return this.options._pubsub;\n }\n\n const pubsub = new PubSub({ projectId });\n\n safeLog.info(logger, 'PubSub initialized', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n emulatorMode: this.isEmulatorMode(),\n });\n\n return pubsub;\n }\n}\n","import { getFirestoreEventStore } from '@emmett-community/emmett-google-firestore';\nimport {\n wireRealtimeDBProjections,\n type RealtimeDBInlineProjectionDefinition,\n} from '@emmett-community/emmett-google-realtime-db';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Database } from 'firebase-admin/database';\nimport type { Logger } from '../types/config';\n\nexport type EventStoreFactoryOptions = {\n firestore: Firestore;\n database: Database;\n projections?: RealtimeDBInlineProjectionDefinition[];\n logger?: Logger;\n};\n\n/**\n * Create a Firestore-backed event store and wire RealtimeDB projections if provided.\n */\nexport const createEventStore = <T extends EventStore = EventStore>(\n options: EventStoreFactoryOptions,\n): T => {\n const { firestore, database, projections, logger } = options;\n const observability = logger ? { logger } : undefined;\n\n const baseEventStore = getFirestoreEventStore(firestore, { observability });\n\n if (projections && projections.length > 0) {\n return wireRealtimeDBProjections({\n eventStore: baseEventStore as unknown as T,\n database,\n projections,\n observability,\n }) as T;\n }\n\n return baseEventStore as unknown as T;\n};\n","import type { DependencyCheck, Logger } from '../types/config';\n\nexport class DependencyTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Dependency check timed out after ${timeoutMs}ms`);\n this.name = 'DependencyTimeoutError';\n }\n}\n\nexport type DependencyCheckResult = {\n name: string;\n ok: boolean;\n required: boolean;\n durationMs: number;\n timedOut: boolean;\n error?: unknown;\n};\n\nexport type DependencyCheckSummary = {\n ok: boolean;\n results: DependencyCheckResult[];\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new DependencyTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Helper for one-off dependency checks with optional logging.\n */\nexport const startDependency = async (\n dependency: string,\n startFn: () => Promise<void>,\n options?: {\n logger?: Logger;\n successMessage?: string;\n timeoutMs?: number;\n },\n): Promise<boolean> => {\n const { logger, successMessage, timeoutMs } = options ?? {};\n const startTime = Date.now();\n\n try {\n await withTimeout(startFn(), timeoutMs);\n logger?.info({ dependency, durationMs: Date.now() - startTime }, successMessage);\n return true;\n } catch (error) {\n logger?.warn(\n { dependency, durationMs: Date.now() - startTime, ...normalizeErrorContext(error) },\n 'Unable to reach dependency',\n );\n return false;\n }\n};\n\n/**\n * Executes dependency checks with optional timeouts.\n */\nexport class DependencyChecker {\n private readonly logger?: Logger;\n private readonly defaultTimeoutMs?: number;\n\n constructor(options?: { logger?: Logger; defaultTimeoutMs?: number }) {\n this.logger = options?.logger;\n this.defaultTimeoutMs = options?.defaultTimeoutMs;\n }\n\n async check(dependency: DependencyCheck): Promise<DependencyCheckResult> {\n const start = Date.now();\n const timeoutMs = dependency.timeoutMs ?? this.defaultTimeoutMs;\n\n try {\n await withTimeout(dependency.check(), timeoutMs);\n\n if (dependency.successMessage) {\n this.logger?.info(\n { dependency: dependency.name, durationMs: Date.now() - start },\n dependency.successMessage,\n );\n }\n\n return {\n name: dependency.name,\n ok: true,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut: false,\n };\n } catch (error) {\n const timedOut = error instanceof DependencyTimeoutError;\n\n this.logger?.warn(\n {\n dependency: dependency.name,\n durationMs: Date.now() - start,\n timedOut,\n ...normalizeErrorContext(error),\n },\n 'Dependency check failed',\n );\n\n return {\n name: dependency.name,\n ok: false,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut,\n error,\n };\n }\n }\n\n async checkAll(dependencies: DependencyCheck[]): Promise<DependencyCheckSummary> {\n const results: DependencyCheckResult[] = [];\n\n for (const dependency of dependencies) {\n results.push(await this.check(dependency));\n }\n\n const ok = results.every((result) => result.ok || !result.required);\n\n return { ok, results };\n }\n}\n","import type { GracefulShutdownConfig, Logger } from '../types/config';\n\nexport class ShutdownTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Shutdown task timed out after ${timeoutMs}ms`);\n this.name = 'ShutdownTimeoutError';\n }\n}\n\nexport type ShutdownTask = {\n name: string;\n close: () => Promise<void>;\n timeoutMs?: number;\n};\n\nexport type ShutdownTaskResult = {\n name: string;\n ok: boolean;\n timedOut: boolean;\n durationMs: number;\n error?: unknown;\n};\n\nexport type GracefulShutdownResult = {\n reason: string;\n exitCode: number;\n tasks: ShutdownTaskResult[];\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new ShutdownTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Runs shutdown tasks with timeout handling and optional exit.\n */\nexport class GracefulShutdown {\n private readonly logger?: Logger;\n private readonly timeoutMs?: number;\n private readonly exitOnComplete: boolean;\n private readonly exitFn: (code: number) => void;\n private readonly tasks: ShutdownTask[] = [];\n private shuttingDown = false;\n private lastResult?: GracefulShutdownResult;\n\n constructor(options?: GracefulShutdownConfig & { logger?: Logger }) {\n this.logger = options?.logger;\n this.timeoutMs = options?.timeoutMs;\n this.exitOnComplete = options?.exitOnComplete ?? false;\n this.exitFn = options?.exitFn ?? process.exit;\n }\n\n /**\n * Register a shutdown task.\n */\n register(task: ShutdownTask): void {\n this.tasks.push(task);\n }\n\n /**\n * Execute all shutdown tasks and return the aggregated result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n if (this.shuttingDown && this.lastResult) {\n return this.lastResult;\n }\n\n this.shuttingDown = true;\n this.logger?.info({ reason }, 'Shutting down gracefully');\n\n const results: ShutdownTaskResult[] = [];\n\n for (const task of this.tasks) {\n const start = Date.now();\n const timeoutMs = task.timeoutMs ?? this.timeoutMs;\n\n try {\n await withTimeout(task.close(), timeoutMs);\n results.push({\n name: task.name,\n ok: true,\n timedOut: false,\n durationMs: Date.now() - start,\n });\n this.logger?.info(\n { task: task.name, durationMs: Date.now() - start },\n 'Shutdown task completed',\n );\n } catch (error) {\n const timedOut = error instanceof ShutdownTimeoutError;\n results.push({\n name: task.name,\n ok: false,\n timedOut,\n durationMs: Date.now() - start,\n error,\n });\n this.logger?.warn(\n {\n task: task.name,\n timedOut,\n durationMs: Date.now() - start,\n ...normalizeErrorContext(error),\n },\n 'Shutdown task failed',\n );\n }\n }\n\n const failed = results.some((result) => !result.ok || result.timedOut);\n const finalExitCode = failed ? exitCode : 0;\n\n if (failed) {\n const failedTasks = results\n .filter((result) => !result.ok || result.timedOut)\n .map((result) => result.name);\n this.logger?.error(\n normalizeContext({ failedTasks }),\n 'Shutdown completed with failures',\n );\n } else {\n this.logger?.info({}, 'Shutdown completed');\n }\n\n const result = { reason, exitCode: finalExitCode, tasks: results };\n this.lastResult = result;\n\n if (this.exitOnComplete) {\n this.exitFn(finalExitCode);\n }\n\n return result;\n }\n}\n","import type { Logger } from '../types/config';\n\nexport type SignalHandlerOptions = {\n shutdown: (reason: string, exitCode?: number) => void | Promise<void>;\n signals?: NodeJS.Signals[];\n logger?: Logger;\n exitCode?: number;\n};\n\n/**\n * Register process signal handlers and return an unregister function.\n */\nexport const registerSignalHandlers = (\n options: SignalHandlerOptions,\n): (() => void) => {\n const signals = options.signals ?? ['SIGINT', 'SIGTERM'];\n const handlers = new Map<NodeJS.Signals, () => void>();\n\n for (const signal of signals) {\n const handler = () => {\n options.logger?.info({ signal }, 'Shutdown signal received');\n void options.shutdown(`Signal ${signal} received`, options.exitCode ?? 0);\n };\n\n handlers.set(signal, handler);\n process.on(signal, handler);\n }\n\n return () => {\n for (const [signal, handler] of handlers.entries()) {\n process.off(signal, handler);\n }\n };\n};\n"],"mappings":"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","names":["admin","normalizeContext","normalizeErrorContext","safeLog","normalizeErrorContext","normalizeContext","normalizeErrorContext","withTimeout","result","normalizeContext","normalizeErrorContext","path","registerSignalHandlers","import_emmett_google_realtime_db","import_emmett_expressjs_with_openapi"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/bootstrap/ServiceBootstrap.ts","../src/firebase/FirebaseInitializer.ts","../src/pubsub/PubSubInitializer.ts","../src/eventstore/EventStoreFactory.ts","../src/lifecycle/DependencyChecker.ts","../src/lifecycle/GracefulShutdown.ts","../src/lifecycle/SignalHandlers.ts"],"sourcesContent":["export * from './bootstrap';\nexport * from './types';\nexport * from './firebase';\nexport * from './pubsub';\nexport * from './lifecycle';\nexport * from './eventstore';\nexport { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';\nexport {\n ApiE2ESpecification,\n ApiSpecification,\n createFirebaseAuthSecurityHandlers,\n existingStream,\n expectNewEvents,\n expectResponse,\n NoContent,\n OK,\n on,\n type ImportedHandlerModules,\n type TestRequest,\n} from '@emmett-community/emmett-expressjs-with-openapi';\n","import path from 'node:path';\nimport type { Application } from 'express';\nimport { createLogger } from '@emmett-community/emmett-observability';\nimport {\n createOpenApiValidatorOptions,\n getApplication,\n startAPI,\n type ApplicationOptions,\n type ImportedHandlerModules,\n type OpenApiValidatorOptions,\n} from '@emmett-community/emmett-expressjs-with-openapi';\nimport {\n getPubSubMessageBus,\n type Logger as PubSubLogger,\n} from '@emmett-community/emmett-google-pubsub';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { PubSub } from '@google-cloud/pubsub';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport { FirebaseInitializer } from '../firebase/FirebaseInitializer';\nimport { PubSubInitializer } from '../pubsub/PubSubInitializer';\nimport { createEventStore } from '../eventstore/EventStoreFactory';\nimport {\n DependencyChecker,\n type DependencyCheckSummary,\n} from '../lifecycle/DependencyChecker';\nimport {\n GracefulShutdown,\n type GracefulShutdownResult,\n} from '../lifecycle/GracefulShutdown';\nimport { registerSignalHandlers } from '../lifecycle/SignalHandlers';\nimport type {\n DependencyCheck,\n Logger as BootstrapLogger,\n MessageBusWithLifecycle,\n ResolvedServiceBootstrapConfig,\n ServiceBootstrapConfig,\n} from '../types/config';\n\n/**\n * Runtime context produced by ServiceBootstrap.\n */\nexport type ServiceBootstrapContext = {\n serviceName: string;\n firebase: {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n };\n firestore: Firestore;\n database: Database;\n auth: Auth;\n pubsub: PubSub;\n eventStore: EventStore;\n messageBus: MessageBusWithLifecycle;\n logger?: BootstrapLogger;\n getCurrentTime: () => Date;\n config: ResolvedServiceBootstrapConfig;\n};\n\n/**\n * Error thrown when required dependencies fail health checks.\n */\nexport class DependencyUnavailableError extends Error {\n readonly summary: DependencyCheckSummary;\n\n constructor(summary: DependencyCheckSummary) {\n const failed = summary.results\n .filter((result) => result.required && !result.ok)\n .map((result) => result.name)\n .join(', ');\n\n super(`Dependency check failed: ${failed}`);\n this.name = 'DependencyUnavailableError';\n this.summary = summary;\n }\n}\n\nexport type CreateAppOptions = {\n openApiPath: string;\n handlersPath: string;\n initializeHandlers: (handlers?: ImportedHandlerModules) => void | Promise<void>;\n openApiOptions?: Partial<\n Omit<\n OpenApiValidatorOptions,\n 'apiSpec' | 'operationHandlers' | 'initializeHandlers'\n >\n >;\n appOptions?: Omit<ApplicationOptions, 'openApiValidator' | 'observability'>;\n};\n\nexport type StartApiOptions = Omit<CreateAppOptions, 'initializeHandlers'> & {\n initializeHandlers: (\n handlers: ImportedHandlerModules | undefined,\n ctx: ServiceBootstrapContext,\n ) => void | Promise<void>;\n port?: number;\n registerSignalHandlers?: boolean;\n beforeStart?: (ctx: ServiceBootstrapContext) => void | Promise<void>;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst createPubSubLogger = (\n logger?: BootstrapLogger,\n): PubSubLogger | undefined => {\n if (!logger) return undefined;\n // Adapter: PubSub logger expects (msg, data), canonical logger uses (context, msg).\n const canonicalLogger = logger as any;\n return {\n debug: (msg, data) => canonicalLogger.debug(normalizeContext(data), msg),\n info: (msg, data) => canonicalLogger.info(normalizeContext(data), msg),\n warn: (msg, data) => canonicalLogger.warn(normalizeContext(data), msg),\n error: (msg, error) =>\n canonicalLogger.error(normalizeErrorContext(error), msg),\n };\n};\n\nconst resolvePath = (inputPath: string): string => {\n return path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(process.cwd(), inputPath);\n};\n\n/**\n * Orchestrates Firebase, PubSub, event store, and lifecycle utilities.\n */\nexport class ServiceBootstrap {\n private readonly config: ServiceBootstrapConfig;\n private resolvedConfig?: ResolvedServiceBootstrapConfig;\n private logger?: BootstrapLogger;\n private context?: ServiceBootstrapContext;\n private dependencyChecker?: DependencyChecker;\n private shutdownManager?: GracefulShutdown;\n\n constructor(config: ServiceBootstrapConfig) {\n this.config = config;\n }\n\n /**\n * Resolve configuration with defaults and environment variables.\n */\n getConfig(): ResolvedServiceBootstrapConfig {\n return this.resolveConfig();\n }\n\n /**\n * Return the initialized context if available.\n */\n getContext(): ServiceBootstrapContext | undefined {\n return this.context;\n }\n\n /**\n * Register process signal handlers that trigger shutdown.\n */\n registerSignalHandlers(options?: {\n signals?: NodeJS.Signals[];\n exitCode?: number;\n }): () => void {\n return registerSignalHandlers({\n shutdown: async (reason, exitCode) => {\n await this.shutdown(reason, exitCode);\n },\n signals: options?.signals,\n logger: this.getLogger(),\n exitCode: options?.exitCode,\n });\n }\n\n /**\n * Create an Express app using emmett-expressjs-with-openapi defaults.\n */\n async createApp(options: CreateAppOptions) {\n const logger = this.getLogger();\n const openApiValidator = createOpenApiValidatorOptions(\n resolvePath(options.openApiPath),\n {\n ...options.openApiOptions,\n operationHandlers: resolvePath(options.handlersPath),\n initializeHandlers: options.initializeHandlers,\n },\n );\n\n return getApplication({\n ...(options.appOptions ?? {}),\n openApiValidator,\n observability: logger ? { logger } : undefined,\n });\n }\n\n /**\n * Initialize, run dependency checks, create the app, and start the HTTP server.\n */\n async startApi(options: StartApiOptions): Promise<{\n app: Application;\n server: ReturnType<typeof startAPI>;\n context: ServiceBootstrapContext;\n }> {\n const {\n port,\n registerSignalHandlers,\n beforeStart,\n initializeHandlers,\n ...createAppOptions\n } = options;\n\n const logger = this.getLogger();\n\n try {\n const ctx = await this.initialize();\n\n if (beforeStart) {\n await beforeStart(ctx);\n }\n\n if (registerSignalHandlers !== false) {\n this.registerSignalHandlers();\n }\n\n await this.start();\n\n const app = await this.createApp({\n ...createAppOptions,\n initializeHandlers: (handlers) => initializeHandlers(handlers, ctx),\n });\n\n const server = startAPI(app, { port, logger });\n\n this.getShutdownManager().register({\n name: 'httpServer',\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n }),\n });\n\n logger?.info({ port: port ?? 3000 }, 'API server started');\n\n return { app, server, context: ctx };\n } catch (error) {\n logger?.error({ err: error }, 'Startup failed');\n await this.shutdown('Startup failed');\n throw error;\n }\n }\n\n /**\n * Initialize Firebase, PubSub, and event store wiring.\n * Does not execute dependency checks.\n */\n async initialize(): Promise<ServiceBootstrapContext> {\n if (this.context) {\n return this.context;\n }\n\n const resolvedConfig = this.resolveConfig();\n const logger = this.getLogger();\n\n const firebaseInitializer = new FirebaseInitializer({\n projectId: resolvedConfig.firebase.projectId,\n databaseURL: resolvedConfig.firebase.databaseURL,\n firestoreEmulatorHost: resolvedConfig.firebase.firestoreEmulatorHost,\n databaseEmulatorHost: resolvedConfig.firebase.databaseEmulatorHost,\n logger,\n _firebaseAdmin: resolvedConfig._testOverrides?.firebaseAdmin,\n });\n\n const firebase = await firebaseInitializer.initialize();\n\n const firestore = resolvedConfig._testOverrides?.firestore ?? firebase.firestore;\n const database = resolvedConfig._testOverrides?.database ?? firebase.database;\n const auth = resolvedConfig._testOverrides?.auth ?? firebase.auth;\n\n const pubsubInitializer = new PubSubInitializer({\n projectId: resolvedConfig.pubsub.projectId,\n emulatorHost: resolvedConfig.pubsub.emulatorHost,\n logger,\n _pubsub: resolvedConfig._testOverrides?.pubsub,\n });\n\n const pubsub = await pubsubInitializer.initialize();\n\n const eventStore =\n resolvedConfig._testOverrides?.eventStore ??\n createEventStore({\n firestore,\n database,\n projections: resolvedConfig.projections,\n collections: resolvedConfig.eventStore.collections,\n logger,\n });\n\n const messageBus =\n resolvedConfig._testOverrides?.messageBus ??\n getPubSubMessageBus({\n pubsub,\n useEmulator: pubsubInitializer.isEmulatorMode(),\n topicPrefix: resolvedConfig.pubsub.topicPrefix,\n subscriptionOptions: resolvedConfig.pubsub.subscriptionOptions,\n autoCreateResources: resolvedConfig.pubsub.autoCreateResources,\n cleanupOnClose: resolvedConfig.pubsub.cleanupOnClose,\n closePubSubClient: resolvedConfig.pubsub.closePubSubClient,\n observability: { logger: createPubSubLogger(logger) },\n });\n\n this.shutdownManager = new GracefulShutdown({\n ...resolvedConfig.shutdown,\n logger,\n });\n\n this.registerDefaultShutdownTasks({\n messageBus,\n firestore,\n firebaseApp: firebase.app,\n });\n\n this.dependencyChecker = new DependencyChecker({ logger });\n\n this.context = {\n serviceName: resolvedConfig.serviceName,\n firebase: {\n app: firebase.app,\n firestore,\n database,\n auth,\n },\n firestore,\n database,\n auth,\n pubsub,\n eventStore,\n messageBus,\n logger,\n getCurrentTime: resolvedConfig.getCurrentTime,\n config: resolvedConfig,\n };\n\n return this.context;\n }\n\n /**\n * Initialize and run dependency checks before returning context.\n */\n async start(): Promise<ServiceBootstrapContext> {\n const ctx = await this.initialize();\n const resolvedConfig = this.resolveConfig();\n\n const checks: DependencyCheck[] = [];\n\n if (resolvedConfig.includeDefaultDependencyChecks) {\n checks.push(...this.buildDefaultDependencyChecks(ctx));\n }\n\n if (resolvedConfig.dependencies.length > 0) {\n checks.push(...resolvedConfig.dependencies);\n }\n\n if (checks.length > 0) {\n const summary = await this.getDependencyChecker().checkAll(checks);\n\n if (!summary.ok) {\n const error = new DependencyUnavailableError(summary);\n\n this.logger?.error(\n {\n err: error,\n results: summary.results,\n },\n 'Dependency checks failed',\n );\n\n if (resolvedConfig.shutdownOnDependencyFailure) {\n await this.shutdown('Dependency check failed');\n }\n\n throw error;\n }\n }\n\n this.logger?.info(\n { serviceName: resolvedConfig.serviceName },\n 'Service is running',\n );\n\n return ctx;\n }\n\n /**\n * Execute graceful shutdown tasks and return the shutdown result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n return this.getShutdownManager().shutdown(reason, exitCode);\n }\n\n private getLogger(): BootstrapLogger | undefined {\n if (this.logger !== undefined) {\n return this.logger;\n }\n\n const resolvedConfig = this.resolveConfig();\n const observability = resolvedConfig.observability;\n\n if (observability.logger) {\n this.logger = observability.logger;\n return this.logger;\n }\n\n if (observability.createLogger === false) {\n this.logger = undefined;\n return this.logger;\n }\n\n this.logger = createLogger({\n serviceName: resolvedConfig.serviceName,\n environment: observability.environment,\n logLevel: observability.logLevel,\n });\n\n return this.logger;\n }\n\n private resolveConfig(): ResolvedServiceBootstrapConfig {\n if (this.resolvedConfig) {\n return this.resolvedConfig;\n }\n\n const missing: string[] = [];\n\n const serviceName = this.config.serviceName?.trim();\n if (!serviceName) {\n missing.push('serviceName');\n }\n\n const firestoreEmulatorHost =\n this.config.firebase?.firestoreEmulatorHost ??\n process.env.FIRESTORE_EMULATOR_HOST;\n\n const databaseEmulatorHost =\n this.config.firebase?.databaseEmulatorHost ??\n process.env.FIREBASE_DATABASE_EMULATOR_HOST;\n\n const pubsubEmulatorHost =\n this.config.pubsub?.emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST;\n\n const hasEmulator =\n Boolean(firestoreEmulatorHost) ||\n Boolean(databaseEmulatorHost) ||\n Boolean(pubsubEmulatorHost);\n\n const firebaseProjectId =\n this.config.firebase?.projectId ??\n process.env.FIRESTORE_PROJECT_ID ??\n process.env.GCLOUD_PROJECT ??\n process.env.GOOGLE_CLOUD_PROJECT ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!firebaseProjectId) {\n missing.push('firebase.projectId (or FIRESTORE_PROJECT_ID)');\n }\n\n const pubsubProjectId =\n this.config.pubsub?.projectId ??\n process.env.PUBSUB_PROJECT_ID ??\n firebaseProjectId ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!pubsubProjectId) {\n missing.push('pubsub.projectId (or PUBSUB_PROJECT_ID)');\n }\n\n if (missing.length > 0) {\n throw new Error(`Missing required configuration: ${missing.join(', ')}`);\n }\n\n const resolvedServiceName = serviceName as string;\n const resolvedFirebaseProjectId = firebaseProjectId as string;\n const resolvedPubsubProjectId = pubsubProjectId as string;\n\n const databaseURL =\n this.config.firebase?.databaseURL ??\n this.getDatabaseURL(resolvedFirebaseProjectId, databaseEmulatorHost);\n\n const observability = {\n ...this.config.observability,\n environment:\n this.config.observability?.environment ?? process.env.NODE_ENV,\n logLevel:\n this.config.observability?.logLevel ??\n (process.env.LOG_LEVEL as\n | 'fatal'\n | 'error'\n | 'warn'\n | 'info'\n | 'debug'\n | 'trace'\n | 'silent'\n | undefined),\n createLogger: this.config.observability?.createLogger ?? true,\n };\n\n const getCurrentTime = this.config.getCurrentTime ?? (() => new Date());\n\n this.resolvedConfig = {\n serviceName: resolvedServiceName,\n firebase: {\n projectId: resolvedFirebaseProjectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n },\n pubsub: {\n projectId: resolvedPubsubProjectId,\n emulatorHost: pubsubEmulatorHost,\n topicPrefix: this.config.pubsub?.topicPrefix ?? resolvedServiceName,\n subscriptionOptions: this.config.pubsub?.subscriptionOptions,\n autoCreateResources: this.config.pubsub?.autoCreateResources ?? true,\n cleanupOnClose: this.config.pubsub?.cleanupOnClose ?? false,\n closePubSubClient: this.config.pubsub?.closePubSubClient ?? true,\n },\n observability,\n projections: this.config.projections ?? [],\n getCurrentTime,\n dependencies: this.config.dependencies ?? [],\n includeDefaultDependencyChecks:\n this.config.includeDefaultDependencyChecks ?? true,\n autoStartMessageBus: this.config.autoStartMessageBus ?? true,\n shutdownOnDependencyFailure:\n this.config.shutdownOnDependencyFailure ?? true,\n shutdown: {\n timeoutMs: this.config.shutdown?.timeoutMs ?? 30000,\n exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,\n exitFn: this.config.shutdown?.exitFn,\n },\n eventStore: {\n collections: this.config.eventStore?.collections,\n },\n _testOverrides: this.config._testOverrides,\n };\n\n return this.resolvedConfig;\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n\n private getDependencyChecker(): DependencyChecker {\n if (!this.dependencyChecker) {\n this.dependencyChecker = new DependencyChecker({ logger: this.getLogger() });\n }\n return this.dependencyChecker;\n }\n\n private getShutdownManager(): GracefulShutdown {\n if (!this.shutdownManager) {\n this.shutdownManager = new GracefulShutdown({\n ...this.resolveConfig().shutdown,\n logger: this.getLogger(),\n });\n }\n return this.shutdownManager;\n }\n\n private registerDefaultShutdownTasks(options: {\n messageBus: MessageBusWithLifecycle;\n firestore: Firestore;\n firebaseApp: FirebaseAppNamespace.App;\n }): void {\n const shutdownManager = this.getShutdownManager();\n\n if (options.messageBus?.close) {\n shutdownManager.register({\n name: 'messageBus',\n close: () => options.messageBus.close(),\n });\n }\n\n if (typeof options.firestore.terminate === 'function') {\n shutdownManager.register({\n name: 'firestore',\n close: () => options.firestore.terminate(),\n });\n }\n\n if (typeof options.firebaseApp.delete === 'function') {\n shutdownManager.register({\n name: 'firebaseApp',\n close: () => options.firebaseApp.delete(),\n });\n }\n }\n\n private buildDefaultDependencyChecks(\n ctx: ServiceBootstrapContext,\n ): DependencyCheck[] {\n const checks: DependencyCheck[] = [];\n\n if (this.resolveConfig().autoStartMessageBus) {\n checks.push({\n name: 'PubSub',\n check: () => ctx.messageBus.start(),\n successMessage: 'Message bus started',\n });\n }\n\n checks.push({\n name: 'Firestore',\n check: async () => {\n await ctx.firestore.doc('_healthcheck/connection').get();\n },\n });\n\n checks.push({\n name: 'Realtime Database',\n check: async () => {\n await ctx.database.ref('_healthcheck/connection').once('value');\n },\n });\n\n return checks;\n }\n}\n","import admin from 'firebase-admin';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport type { FirebaseAdminLike, Logger } from '../types/config';\n\nexport type FirebaseInitializationOptions = {\n projectId: string;\n databaseURL?: string;\n firestoreEmulatorHost?: string;\n databaseEmulatorHost?: string;\n logger?: Logger;\n _firebaseAdmin?: FirebaseAdminLike;\n};\n\nexport type FirebaseInitResult = {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes Firebase Admin SDK with emulator support.\n */\nexport class FirebaseInitializer {\n private readonly options: FirebaseInitializationOptions;\n\n constructor(options: FirebaseInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator hosts are configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.firestoreEmulatorHost ||\n this.options.databaseEmulatorHost ||\n process.env.FIRESTORE_EMULATOR_HOST ||\n process.env.FIREBASE_DATABASE_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize Firebase Admin and return service handles.\n */\n async initialize(): Promise<FirebaseInitResult> {\n const {\n projectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n logger,\n } = this.options;\n\n if (firestoreEmulatorHost && !process.env.FIRESTORE_EMULATOR_HOST) {\n process.env.FIRESTORE_EMULATOR_HOST = firestoreEmulatorHost;\n }\n\n if (databaseEmulatorHost && !process.env.FIREBASE_DATABASE_EMULATOR_HOST) {\n process.env.FIREBASE_DATABASE_EMULATOR_HOST = databaseEmulatorHost;\n }\n\n const resolvedDatabaseURL =\n databaseURL ?? this.getDatabaseURL(projectId, databaseEmulatorHost);\n\n const firebaseAdmin = this.options._firebaseAdmin ?? admin;\n const app = this.getOrCreateApp(firebaseAdmin, projectId, resolvedDatabaseURL);\n\n safeLog.info(logger, 'Firebase initialized', {\n projectId,\n databaseURL: resolvedDatabaseURL,\n emulatorMode: this.isEmulatorMode(),\n });\n\n const firestore = app.firestore();\n const database = app.database();\n const auth = app.auth();\n\n if (firestoreEmulatorHost) {\n firestore.settings({\n host: firestoreEmulatorHost,\n ssl: false,\n });\n safeLog.info(logger, 'Firestore emulator configured', {\n host: firestoreEmulatorHost,\n });\n }\n\n return { app, firestore, database, auth };\n }\n\n private getOrCreateApp(\n firebaseAdmin: FirebaseAdminLike,\n projectId: string,\n databaseURL: string,\n ): FirebaseAppNamespace.App {\n const apps = (firebaseAdmin.apps ?? []).filter(\n (app): app is FirebaseAppNamespace.App => app !== null,\n );\n\n if (apps.length > 0 && firebaseAdmin.app) {\n safeLog.debug(this.options.logger, 'Reusing existing Firebase app');\n return firebaseAdmin.app();\n }\n\n safeLog.debug(this.options.logger, 'Creating Firebase app');\n return firebaseAdmin.initializeApp(\n {\n projectId,\n databaseURL,\n },\n );\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n}\n","import { PubSub } from '@google-cloud/pubsub';\nimport type { Logger } from '../types/config';\n\nexport type PubSubInitializationOptions = {\n projectId: string;\n emulatorHost?: string;\n logger?: Logger;\n _pubsub?: PubSub;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes PubSub client with optional emulator support.\n */\nexport class PubSubInitializer {\n private readonly options: PubSubInitializationOptions;\n\n constructor(options: PubSubInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator host is configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.emulatorHost || process.env.PUBSUB_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize PubSub client or return injected instance.\n */\n async initialize(): Promise<PubSub> {\n const { projectId, emulatorHost, logger } = this.options;\n\n if (emulatorHost && !process.env.PUBSUB_EMULATOR_HOST) {\n process.env.PUBSUB_EMULATOR_HOST = emulatorHost;\n }\n\n if (this.options._pubsub) {\n safeLog.info(logger, 'Using provided PubSub client', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n });\n return this.options._pubsub;\n }\n\n const pubsub = new PubSub({ projectId });\n\n safeLog.info(logger, 'PubSub initialized', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n emulatorMode: this.isEmulatorMode(),\n });\n\n return pubsub;\n }\n}\n","import {\n getFirestoreEventStore,\n type FirestoreEventStoreOptions,\n} from '@emmett-community/emmett-google-firestore';\nimport {\n wireRealtimeDBProjections,\n type RealtimeDBInlineProjectionDefinition,\n} from '@emmett-community/emmett-google-realtime-db';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Database } from 'firebase-admin/database';\nimport type { Logger } from '../types/config';\n\nexport type EventStoreFactoryOptions = {\n firestore: Firestore;\n database: Database;\n projections?: RealtimeDBInlineProjectionDefinition[];\n logger?: Logger;\n collections?: FirestoreEventStoreOptions['collections'];\n};\n\n/**\n * Create a Firestore-backed event store and wire RealtimeDB projections if provided.\n */\nexport const createEventStore = <T extends EventStore = EventStore>(\n options: EventStoreFactoryOptions,\n): T => {\n const { firestore, database, projections, logger, collections } = options;\n const observability = logger ? { logger } : undefined;\n\n const baseEventStore = getFirestoreEventStore(firestore, {\n observability,\n collections,\n });\n\n if (projections && projections.length > 0) {\n return wireRealtimeDBProjections({\n eventStore: baseEventStore as unknown as T,\n database,\n projections,\n observability,\n }) as T;\n }\n\n return baseEventStore as unknown as T;\n};\n","import type { DependencyCheck, Logger } from '../types/config';\n\nexport class DependencyTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Dependency check timed out after ${timeoutMs}ms`);\n this.name = 'DependencyTimeoutError';\n }\n}\n\nexport type DependencyCheckResult = {\n name: string;\n ok: boolean;\n required: boolean;\n durationMs: number;\n timedOut: boolean;\n error?: unknown;\n};\n\nexport type DependencyCheckSummary = {\n ok: boolean;\n results: DependencyCheckResult[];\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new DependencyTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Helper for one-off dependency checks with optional logging.\n */\nexport const startDependency = async (\n dependency: string,\n startFn: () => Promise<void>,\n options?: {\n logger?: Logger;\n successMessage?: string;\n timeoutMs?: number;\n },\n): Promise<boolean> => {\n const { logger, successMessage, timeoutMs } = options ?? {};\n const startTime = Date.now();\n\n try {\n await withTimeout(startFn(), timeoutMs);\n logger?.info({ dependency, durationMs: Date.now() - startTime }, successMessage);\n return true;\n } catch (error) {\n logger?.warn(\n { dependency, durationMs: Date.now() - startTime, ...normalizeErrorContext(error) },\n 'Unable to reach dependency',\n );\n return false;\n }\n};\n\n/**\n * Executes dependency checks with optional timeouts.\n */\nexport class DependencyChecker {\n private readonly logger?: Logger;\n private readonly defaultTimeoutMs?: number;\n\n constructor(options?: { logger?: Logger; defaultTimeoutMs?: number }) {\n this.logger = options?.logger;\n this.defaultTimeoutMs = options?.defaultTimeoutMs;\n }\n\n async check(dependency: DependencyCheck): Promise<DependencyCheckResult> {\n const start = Date.now();\n const timeoutMs = dependency.timeoutMs ?? this.defaultTimeoutMs;\n\n try {\n await withTimeout(dependency.check(), timeoutMs);\n\n if (dependency.successMessage) {\n this.logger?.info(\n { dependency: dependency.name, durationMs: Date.now() - start },\n dependency.successMessage,\n );\n }\n\n return {\n name: dependency.name,\n ok: true,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut: false,\n };\n } catch (error) {\n const timedOut = error instanceof DependencyTimeoutError;\n\n this.logger?.warn(\n {\n dependency: dependency.name,\n durationMs: Date.now() - start,\n timedOut,\n ...normalizeErrorContext(error),\n },\n 'Dependency check failed',\n );\n\n return {\n name: dependency.name,\n ok: false,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut,\n error,\n };\n }\n }\n\n async checkAll(dependencies: DependencyCheck[]): Promise<DependencyCheckSummary> {\n const results: DependencyCheckResult[] = [];\n\n for (const dependency of dependencies) {\n results.push(await this.check(dependency));\n }\n\n const ok = results.every((result) => result.ok || !result.required);\n\n return { ok, results };\n }\n}\n","import type { GracefulShutdownConfig, Logger } from '../types/config';\n\nexport class ShutdownTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Shutdown task timed out after ${timeoutMs}ms`);\n this.name = 'ShutdownTimeoutError';\n }\n}\n\nexport type ShutdownTask = {\n name: string;\n close: () => Promise<void>;\n timeoutMs?: number;\n};\n\nexport type ShutdownTaskResult = {\n name: string;\n ok: boolean;\n timedOut: boolean;\n durationMs: number;\n error?: unknown;\n};\n\nexport type GracefulShutdownResult = {\n reason: string;\n exitCode: number;\n tasks: ShutdownTaskResult[];\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new ShutdownTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Runs shutdown tasks with timeout handling and optional exit.\n */\nexport class GracefulShutdown {\n private readonly logger?: Logger;\n private readonly timeoutMs?: number;\n private readonly exitOnComplete: boolean;\n private readonly exitFn: (code: number) => void;\n private readonly tasks: ShutdownTask[] = [];\n private shuttingDown = false;\n private lastResult?: GracefulShutdownResult;\n\n constructor(options?: GracefulShutdownConfig & { logger?: Logger }) {\n this.logger = options?.logger;\n this.timeoutMs = options?.timeoutMs;\n this.exitOnComplete = options?.exitOnComplete ?? false;\n this.exitFn = options?.exitFn ?? process.exit;\n }\n\n /**\n * Register a shutdown task.\n */\n register(task: ShutdownTask): void {\n this.tasks.push(task);\n }\n\n /**\n * Execute all shutdown tasks and return the aggregated result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n if (this.shuttingDown && this.lastResult) {\n return this.lastResult;\n }\n\n this.shuttingDown = true;\n this.logger?.info({ reason }, 'Shutting down gracefully');\n\n const results: ShutdownTaskResult[] = [];\n\n for (const task of this.tasks) {\n const start = Date.now();\n const timeoutMs = task.timeoutMs ?? this.timeoutMs;\n\n try {\n await withTimeout(task.close(), timeoutMs);\n results.push({\n name: task.name,\n ok: true,\n timedOut: false,\n durationMs: Date.now() - start,\n });\n this.logger?.info(\n { task: task.name, durationMs: Date.now() - start },\n 'Shutdown task completed',\n );\n } catch (error) {\n const timedOut = error instanceof ShutdownTimeoutError;\n results.push({\n name: task.name,\n ok: false,\n timedOut,\n durationMs: Date.now() - start,\n error,\n });\n this.logger?.warn(\n {\n task: task.name,\n timedOut,\n durationMs: Date.now() - start,\n ...normalizeErrorContext(error),\n },\n 'Shutdown task failed',\n );\n }\n }\n\n const failed = results.some((result) => !result.ok || result.timedOut);\n const finalExitCode = failed ? exitCode : 0;\n\n if (failed) {\n const failedTasks = results\n .filter((result) => !result.ok || result.timedOut)\n .map((result) => result.name);\n this.logger?.error(\n normalizeContext({ failedTasks }),\n 'Shutdown completed with failures',\n );\n } else {\n this.logger?.info({}, 'Shutdown completed');\n }\n\n const result = { reason, exitCode: finalExitCode, tasks: results };\n this.lastResult = result;\n\n if (this.exitOnComplete) {\n this.exitFn(finalExitCode);\n }\n\n return result;\n }\n}\n","import type { Logger } from '../types/config';\n\nexport type SignalHandlerOptions = {\n shutdown: (reason: string, exitCode?: number) => void | Promise<void>;\n signals?: NodeJS.Signals[];\n logger?: Logger;\n exitCode?: number;\n};\n\n/**\n * Register process signal handlers and return an unregister function.\n */\nexport const registerSignalHandlers = (\n options: SignalHandlerOptions,\n): (() => void) => {\n const signals = options.signals ?? ['SIGINT', 'SIGTERM'];\n const handlers = new Map<NodeJS.Signals, () => void>();\n\n for (const signal of signals) {\n const handler = () => {\n options.logger?.info({ signal }, 'Shutdown signal received');\n void options.shutdown(`Signal ${signal} received`, options.exitCode ?? 0);\n };\n\n handlers.set(signal, handler);\n process.on(signal, handler);\n }\n\n return () => {\n for (const [signal, handler] of handlers.entries()) {\n process.off(signal, handler);\n }\n };\n};\n"],"mappings":"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","names":["admin","normalizeContext","normalizeErrorContext","safeLog","normalizeErrorContext","normalizeContext","normalizeErrorContext","withTimeout","result","normalizeContext","normalizeErrorContext","path","registerSignalHandlers","import_emmett_google_realtime_db","import_emmett_expressjs_with_openapi"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -10,6 +10,7 @@ import { Database } from 'firebase-admin/database';
|
|
|
10
10
|
import { PubSubMessageBusLifecycle, SubscriptionOptions } from '@emmett-community/emmett-google-pubsub';
|
|
11
11
|
import { RealtimeDBInlineProjectionDefinition } from '@emmett-community/emmett-google-realtime-db';
|
|
12
12
|
export { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';
|
|
13
|
+
import { FirestoreEventStoreOptions } from '@emmett-community/emmett-google-firestore';
|
|
13
14
|
|
|
14
15
|
type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
15
16
|
/**
|
|
@@ -81,6 +82,9 @@ type ServiceBootstrapConfig = {
|
|
|
81
82
|
serviceName: string;
|
|
82
83
|
firebase?: FirebaseConfig;
|
|
83
84
|
pubsub?: PubSubConfig;
|
|
85
|
+
eventStore?: {
|
|
86
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
87
|
+
};
|
|
84
88
|
observability?: ObservabilityConfig;
|
|
85
89
|
projections?: RealtimeDBInlineProjectionDefinition[];
|
|
86
90
|
getCurrentTime?: () => Date;
|
|
@@ -110,6 +114,9 @@ type ResolvedServiceBootstrapConfig = {
|
|
|
110
114
|
serviceName: string;
|
|
111
115
|
firebase: ResolvedFirebaseConfig;
|
|
112
116
|
pubsub: ResolvedPubSubConfig;
|
|
117
|
+
eventStore: {
|
|
118
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
119
|
+
};
|
|
113
120
|
observability: ObservabilityConfig;
|
|
114
121
|
projections: RealtimeDBInlineProjectionDefinition[];
|
|
115
122
|
getCurrentTime: () => Date;
|
|
@@ -373,6 +380,7 @@ type EventStoreFactoryOptions = {
|
|
|
373
380
|
database: Database;
|
|
374
381
|
projections?: RealtimeDBInlineProjectionDefinition[];
|
|
375
382
|
logger?: Logger;
|
|
383
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
376
384
|
};
|
|
377
385
|
/**
|
|
378
386
|
* Create a Firestore-backed event store and wire RealtimeDB projections if provided.
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Database } from 'firebase-admin/database';
|
|
|
10
10
|
import { PubSubMessageBusLifecycle, SubscriptionOptions } from '@emmett-community/emmett-google-pubsub';
|
|
11
11
|
import { RealtimeDBInlineProjectionDefinition } from '@emmett-community/emmett-google-realtime-db';
|
|
12
12
|
export { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';
|
|
13
|
+
import { FirestoreEventStoreOptions } from '@emmett-community/emmett-google-firestore';
|
|
13
14
|
|
|
14
15
|
type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
15
16
|
/**
|
|
@@ -81,6 +82,9 @@ type ServiceBootstrapConfig = {
|
|
|
81
82
|
serviceName: string;
|
|
82
83
|
firebase?: FirebaseConfig;
|
|
83
84
|
pubsub?: PubSubConfig;
|
|
85
|
+
eventStore?: {
|
|
86
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
87
|
+
};
|
|
84
88
|
observability?: ObservabilityConfig;
|
|
85
89
|
projections?: RealtimeDBInlineProjectionDefinition[];
|
|
86
90
|
getCurrentTime?: () => Date;
|
|
@@ -110,6 +114,9 @@ type ResolvedServiceBootstrapConfig = {
|
|
|
110
114
|
serviceName: string;
|
|
111
115
|
firebase: ResolvedFirebaseConfig;
|
|
112
116
|
pubsub: ResolvedPubSubConfig;
|
|
117
|
+
eventStore: {
|
|
118
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
119
|
+
};
|
|
113
120
|
observability: ObservabilityConfig;
|
|
114
121
|
projections: RealtimeDBInlineProjectionDefinition[];
|
|
115
122
|
getCurrentTime: () => Date;
|
|
@@ -373,6 +380,7 @@ type EventStoreFactoryOptions = {
|
|
|
373
380
|
database: Database;
|
|
374
381
|
projections?: RealtimeDBInlineProjectionDefinition[];
|
|
375
382
|
logger?: Logger;
|
|
383
|
+
collections?: FirestoreEventStoreOptions['collections'];
|
|
376
384
|
};
|
|
377
385
|
/**
|
|
378
386
|
* Create a Firestore-backed event store and wire RealtimeDB projections if provided.
|
package/dist/index.js
CHANGED
|
@@ -195,14 +195,19 @@ var PubSubInitializer = class {
|
|
|
195
195
|
};
|
|
196
196
|
|
|
197
197
|
// src/eventstore/EventStoreFactory.ts
|
|
198
|
-
import {
|
|
198
|
+
import {
|
|
199
|
+
getFirestoreEventStore
|
|
200
|
+
} from "@emmett-community/emmett-google-firestore";
|
|
199
201
|
import {
|
|
200
202
|
wireRealtimeDBProjections
|
|
201
203
|
} from "@emmett-community/emmett-google-realtime-db";
|
|
202
204
|
var createEventStore = (options) => {
|
|
203
|
-
const { firestore, database, projections, logger } = options;
|
|
205
|
+
const { firestore, database, projections, logger, collections } = options;
|
|
204
206
|
const observability = logger ? { logger } : void 0;
|
|
205
|
-
const baseEventStore = getFirestoreEventStore(firestore, {
|
|
207
|
+
const baseEventStore = getFirestoreEventStore(firestore, {
|
|
208
|
+
observability,
|
|
209
|
+
collections
|
|
210
|
+
});
|
|
206
211
|
if (projections && projections.length > 0) {
|
|
207
212
|
return wireRealtimeDBProjections({
|
|
208
213
|
eventStore: baseEventStore,
|
|
@@ -629,6 +634,7 @@ var ServiceBootstrap = class {
|
|
|
629
634
|
firestore,
|
|
630
635
|
database,
|
|
631
636
|
projections: resolvedConfig.projections,
|
|
637
|
+
collections: resolvedConfig.eventStore.collections,
|
|
632
638
|
logger
|
|
633
639
|
});
|
|
634
640
|
const messageBus = resolvedConfig._testOverrides?.messageBus ?? getPubSubMessageBus({
|
|
@@ -798,6 +804,9 @@ var ServiceBootstrap = class {
|
|
|
798
804
|
exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,
|
|
799
805
|
exitFn: this.config.shutdown?.exitFn
|
|
800
806
|
},
|
|
807
|
+
eventStore: {
|
|
808
|
+
collections: this.config.eventStore?.collections
|
|
809
|
+
},
|
|
801
810
|
_testOverrides: this.config._testOverrides
|
|
802
811
|
};
|
|
803
812
|
return this.resolvedConfig;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bootstrap/ServiceBootstrap.ts","../src/firebase/FirebaseInitializer.ts","../src/pubsub/PubSubInitializer.ts","../src/eventstore/EventStoreFactory.ts","../src/lifecycle/DependencyChecker.ts","../src/lifecycle/GracefulShutdown.ts","../src/lifecycle/SignalHandlers.ts","../src/index.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Application } from 'express';\nimport { createLogger } from '@emmett-community/emmett-observability';\nimport {\n createOpenApiValidatorOptions,\n getApplication,\n startAPI,\n type ApplicationOptions,\n type ImportedHandlerModules,\n type OpenApiValidatorOptions,\n} from '@emmett-community/emmett-expressjs-with-openapi';\nimport {\n getPubSubMessageBus,\n type Logger as PubSubLogger,\n} from '@emmett-community/emmett-google-pubsub';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { PubSub } from '@google-cloud/pubsub';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport { FirebaseInitializer } from '../firebase/FirebaseInitializer';\nimport { PubSubInitializer } from '../pubsub/PubSubInitializer';\nimport { createEventStore } from '../eventstore/EventStoreFactory';\nimport {\n DependencyChecker,\n type DependencyCheckSummary,\n} from '../lifecycle/DependencyChecker';\nimport {\n GracefulShutdown,\n type GracefulShutdownResult,\n} from '../lifecycle/GracefulShutdown';\nimport { registerSignalHandlers } from '../lifecycle/SignalHandlers';\nimport type {\n DependencyCheck,\n Logger as BootstrapLogger,\n MessageBusWithLifecycle,\n ResolvedServiceBootstrapConfig,\n ServiceBootstrapConfig,\n} from '../types/config';\n\n/**\n * Runtime context produced by ServiceBootstrap.\n */\nexport type ServiceBootstrapContext = {\n serviceName: string;\n firebase: {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n };\n firestore: Firestore;\n database: Database;\n auth: Auth;\n pubsub: PubSub;\n eventStore: EventStore;\n messageBus: MessageBusWithLifecycle;\n logger?: BootstrapLogger;\n getCurrentTime: () => Date;\n config: ResolvedServiceBootstrapConfig;\n};\n\n/**\n * Error thrown when required dependencies fail health checks.\n */\nexport class DependencyUnavailableError extends Error {\n readonly summary: DependencyCheckSummary;\n\n constructor(summary: DependencyCheckSummary) {\n const failed = summary.results\n .filter((result) => result.required && !result.ok)\n .map((result) => result.name)\n .join(', ');\n\n super(`Dependency check failed: ${failed}`);\n this.name = 'DependencyUnavailableError';\n this.summary = summary;\n }\n}\n\nexport type CreateAppOptions = {\n openApiPath: string;\n handlersPath: string;\n initializeHandlers: (handlers?: ImportedHandlerModules) => void | Promise<void>;\n openApiOptions?: Partial<\n Omit<\n OpenApiValidatorOptions,\n 'apiSpec' | 'operationHandlers' | 'initializeHandlers'\n >\n >;\n appOptions?: Omit<ApplicationOptions, 'openApiValidator' | 'observability'>;\n};\n\nexport type StartApiOptions = Omit<CreateAppOptions, 'initializeHandlers'> & {\n initializeHandlers: (\n handlers: ImportedHandlerModules | undefined,\n ctx: ServiceBootstrapContext,\n ) => void | Promise<void>;\n port?: number;\n registerSignalHandlers?: boolean;\n beforeStart?: (ctx: ServiceBootstrapContext) => void | Promise<void>;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst createPubSubLogger = (\n logger?: BootstrapLogger,\n): PubSubLogger | undefined => {\n if (!logger) return undefined;\n // Adapter: PubSub logger expects (msg, data), canonical logger uses (context, msg).\n const canonicalLogger = logger as any;\n return {\n debug: (msg, data) => canonicalLogger.debug(normalizeContext(data), msg),\n info: (msg, data) => canonicalLogger.info(normalizeContext(data), msg),\n warn: (msg, data) => canonicalLogger.warn(normalizeContext(data), msg),\n error: (msg, error) =>\n canonicalLogger.error(normalizeErrorContext(error), msg),\n };\n};\n\nconst resolvePath = (inputPath: string): string => {\n return path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(process.cwd(), inputPath);\n};\n\n/**\n * Orchestrates Firebase, PubSub, event store, and lifecycle utilities.\n */\nexport class ServiceBootstrap {\n private readonly config: ServiceBootstrapConfig;\n private resolvedConfig?: ResolvedServiceBootstrapConfig;\n private logger?: BootstrapLogger;\n private context?: ServiceBootstrapContext;\n private dependencyChecker?: DependencyChecker;\n private shutdownManager?: GracefulShutdown;\n\n constructor(config: ServiceBootstrapConfig) {\n this.config = config;\n }\n\n /**\n * Resolve configuration with defaults and environment variables.\n */\n getConfig(): ResolvedServiceBootstrapConfig {\n return this.resolveConfig();\n }\n\n /**\n * Return the initialized context if available.\n */\n getContext(): ServiceBootstrapContext | undefined {\n return this.context;\n }\n\n /**\n * Register process signal handlers that trigger shutdown.\n */\n registerSignalHandlers(options?: {\n signals?: NodeJS.Signals[];\n exitCode?: number;\n }): () => void {\n return registerSignalHandlers({\n shutdown: async (reason, exitCode) => {\n await this.shutdown(reason, exitCode);\n },\n signals: options?.signals,\n logger: this.getLogger(),\n exitCode: options?.exitCode,\n });\n }\n\n /**\n * Create an Express app using emmett-expressjs-with-openapi defaults.\n */\n async createApp(options: CreateAppOptions) {\n const logger = this.getLogger();\n const openApiValidator = createOpenApiValidatorOptions(\n resolvePath(options.openApiPath),\n {\n ...options.openApiOptions,\n operationHandlers: resolvePath(options.handlersPath),\n initializeHandlers: options.initializeHandlers,\n },\n );\n\n return getApplication({\n ...(options.appOptions ?? {}),\n openApiValidator,\n observability: logger ? { logger } : undefined,\n });\n }\n\n /**\n * Initialize, run dependency checks, create the app, and start the HTTP server.\n */\n async startApi(options: StartApiOptions): Promise<{\n app: Application;\n server: ReturnType<typeof startAPI>;\n context: ServiceBootstrapContext;\n }> {\n const {\n port,\n registerSignalHandlers,\n beforeStart,\n initializeHandlers,\n ...createAppOptions\n } = options;\n\n const logger = this.getLogger();\n\n try {\n const ctx = await this.initialize();\n\n if (beforeStart) {\n await beforeStart(ctx);\n }\n\n if (registerSignalHandlers !== false) {\n this.registerSignalHandlers();\n }\n\n await this.start();\n\n const app = await this.createApp({\n ...createAppOptions,\n initializeHandlers: (handlers) => initializeHandlers(handlers, ctx),\n });\n\n const server = startAPI(app, { port, logger });\n\n this.getShutdownManager().register({\n name: 'httpServer',\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n }),\n });\n\n logger?.info({ port: port ?? 3000 }, 'API server started');\n\n return { app, server, context: ctx };\n } catch (error) {\n logger?.error({ err: error }, 'Startup failed');\n await this.shutdown('Startup failed');\n throw error;\n }\n }\n\n /**\n * Initialize Firebase, PubSub, and event store wiring.\n * Does not execute dependency checks.\n */\n async initialize(): Promise<ServiceBootstrapContext> {\n if (this.context) {\n return this.context;\n }\n\n const resolvedConfig = this.resolveConfig();\n const logger = this.getLogger();\n\n const firebaseInitializer = new FirebaseInitializer({\n projectId: resolvedConfig.firebase.projectId,\n databaseURL: resolvedConfig.firebase.databaseURL,\n firestoreEmulatorHost: resolvedConfig.firebase.firestoreEmulatorHost,\n databaseEmulatorHost: resolvedConfig.firebase.databaseEmulatorHost,\n logger,\n _firebaseAdmin: resolvedConfig._testOverrides?.firebaseAdmin,\n });\n\n const firebase = await firebaseInitializer.initialize();\n\n const firestore = resolvedConfig._testOverrides?.firestore ?? firebase.firestore;\n const database = resolvedConfig._testOverrides?.database ?? firebase.database;\n const auth = resolvedConfig._testOverrides?.auth ?? firebase.auth;\n\n const pubsubInitializer = new PubSubInitializer({\n projectId: resolvedConfig.pubsub.projectId,\n emulatorHost: resolvedConfig.pubsub.emulatorHost,\n logger,\n _pubsub: resolvedConfig._testOverrides?.pubsub,\n });\n\n const pubsub = await pubsubInitializer.initialize();\n\n const eventStore =\n resolvedConfig._testOverrides?.eventStore ??\n createEventStore({\n firestore,\n database,\n projections: resolvedConfig.projections,\n logger,\n });\n\n const messageBus =\n resolvedConfig._testOverrides?.messageBus ??\n getPubSubMessageBus({\n pubsub,\n useEmulator: pubsubInitializer.isEmulatorMode(),\n topicPrefix: resolvedConfig.pubsub.topicPrefix,\n subscriptionOptions: resolvedConfig.pubsub.subscriptionOptions,\n autoCreateResources: resolvedConfig.pubsub.autoCreateResources,\n cleanupOnClose: resolvedConfig.pubsub.cleanupOnClose,\n closePubSubClient: resolvedConfig.pubsub.closePubSubClient,\n observability: { logger: createPubSubLogger(logger) },\n });\n\n this.shutdownManager = new GracefulShutdown({\n ...resolvedConfig.shutdown,\n logger,\n });\n\n this.registerDefaultShutdownTasks({\n messageBus,\n firestore,\n firebaseApp: firebase.app,\n });\n\n this.dependencyChecker = new DependencyChecker({ logger });\n\n this.context = {\n serviceName: resolvedConfig.serviceName,\n firebase: {\n app: firebase.app,\n firestore,\n database,\n auth,\n },\n firestore,\n database,\n auth,\n pubsub,\n eventStore,\n messageBus,\n logger,\n getCurrentTime: resolvedConfig.getCurrentTime,\n config: resolvedConfig,\n };\n\n return this.context;\n }\n\n /**\n * Initialize and run dependency checks before returning context.\n */\n async start(): Promise<ServiceBootstrapContext> {\n const ctx = await this.initialize();\n const resolvedConfig = this.resolveConfig();\n\n const checks: DependencyCheck[] = [];\n\n if (resolvedConfig.includeDefaultDependencyChecks) {\n checks.push(...this.buildDefaultDependencyChecks(ctx));\n }\n\n if (resolvedConfig.dependencies.length > 0) {\n checks.push(...resolvedConfig.dependencies);\n }\n\n if (checks.length > 0) {\n const summary = await this.getDependencyChecker().checkAll(checks);\n\n if (!summary.ok) {\n const error = new DependencyUnavailableError(summary);\n\n this.logger?.error(\n {\n err: error,\n results: summary.results,\n },\n 'Dependency checks failed',\n );\n\n if (resolvedConfig.shutdownOnDependencyFailure) {\n await this.shutdown('Dependency check failed');\n }\n\n throw error;\n }\n }\n\n this.logger?.info(\n { serviceName: resolvedConfig.serviceName },\n 'Service is running',\n );\n\n return ctx;\n }\n\n /**\n * Execute graceful shutdown tasks and return the shutdown result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n return this.getShutdownManager().shutdown(reason, exitCode);\n }\n\n private getLogger(): BootstrapLogger | undefined {\n if (this.logger !== undefined) {\n return this.logger;\n }\n\n const resolvedConfig = this.resolveConfig();\n const observability = resolvedConfig.observability;\n\n if (observability.logger) {\n this.logger = observability.logger;\n return this.logger;\n }\n\n if (observability.createLogger === false) {\n this.logger = undefined;\n return this.logger;\n }\n\n this.logger = createLogger({\n serviceName: resolvedConfig.serviceName,\n environment: observability.environment,\n logLevel: observability.logLevel,\n });\n\n return this.logger;\n }\n\n private resolveConfig(): ResolvedServiceBootstrapConfig {\n if (this.resolvedConfig) {\n return this.resolvedConfig;\n }\n\n const missing: string[] = [];\n\n const serviceName = this.config.serviceName?.trim();\n if (!serviceName) {\n missing.push('serviceName');\n }\n\n const firestoreEmulatorHost =\n this.config.firebase?.firestoreEmulatorHost ??\n process.env.FIRESTORE_EMULATOR_HOST;\n\n const databaseEmulatorHost =\n this.config.firebase?.databaseEmulatorHost ??\n process.env.FIREBASE_DATABASE_EMULATOR_HOST;\n\n const pubsubEmulatorHost =\n this.config.pubsub?.emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST;\n\n const hasEmulator =\n Boolean(firestoreEmulatorHost) ||\n Boolean(databaseEmulatorHost) ||\n Boolean(pubsubEmulatorHost);\n\n const firebaseProjectId =\n this.config.firebase?.projectId ??\n process.env.FIRESTORE_PROJECT_ID ??\n process.env.GCLOUD_PROJECT ??\n process.env.GOOGLE_CLOUD_PROJECT ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!firebaseProjectId) {\n missing.push('firebase.projectId (or FIRESTORE_PROJECT_ID)');\n }\n\n const pubsubProjectId =\n this.config.pubsub?.projectId ??\n process.env.PUBSUB_PROJECT_ID ??\n firebaseProjectId ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!pubsubProjectId) {\n missing.push('pubsub.projectId (or PUBSUB_PROJECT_ID)');\n }\n\n if (missing.length > 0) {\n throw new Error(`Missing required configuration: ${missing.join(', ')}`);\n }\n\n const resolvedServiceName = serviceName as string;\n const resolvedFirebaseProjectId = firebaseProjectId as string;\n const resolvedPubsubProjectId = pubsubProjectId as string;\n\n const databaseURL =\n this.config.firebase?.databaseURL ??\n this.getDatabaseURL(resolvedFirebaseProjectId, databaseEmulatorHost);\n\n const observability = {\n ...this.config.observability,\n environment:\n this.config.observability?.environment ?? process.env.NODE_ENV,\n logLevel:\n this.config.observability?.logLevel ??\n (process.env.LOG_LEVEL as\n | 'fatal'\n | 'error'\n | 'warn'\n | 'info'\n | 'debug'\n | 'trace'\n | 'silent'\n | undefined),\n createLogger: this.config.observability?.createLogger ?? true,\n };\n\n const getCurrentTime = this.config.getCurrentTime ?? (() => new Date());\n\n this.resolvedConfig = {\n serviceName: resolvedServiceName,\n firebase: {\n projectId: resolvedFirebaseProjectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n },\n pubsub: {\n projectId: resolvedPubsubProjectId,\n emulatorHost: pubsubEmulatorHost,\n topicPrefix: this.config.pubsub?.topicPrefix ?? resolvedServiceName,\n subscriptionOptions: this.config.pubsub?.subscriptionOptions,\n autoCreateResources: this.config.pubsub?.autoCreateResources ?? true,\n cleanupOnClose: this.config.pubsub?.cleanupOnClose ?? false,\n closePubSubClient: this.config.pubsub?.closePubSubClient ?? true,\n },\n observability,\n projections: this.config.projections ?? [],\n getCurrentTime,\n dependencies: this.config.dependencies ?? [],\n includeDefaultDependencyChecks:\n this.config.includeDefaultDependencyChecks ?? true,\n autoStartMessageBus: this.config.autoStartMessageBus ?? true,\n shutdownOnDependencyFailure:\n this.config.shutdownOnDependencyFailure ?? true,\n shutdown: {\n timeoutMs: this.config.shutdown?.timeoutMs ?? 30000,\n exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,\n exitFn: this.config.shutdown?.exitFn,\n },\n _testOverrides: this.config._testOverrides,\n };\n\n return this.resolvedConfig;\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n\n private getDependencyChecker(): DependencyChecker {\n if (!this.dependencyChecker) {\n this.dependencyChecker = new DependencyChecker({ logger: this.getLogger() });\n }\n return this.dependencyChecker;\n }\n\n private getShutdownManager(): GracefulShutdown {\n if (!this.shutdownManager) {\n this.shutdownManager = new GracefulShutdown({\n ...this.resolveConfig().shutdown,\n logger: this.getLogger(),\n });\n }\n return this.shutdownManager;\n }\n\n private registerDefaultShutdownTasks(options: {\n messageBus: MessageBusWithLifecycle;\n firestore: Firestore;\n firebaseApp: FirebaseAppNamespace.App;\n }): void {\n const shutdownManager = this.getShutdownManager();\n\n if (options.messageBus?.close) {\n shutdownManager.register({\n name: 'messageBus',\n close: () => options.messageBus.close(),\n });\n }\n\n if (typeof options.firestore.terminate === 'function') {\n shutdownManager.register({\n name: 'firestore',\n close: () => options.firestore.terminate(),\n });\n }\n\n if (typeof options.firebaseApp.delete === 'function') {\n shutdownManager.register({\n name: 'firebaseApp',\n close: () => options.firebaseApp.delete(),\n });\n }\n }\n\n private buildDefaultDependencyChecks(\n ctx: ServiceBootstrapContext,\n ): DependencyCheck[] {\n const checks: DependencyCheck[] = [];\n\n if (this.resolveConfig().autoStartMessageBus) {\n checks.push({\n name: 'PubSub',\n check: () => ctx.messageBus.start(),\n successMessage: 'Message bus started',\n });\n }\n\n checks.push({\n name: 'Firestore',\n check: async () => {\n await ctx.firestore.doc('_healthcheck/connection').get();\n },\n });\n\n checks.push({\n name: 'Realtime Database',\n check: async () => {\n await ctx.database.ref('_healthcheck/connection').once('value');\n },\n });\n\n return checks;\n }\n}\n","import admin from 'firebase-admin';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport type { FirebaseAdminLike, Logger } from '../types/config';\n\nexport type FirebaseInitializationOptions = {\n projectId: string;\n databaseURL?: string;\n firestoreEmulatorHost?: string;\n databaseEmulatorHost?: string;\n logger?: Logger;\n _firebaseAdmin?: FirebaseAdminLike;\n};\n\nexport type FirebaseInitResult = {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes Firebase Admin SDK with emulator support.\n */\nexport class FirebaseInitializer {\n private readonly options: FirebaseInitializationOptions;\n\n constructor(options: FirebaseInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator hosts are configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.firestoreEmulatorHost ||\n this.options.databaseEmulatorHost ||\n process.env.FIRESTORE_EMULATOR_HOST ||\n process.env.FIREBASE_DATABASE_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize Firebase Admin and return service handles.\n */\n async initialize(): Promise<FirebaseInitResult> {\n const {\n projectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n logger,\n } = this.options;\n\n if (firestoreEmulatorHost && !process.env.FIRESTORE_EMULATOR_HOST) {\n process.env.FIRESTORE_EMULATOR_HOST = firestoreEmulatorHost;\n }\n\n if (databaseEmulatorHost && !process.env.FIREBASE_DATABASE_EMULATOR_HOST) {\n process.env.FIREBASE_DATABASE_EMULATOR_HOST = databaseEmulatorHost;\n }\n\n const resolvedDatabaseURL =\n databaseURL ?? this.getDatabaseURL(projectId, databaseEmulatorHost);\n\n const firebaseAdmin = this.options._firebaseAdmin ?? admin;\n const app = this.getOrCreateApp(firebaseAdmin, projectId, resolvedDatabaseURL);\n\n safeLog.info(logger, 'Firebase initialized', {\n projectId,\n databaseURL: resolvedDatabaseURL,\n emulatorMode: this.isEmulatorMode(),\n });\n\n const firestore = app.firestore();\n const database = app.database();\n const auth = app.auth();\n\n if (firestoreEmulatorHost) {\n firestore.settings({\n host: firestoreEmulatorHost,\n ssl: false,\n });\n safeLog.info(logger, 'Firestore emulator configured', {\n host: firestoreEmulatorHost,\n });\n }\n\n return { app, firestore, database, auth };\n }\n\n private getOrCreateApp(\n firebaseAdmin: FirebaseAdminLike,\n projectId: string,\n databaseURL: string,\n ): FirebaseAppNamespace.App {\n const apps = (firebaseAdmin.apps ?? []).filter(\n (app): app is FirebaseAppNamespace.App => app !== null,\n );\n\n if (apps.length > 0 && firebaseAdmin.app) {\n safeLog.debug(this.options.logger, 'Reusing existing Firebase app');\n return firebaseAdmin.app();\n }\n\n safeLog.debug(this.options.logger, 'Creating Firebase app');\n return firebaseAdmin.initializeApp(\n {\n projectId,\n databaseURL,\n },\n );\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n}\n","import { PubSub } from '@google-cloud/pubsub';\nimport type { Logger } from '../types/config';\n\nexport type PubSubInitializationOptions = {\n projectId: string;\n emulatorHost?: string;\n logger?: Logger;\n _pubsub?: PubSub;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes PubSub client with optional emulator support.\n */\nexport class PubSubInitializer {\n private readonly options: PubSubInitializationOptions;\n\n constructor(options: PubSubInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator host is configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.emulatorHost || process.env.PUBSUB_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize PubSub client or return injected instance.\n */\n async initialize(): Promise<PubSub> {\n const { projectId, emulatorHost, logger } = this.options;\n\n if (emulatorHost && !process.env.PUBSUB_EMULATOR_HOST) {\n process.env.PUBSUB_EMULATOR_HOST = emulatorHost;\n }\n\n if (this.options._pubsub) {\n safeLog.info(logger, 'Using provided PubSub client', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n });\n return this.options._pubsub;\n }\n\n const pubsub = new PubSub({ projectId });\n\n safeLog.info(logger, 'PubSub initialized', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n emulatorMode: this.isEmulatorMode(),\n });\n\n return pubsub;\n }\n}\n","import { getFirestoreEventStore } from '@emmett-community/emmett-google-firestore';\nimport {\n wireRealtimeDBProjections,\n type RealtimeDBInlineProjectionDefinition,\n} from '@emmett-community/emmett-google-realtime-db';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Database } from 'firebase-admin/database';\nimport type { Logger } from '../types/config';\n\nexport type EventStoreFactoryOptions = {\n firestore: Firestore;\n database: Database;\n projections?: RealtimeDBInlineProjectionDefinition[];\n logger?: Logger;\n};\n\n/**\n * Create a Firestore-backed event store and wire RealtimeDB projections if provided.\n */\nexport const createEventStore = <T extends EventStore = EventStore>(\n options: EventStoreFactoryOptions,\n): T => {\n const { firestore, database, projections, logger } = options;\n const observability = logger ? { logger } : undefined;\n\n const baseEventStore = getFirestoreEventStore(firestore, { observability });\n\n if (projections && projections.length > 0) {\n return wireRealtimeDBProjections({\n eventStore: baseEventStore as unknown as T,\n database,\n projections,\n observability,\n }) as T;\n }\n\n return baseEventStore as unknown as T;\n};\n","import type { DependencyCheck, Logger } from '../types/config';\n\nexport class DependencyTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Dependency check timed out after ${timeoutMs}ms`);\n this.name = 'DependencyTimeoutError';\n }\n}\n\nexport type DependencyCheckResult = {\n name: string;\n ok: boolean;\n required: boolean;\n durationMs: number;\n timedOut: boolean;\n error?: unknown;\n};\n\nexport type DependencyCheckSummary = {\n ok: boolean;\n results: DependencyCheckResult[];\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new DependencyTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Helper for one-off dependency checks with optional logging.\n */\nexport const startDependency = async (\n dependency: string,\n startFn: () => Promise<void>,\n options?: {\n logger?: Logger;\n successMessage?: string;\n timeoutMs?: number;\n },\n): Promise<boolean> => {\n const { logger, successMessage, timeoutMs } = options ?? {};\n const startTime = Date.now();\n\n try {\n await withTimeout(startFn(), timeoutMs);\n logger?.info({ dependency, durationMs: Date.now() - startTime }, successMessage);\n return true;\n } catch (error) {\n logger?.warn(\n { dependency, durationMs: Date.now() - startTime, ...normalizeErrorContext(error) },\n 'Unable to reach dependency',\n );\n return false;\n }\n};\n\n/**\n * Executes dependency checks with optional timeouts.\n */\nexport class DependencyChecker {\n private readonly logger?: Logger;\n private readonly defaultTimeoutMs?: number;\n\n constructor(options?: { logger?: Logger; defaultTimeoutMs?: number }) {\n this.logger = options?.logger;\n this.defaultTimeoutMs = options?.defaultTimeoutMs;\n }\n\n async check(dependency: DependencyCheck): Promise<DependencyCheckResult> {\n const start = Date.now();\n const timeoutMs = dependency.timeoutMs ?? this.defaultTimeoutMs;\n\n try {\n await withTimeout(dependency.check(), timeoutMs);\n\n if (dependency.successMessage) {\n this.logger?.info(\n { dependency: dependency.name, durationMs: Date.now() - start },\n dependency.successMessage,\n );\n }\n\n return {\n name: dependency.name,\n ok: true,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut: false,\n };\n } catch (error) {\n const timedOut = error instanceof DependencyTimeoutError;\n\n this.logger?.warn(\n {\n dependency: dependency.name,\n durationMs: Date.now() - start,\n timedOut,\n ...normalizeErrorContext(error),\n },\n 'Dependency check failed',\n );\n\n return {\n name: dependency.name,\n ok: false,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut,\n error,\n };\n }\n }\n\n async checkAll(dependencies: DependencyCheck[]): Promise<DependencyCheckSummary> {\n const results: DependencyCheckResult[] = [];\n\n for (const dependency of dependencies) {\n results.push(await this.check(dependency));\n }\n\n const ok = results.every((result) => result.ok || !result.required);\n\n return { ok, results };\n }\n}\n","import type { GracefulShutdownConfig, Logger } from '../types/config';\n\nexport class ShutdownTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Shutdown task timed out after ${timeoutMs}ms`);\n this.name = 'ShutdownTimeoutError';\n }\n}\n\nexport type ShutdownTask = {\n name: string;\n close: () => Promise<void>;\n timeoutMs?: number;\n};\n\nexport type ShutdownTaskResult = {\n name: string;\n ok: boolean;\n timedOut: boolean;\n durationMs: number;\n error?: unknown;\n};\n\nexport type GracefulShutdownResult = {\n reason: string;\n exitCode: number;\n tasks: ShutdownTaskResult[];\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new ShutdownTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Runs shutdown tasks with timeout handling and optional exit.\n */\nexport class GracefulShutdown {\n private readonly logger?: Logger;\n private readonly timeoutMs?: number;\n private readonly exitOnComplete: boolean;\n private readonly exitFn: (code: number) => void;\n private readonly tasks: ShutdownTask[] = [];\n private shuttingDown = false;\n private lastResult?: GracefulShutdownResult;\n\n constructor(options?: GracefulShutdownConfig & { logger?: Logger }) {\n this.logger = options?.logger;\n this.timeoutMs = options?.timeoutMs;\n this.exitOnComplete = options?.exitOnComplete ?? false;\n this.exitFn = options?.exitFn ?? process.exit;\n }\n\n /**\n * Register a shutdown task.\n */\n register(task: ShutdownTask): void {\n this.tasks.push(task);\n }\n\n /**\n * Execute all shutdown tasks and return the aggregated result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n if (this.shuttingDown && this.lastResult) {\n return this.lastResult;\n }\n\n this.shuttingDown = true;\n this.logger?.info({ reason }, 'Shutting down gracefully');\n\n const results: ShutdownTaskResult[] = [];\n\n for (const task of this.tasks) {\n const start = Date.now();\n const timeoutMs = task.timeoutMs ?? this.timeoutMs;\n\n try {\n await withTimeout(task.close(), timeoutMs);\n results.push({\n name: task.name,\n ok: true,\n timedOut: false,\n durationMs: Date.now() - start,\n });\n this.logger?.info(\n { task: task.name, durationMs: Date.now() - start },\n 'Shutdown task completed',\n );\n } catch (error) {\n const timedOut = error instanceof ShutdownTimeoutError;\n results.push({\n name: task.name,\n ok: false,\n timedOut,\n durationMs: Date.now() - start,\n error,\n });\n this.logger?.warn(\n {\n task: task.name,\n timedOut,\n durationMs: Date.now() - start,\n ...normalizeErrorContext(error),\n },\n 'Shutdown task failed',\n );\n }\n }\n\n const failed = results.some((result) => !result.ok || result.timedOut);\n const finalExitCode = failed ? exitCode : 0;\n\n if (failed) {\n const failedTasks = results\n .filter((result) => !result.ok || result.timedOut)\n .map((result) => result.name);\n this.logger?.error(\n normalizeContext({ failedTasks }),\n 'Shutdown completed with failures',\n );\n } else {\n this.logger?.info({}, 'Shutdown completed');\n }\n\n const result = { reason, exitCode: finalExitCode, tasks: results };\n this.lastResult = result;\n\n if (this.exitOnComplete) {\n this.exitFn(finalExitCode);\n }\n\n return result;\n }\n}\n","import type { Logger } from '../types/config';\n\nexport type SignalHandlerOptions = {\n shutdown: (reason: string, exitCode?: number) => void | Promise<void>;\n signals?: NodeJS.Signals[];\n logger?: Logger;\n exitCode?: number;\n};\n\n/**\n * Register process signal handlers and return an unregister function.\n */\nexport const registerSignalHandlers = (\n options: SignalHandlerOptions,\n): (() => void) => {\n const signals = options.signals ?? ['SIGINT', 'SIGTERM'];\n const handlers = new Map<NodeJS.Signals, () => void>();\n\n for (const signal of signals) {\n const handler = () => {\n options.logger?.info({ signal }, 'Shutdown signal received');\n void options.shutdown(`Signal ${signal} received`, options.exitCode ?? 0);\n };\n\n handlers.set(signal, handler);\n process.on(signal, handler);\n }\n\n return () => {\n for (const [signal, handler] of handlers.entries()) {\n process.off(signal, handler);\n }\n };\n};\n","export * from './bootstrap';\nexport * from './types';\nexport * from './firebase';\nexport * from './pubsub';\nexport * from './lifecycle';\nexport * from './eventstore';\nexport { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';\nexport {\n ApiE2ESpecification,\n ApiSpecification,\n createFirebaseAuthSecurityHandlers,\n existingStream,\n expectNewEvents,\n expectResponse,\n NoContent,\n OK,\n on,\n type ImportedHandlerModules,\n type TestRequest,\n} from '@emmett-community/emmett-expressjs-with-openapi';\n"],"mappings":"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","names":["normalizeContext","normalizeErrorContext","safeLog","normalizeErrorContext","normalizeContext","normalizeErrorContext","withTimeout","result","normalizeContext","normalizeErrorContext","registerSignalHandlers"]}
|
|
1
|
+
{"version":3,"sources":["../src/bootstrap/ServiceBootstrap.ts","../src/firebase/FirebaseInitializer.ts","../src/pubsub/PubSubInitializer.ts","../src/eventstore/EventStoreFactory.ts","../src/lifecycle/DependencyChecker.ts","../src/lifecycle/GracefulShutdown.ts","../src/lifecycle/SignalHandlers.ts","../src/index.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Application } from 'express';\nimport { createLogger } from '@emmett-community/emmett-observability';\nimport {\n createOpenApiValidatorOptions,\n getApplication,\n startAPI,\n type ApplicationOptions,\n type ImportedHandlerModules,\n type OpenApiValidatorOptions,\n} from '@emmett-community/emmett-expressjs-with-openapi';\nimport {\n getPubSubMessageBus,\n type Logger as PubSubLogger,\n} from '@emmett-community/emmett-google-pubsub';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { PubSub } from '@google-cloud/pubsub';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport { FirebaseInitializer } from '../firebase/FirebaseInitializer';\nimport { PubSubInitializer } from '../pubsub/PubSubInitializer';\nimport { createEventStore } from '../eventstore/EventStoreFactory';\nimport {\n DependencyChecker,\n type DependencyCheckSummary,\n} from '../lifecycle/DependencyChecker';\nimport {\n GracefulShutdown,\n type GracefulShutdownResult,\n} from '../lifecycle/GracefulShutdown';\nimport { registerSignalHandlers } from '../lifecycle/SignalHandlers';\nimport type {\n DependencyCheck,\n Logger as BootstrapLogger,\n MessageBusWithLifecycle,\n ResolvedServiceBootstrapConfig,\n ServiceBootstrapConfig,\n} from '../types/config';\n\n/**\n * Runtime context produced by ServiceBootstrap.\n */\nexport type ServiceBootstrapContext = {\n serviceName: string;\n firebase: {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n };\n firestore: Firestore;\n database: Database;\n auth: Auth;\n pubsub: PubSub;\n eventStore: EventStore;\n messageBus: MessageBusWithLifecycle;\n logger?: BootstrapLogger;\n getCurrentTime: () => Date;\n config: ResolvedServiceBootstrapConfig;\n};\n\n/**\n * Error thrown when required dependencies fail health checks.\n */\nexport class DependencyUnavailableError extends Error {\n readonly summary: DependencyCheckSummary;\n\n constructor(summary: DependencyCheckSummary) {\n const failed = summary.results\n .filter((result) => result.required && !result.ok)\n .map((result) => result.name)\n .join(', ');\n\n super(`Dependency check failed: ${failed}`);\n this.name = 'DependencyUnavailableError';\n this.summary = summary;\n }\n}\n\nexport type CreateAppOptions = {\n openApiPath: string;\n handlersPath: string;\n initializeHandlers: (handlers?: ImportedHandlerModules) => void | Promise<void>;\n openApiOptions?: Partial<\n Omit<\n OpenApiValidatorOptions,\n 'apiSpec' | 'operationHandlers' | 'initializeHandlers'\n >\n >;\n appOptions?: Omit<ApplicationOptions, 'openApiValidator' | 'observability'>;\n};\n\nexport type StartApiOptions = Omit<CreateAppOptions, 'initializeHandlers'> & {\n initializeHandlers: (\n handlers: ImportedHandlerModules | undefined,\n ctx: ServiceBootstrapContext,\n ) => void | Promise<void>;\n port?: number;\n registerSignalHandlers?: boolean;\n beforeStart?: (ctx: ServiceBootstrapContext) => void | Promise<void>;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst createPubSubLogger = (\n logger?: BootstrapLogger,\n): PubSubLogger | undefined => {\n if (!logger) return undefined;\n // Adapter: PubSub logger expects (msg, data), canonical logger uses (context, msg).\n const canonicalLogger = logger as any;\n return {\n debug: (msg, data) => canonicalLogger.debug(normalizeContext(data), msg),\n info: (msg, data) => canonicalLogger.info(normalizeContext(data), msg),\n warn: (msg, data) => canonicalLogger.warn(normalizeContext(data), msg),\n error: (msg, error) =>\n canonicalLogger.error(normalizeErrorContext(error), msg),\n };\n};\n\nconst resolvePath = (inputPath: string): string => {\n return path.isAbsolute(inputPath)\n ? inputPath\n : path.resolve(process.cwd(), inputPath);\n};\n\n/**\n * Orchestrates Firebase, PubSub, event store, and lifecycle utilities.\n */\nexport class ServiceBootstrap {\n private readonly config: ServiceBootstrapConfig;\n private resolvedConfig?: ResolvedServiceBootstrapConfig;\n private logger?: BootstrapLogger;\n private context?: ServiceBootstrapContext;\n private dependencyChecker?: DependencyChecker;\n private shutdownManager?: GracefulShutdown;\n\n constructor(config: ServiceBootstrapConfig) {\n this.config = config;\n }\n\n /**\n * Resolve configuration with defaults and environment variables.\n */\n getConfig(): ResolvedServiceBootstrapConfig {\n return this.resolveConfig();\n }\n\n /**\n * Return the initialized context if available.\n */\n getContext(): ServiceBootstrapContext | undefined {\n return this.context;\n }\n\n /**\n * Register process signal handlers that trigger shutdown.\n */\n registerSignalHandlers(options?: {\n signals?: NodeJS.Signals[];\n exitCode?: number;\n }): () => void {\n return registerSignalHandlers({\n shutdown: async (reason, exitCode) => {\n await this.shutdown(reason, exitCode);\n },\n signals: options?.signals,\n logger: this.getLogger(),\n exitCode: options?.exitCode,\n });\n }\n\n /**\n * Create an Express app using emmett-expressjs-with-openapi defaults.\n */\n async createApp(options: CreateAppOptions) {\n const logger = this.getLogger();\n const openApiValidator = createOpenApiValidatorOptions(\n resolvePath(options.openApiPath),\n {\n ...options.openApiOptions,\n operationHandlers: resolvePath(options.handlersPath),\n initializeHandlers: options.initializeHandlers,\n },\n );\n\n return getApplication({\n ...(options.appOptions ?? {}),\n openApiValidator,\n observability: logger ? { logger } : undefined,\n });\n }\n\n /**\n * Initialize, run dependency checks, create the app, and start the HTTP server.\n */\n async startApi(options: StartApiOptions): Promise<{\n app: Application;\n server: ReturnType<typeof startAPI>;\n context: ServiceBootstrapContext;\n }> {\n const {\n port,\n registerSignalHandlers,\n beforeStart,\n initializeHandlers,\n ...createAppOptions\n } = options;\n\n const logger = this.getLogger();\n\n try {\n const ctx = await this.initialize();\n\n if (beforeStart) {\n await beforeStart(ctx);\n }\n\n if (registerSignalHandlers !== false) {\n this.registerSignalHandlers();\n }\n\n await this.start();\n\n const app = await this.createApp({\n ...createAppOptions,\n initializeHandlers: (handlers) => initializeHandlers(handlers, ctx),\n });\n\n const server = startAPI(app, { port, logger });\n\n this.getShutdownManager().register({\n name: 'httpServer',\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n }),\n });\n\n logger?.info({ port: port ?? 3000 }, 'API server started');\n\n return { app, server, context: ctx };\n } catch (error) {\n logger?.error({ err: error }, 'Startup failed');\n await this.shutdown('Startup failed');\n throw error;\n }\n }\n\n /**\n * Initialize Firebase, PubSub, and event store wiring.\n * Does not execute dependency checks.\n */\n async initialize(): Promise<ServiceBootstrapContext> {\n if (this.context) {\n return this.context;\n }\n\n const resolvedConfig = this.resolveConfig();\n const logger = this.getLogger();\n\n const firebaseInitializer = new FirebaseInitializer({\n projectId: resolvedConfig.firebase.projectId,\n databaseURL: resolvedConfig.firebase.databaseURL,\n firestoreEmulatorHost: resolvedConfig.firebase.firestoreEmulatorHost,\n databaseEmulatorHost: resolvedConfig.firebase.databaseEmulatorHost,\n logger,\n _firebaseAdmin: resolvedConfig._testOverrides?.firebaseAdmin,\n });\n\n const firebase = await firebaseInitializer.initialize();\n\n const firestore = resolvedConfig._testOverrides?.firestore ?? firebase.firestore;\n const database = resolvedConfig._testOverrides?.database ?? firebase.database;\n const auth = resolvedConfig._testOverrides?.auth ?? firebase.auth;\n\n const pubsubInitializer = new PubSubInitializer({\n projectId: resolvedConfig.pubsub.projectId,\n emulatorHost: resolvedConfig.pubsub.emulatorHost,\n logger,\n _pubsub: resolvedConfig._testOverrides?.pubsub,\n });\n\n const pubsub = await pubsubInitializer.initialize();\n\n const eventStore =\n resolvedConfig._testOverrides?.eventStore ??\n createEventStore({\n firestore,\n database,\n projections: resolvedConfig.projections,\n collections: resolvedConfig.eventStore.collections,\n logger,\n });\n\n const messageBus =\n resolvedConfig._testOverrides?.messageBus ??\n getPubSubMessageBus({\n pubsub,\n useEmulator: pubsubInitializer.isEmulatorMode(),\n topicPrefix: resolvedConfig.pubsub.topicPrefix,\n subscriptionOptions: resolvedConfig.pubsub.subscriptionOptions,\n autoCreateResources: resolvedConfig.pubsub.autoCreateResources,\n cleanupOnClose: resolvedConfig.pubsub.cleanupOnClose,\n closePubSubClient: resolvedConfig.pubsub.closePubSubClient,\n observability: { logger: createPubSubLogger(logger) },\n });\n\n this.shutdownManager = new GracefulShutdown({\n ...resolvedConfig.shutdown,\n logger,\n });\n\n this.registerDefaultShutdownTasks({\n messageBus,\n firestore,\n firebaseApp: firebase.app,\n });\n\n this.dependencyChecker = new DependencyChecker({ logger });\n\n this.context = {\n serviceName: resolvedConfig.serviceName,\n firebase: {\n app: firebase.app,\n firestore,\n database,\n auth,\n },\n firestore,\n database,\n auth,\n pubsub,\n eventStore,\n messageBus,\n logger,\n getCurrentTime: resolvedConfig.getCurrentTime,\n config: resolvedConfig,\n };\n\n return this.context;\n }\n\n /**\n * Initialize and run dependency checks before returning context.\n */\n async start(): Promise<ServiceBootstrapContext> {\n const ctx = await this.initialize();\n const resolvedConfig = this.resolveConfig();\n\n const checks: DependencyCheck[] = [];\n\n if (resolvedConfig.includeDefaultDependencyChecks) {\n checks.push(...this.buildDefaultDependencyChecks(ctx));\n }\n\n if (resolvedConfig.dependencies.length > 0) {\n checks.push(...resolvedConfig.dependencies);\n }\n\n if (checks.length > 0) {\n const summary = await this.getDependencyChecker().checkAll(checks);\n\n if (!summary.ok) {\n const error = new DependencyUnavailableError(summary);\n\n this.logger?.error(\n {\n err: error,\n results: summary.results,\n },\n 'Dependency checks failed',\n );\n\n if (resolvedConfig.shutdownOnDependencyFailure) {\n await this.shutdown('Dependency check failed');\n }\n\n throw error;\n }\n }\n\n this.logger?.info(\n { serviceName: resolvedConfig.serviceName },\n 'Service is running',\n );\n\n return ctx;\n }\n\n /**\n * Execute graceful shutdown tasks and return the shutdown result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n return this.getShutdownManager().shutdown(reason, exitCode);\n }\n\n private getLogger(): BootstrapLogger | undefined {\n if (this.logger !== undefined) {\n return this.logger;\n }\n\n const resolvedConfig = this.resolveConfig();\n const observability = resolvedConfig.observability;\n\n if (observability.logger) {\n this.logger = observability.logger;\n return this.logger;\n }\n\n if (observability.createLogger === false) {\n this.logger = undefined;\n return this.logger;\n }\n\n this.logger = createLogger({\n serviceName: resolvedConfig.serviceName,\n environment: observability.environment,\n logLevel: observability.logLevel,\n });\n\n return this.logger;\n }\n\n private resolveConfig(): ResolvedServiceBootstrapConfig {\n if (this.resolvedConfig) {\n return this.resolvedConfig;\n }\n\n const missing: string[] = [];\n\n const serviceName = this.config.serviceName?.trim();\n if (!serviceName) {\n missing.push('serviceName');\n }\n\n const firestoreEmulatorHost =\n this.config.firebase?.firestoreEmulatorHost ??\n process.env.FIRESTORE_EMULATOR_HOST;\n\n const databaseEmulatorHost =\n this.config.firebase?.databaseEmulatorHost ??\n process.env.FIREBASE_DATABASE_EMULATOR_HOST;\n\n const pubsubEmulatorHost =\n this.config.pubsub?.emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST;\n\n const hasEmulator =\n Boolean(firestoreEmulatorHost) ||\n Boolean(databaseEmulatorHost) ||\n Boolean(pubsubEmulatorHost);\n\n const firebaseProjectId =\n this.config.firebase?.projectId ??\n process.env.FIRESTORE_PROJECT_ID ??\n process.env.GCLOUD_PROJECT ??\n process.env.GOOGLE_CLOUD_PROJECT ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!firebaseProjectId) {\n missing.push('firebase.projectId (or FIRESTORE_PROJECT_ID)');\n }\n\n const pubsubProjectId =\n this.config.pubsub?.projectId ??\n process.env.PUBSUB_PROJECT_ID ??\n firebaseProjectId ??\n (hasEmulator ? 'demo-project' : undefined);\n\n if (!pubsubProjectId) {\n missing.push('pubsub.projectId (or PUBSUB_PROJECT_ID)');\n }\n\n if (missing.length > 0) {\n throw new Error(`Missing required configuration: ${missing.join(', ')}`);\n }\n\n const resolvedServiceName = serviceName as string;\n const resolvedFirebaseProjectId = firebaseProjectId as string;\n const resolvedPubsubProjectId = pubsubProjectId as string;\n\n const databaseURL =\n this.config.firebase?.databaseURL ??\n this.getDatabaseURL(resolvedFirebaseProjectId, databaseEmulatorHost);\n\n const observability = {\n ...this.config.observability,\n environment:\n this.config.observability?.environment ?? process.env.NODE_ENV,\n logLevel:\n this.config.observability?.logLevel ??\n (process.env.LOG_LEVEL as\n | 'fatal'\n | 'error'\n | 'warn'\n | 'info'\n | 'debug'\n | 'trace'\n | 'silent'\n | undefined),\n createLogger: this.config.observability?.createLogger ?? true,\n };\n\n const getCurrentTime = this.config.getCurrentTime ?? (() => new Date());\n\n this.resolvedConfig = {\n serviceName: resolvedServiceName,\n firebase: {\n projectId: resolvedFirebaseProjectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n },\n pubsub: {\n projectId: resolvedPubsubProjectId,\n emulatorHost: pubsubEmulatorHost,\n topicPrefix: this.config.pubsub?.topicPrefix ?? resolvedServiceName,\n subscriptionOptions: this.config.pubsub?.subscriptionOptions,\n autoCreateResources: this.config.pubsub?.autoCreateResources ?? true,\n cleanupOnClose: this.config.pubsub?.cleanupOnClose ?? false,\n closePubSubClient: this.config.pubsub?.closePubSubClient ?? true,\n },\n observability,\n projections: this.config.projections ?? [],\n getCurrentTime,\n dependencies: this.config.dependencies ?? [],\n includeDefaultDependencyChecks:\n this.config.includeDefaultDependencyChecks ?? true,\n autoStartMessageBus: this.config.autoStartMessageBus ?? true,\n shutdownOnDependencyFailure:\n this.config.shutdownOnDependencyFailure ?? true,\n shutdown: {\n timeoutMs: this.config.shutdown?.timeoutMs ?? 30000,\n exitOnComplete: this.config.shutdown?.exitOnComplete ?? false,\n exitFn: this.config.shutdown?.exitFn,\n },\n eventStore: {\n collections: this.config.eventStore?.collections,\n },\n _testOverrides: this.config._testOverrides,\n };\n\n return this.resolvedConfig;\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n\n private getDependencyChecker(): DependencyChecker {\n if (!this.dependencyChecker) {\n this.dependencyChecker = new DependencyChecker({ logger: this.getLogger() });\n }\n return this.dependencyChecker;\n }\n\n private getShutdownManager(): GracefulShutdown {\n if (!this.shutdownManager) {\n this.shutdownManager = new GracefulShutdown({\n ...this.resolveConfig().shutdown,\n logger: this.getLogger(),\n });\n }\n return this.shutdownManager;\n }\n\n private registerDefaultShutdownTasks(options: {\n messageBus: MessageBusWithLifecycle;\n firestore: Firestore;\n firebaseApp: FirebaseAppNamespace.App;\n }): void {\n const shutdownManager = this.getShutdownManager();\n\n if (options.messageBus?.close) {\n shutdownManager.register({\n name: 'messageBus',\n close: () => options.messageBus.close(),\n });\n }\n\n if (typeof options.firestore.terminate === 'function') {\n shutdownManager.register({\n name: 'firestore',\n close: () => options.firestore.terminate(),\n });\n }\n\n if (typeof options.firebaseApp.delete === 'function') {\n shutdownManager.register({\n name: 'firebaseApp',\n close: () => options.firebaseApp.delete(),\n });\n }\n }\n\n private buildDefaultDependencyChecks(\n ctx: ServiceBootstrapContext,\n ): DependencyCheck[] {\n const checks: DependencyCheck[] = [];\n\n if (this.resolveConfig().autoStartMessageBus) {\n checks.push({\n name: 'PubSub',\n check: () => ctx.messageBus.start(),\n successMessage: 'Message bus started',\n });\n }\n\n checks.push({\n name: 'Firestore',\n check: async () => {\n await ctx.firestore.doc('_healthcheck/connection').get();\n },\n });\n\n checks.push({\n name: 'Realtime Database',\n check: async () => {\n await ctx.database.ref('_healthcheck/connection').once('value');\n },\n });\n\n return checks;\n }\n}\n","import admin from 'firebase-admin';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Auth } from 'firebase-admin/auth';\nimport type { app as FirebaseAppNamespace } from 'firebase-admin';\nimport type { Database } from 'firebase-admin/database';\nimport type { FirebaseAdminLike, Logger } from '../types/config';\n\nexport type FirebaseInitializationOptions = {\n projectId: string;\n databaseURL?: string;\n firestoreEmulatorHost?: string;\n databaseEmulatorHost?: string;\n logger?: Logger;\n _firebaseAdmin?: FirebaseAdminLike;\n};\n\nexport type FirebaseInitResult = {\n app: FirebaseAppNamespace.App;\n firestore: Firestore;\n database: Database;\n auth: Auth;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes Firebase Admin SDK with emulator support.\n */\nexport class FirebaseInitializer {\n private readonly options: FirebaseInitializationOptions;\n\n constructor(options: FirebaseInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator hosts are configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.firestoreEmulatorHost ||\n this.options.databaseEmulatorHost ||\n process.env.FIRESTORE_EMULATOR_HOST ||\n process.env.FIREBASE_DATABASE_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize Firebase Admin and return service handles.\n */\n async initialize(): Promise<FirebaseInitResult> {\n const {\n projectId,\n databaseURL,\n firestoreEmulatorHost,\n databaseEmulatorHost,\n logger,\n } = this.options;\n\n if (firestoreEmulatorHost && !process.env.FIRESTORE_EMULATOR_HOST) {\n process.env.FIRESTORE_EMULATOR_HOST = firestoreEmulatorHost;\n }\n\n if (databaseEmulatorHost && !process.env.FIREBASE_DATABASE_EMULATOR_HOST) {\n process.env.FIREBASE_DATABASE_EMULATOR_HOST = databaseEmulatorHost;\n }\n\n const resolvedDatabaseURL =\n databaseURL ?? this.getDatabaseURL(projectId, databaseEmulatorHost);\n\n const firebaseAdmin = this.options._firebaseAdmin ?? admin;\n const app = this.getOrCreateApp(firebaseAdmin, projectId, resolvedDatabaseURL);\n\n safeLog.info(logger, 'Firebase initialized', {\n projectId,\n databaseURL: resolvedDatabaseURL,\n emulatorMode: this.isEmulatorMode(),\n });\n\n const firestore = app.firestore();\n const database = app.database();\n const auth = app.auth();\n\n if (firestoreEmulatorHost) {\n firestore.settings({\n host: firestoreEmulatorHost,\n ssl: false,\n });\n safeLog.info(logger, 'Firestore emulator configured', {\n host: firestoreEmulatorHost,\n });\n }\n\n return { app, firestore, database, auth };\n }\n\n private getOrCreateApp(\n firebaseAdmin: FirebaseAdminLike,\n projectId: string,\n databaseURL: string,\n ): FirebaseAppNamespace.App {\n const apps = (firebaseAdmin.apps ?? []).filter(\n (app): app is FirebaseAppNamespace.App => app !== null,\n );\n\n if (apps.length > 0 && firebaseAdmin.app) {\n safeLog.debug(this.options.logger, 'Reusing existing Firebase app');\n return firebaseAdmin.app();\n }\n\n safeLog.debug(this.options.logger, 'Creating Firebase app');\n return firebaseAdmin.initializeApp(\n {\n projectId,\n databaseURL,\n },\n );\n }\n\n private getDatabaseURL(projectId: string, emulatorHost?: string): string {\n if (emulatorHost) {\n return `http://${emulatorHost}?ns=${projectId}`;\n }\n return `https://${projectId}-default-rtdb.firebaseio.com`;\n }\n}\n","import { PubSub } from '@google-cloud/pubsub';\nimport type { Logger } from '../types/config';\n\nexport type PubSubInitializationOptions = {\n projectId: string;\n emulatorHost?: string;\n logger?: Logger;\n _pubsub?: PubSub;\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown): void => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown): void => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Initializes PubSub client with optional emulator support.\n */\nexport class PubSubInitializer {\n private readonly options: PubSubInitializationOptions;\n\n constructor(options: PubSubInitializationOptions) {\n this.options = options;\n }\n\n /**\n * Returns true if emulator host is configured.\n */\n isEmulatorMode(): boolean {\n return Boolean(\n this.options.emulatorHost || process.env.PUBSUB_EMULATOR_HOST,\n );\n }\n\n /**\n * Initialize PubSub client or return injected instance.\n */\n async initialize(): Promise<PubSub> {\n const { projectId, emulatorHost, logger } = this.options;\n\n if (emulatorHost && !process.env.PUBSUB_EMULATOR_HOST) {\n process.env.PUBSUB_EMULATOR_HOST = emulatorHost;\n }\n\n if (this.options._pubsub) {\n safeLog.info(logger, 'Using provided PubSub client', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n });\n return this.options._pubsub;\n }\n\n const pubsub = new PubSub({ projectId });\n\n safeLog.info(logger, 'PubSub initialized', {\n projectId,\n emulatorHost: emulatorHost ?? process.env.PUBSUB_EMULATOR_HOST,\n emulatorMode: this.isEmulatorMode(),\n });\n\n return pubsub;\n }\n}\n","import {\n getFirestoreEventStore,\n type FirestoreEventStoreOptions,\n} from '@emmett-community/emmett-google-firestore';\nimport {\n wireRealtimeDBProjections,\n type RealtimeDBInlineProjectionDefinition,\n} from '@emmett-community/emmett-google-realtime-db';\nimport type { EventStore } from '@event-driven-io/emmett';\nimport type { Firestore } from '@google-cloud/firestore';\nimport type { Database } from 'firebase-admin/database';\nimport type { Logger } from '../types/config';\n\nexport type EventStoreFactoryOptions = {\n firestore: Firestore;\n database: Database;\n projections?: RealtimeDBInlineProjectionDefinition[];\n logger?: Logger;\n collections?: FirestoreEventStoreOptions['collections'];\n};\n\n/**\n * Create a Firestore-backed event store and wire RealtimeDB projections if provided.\n */\nexport const createEventStore = <T extends EventStore = EventStore>(\n options: EventStoreFactoryOptions,\n): T => {\n const { firestore, database, projections, logger, collections } = options;\n const observability = logger ? { logger } : undefined;\n\n const baseEventStore = getFirestoreEventStore(firestore, {\n observability,\n collections,\n });\n\n if (projections && projections.length > 0) {\n return wireRealtimeDBProjections({\n eventStore: baseEventStore as unknown as T,\n database,\n projections,\n observability,\n }) as T;\n }\n\n return baseEventStore as unknown as T;\n};\n","import type { DependencyCheck, Logger } from '../types/config';\n\nexport class DependencyTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Dependency check timed out after ${timeoutMs}ms`);\n this.name = 'DependencyTimeoutError';\n }\n}\n\nexport type DependencyCheckResult = {\n name: string;\n ok: boolean;\n required: boolean;\n durationMs: number;\n timedOut: boolean;\n error?: unknown;\n};\n\nexport type DependencyCheckSummary = {\n ok: boolean;\n results: DependencyCheckResult[];\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new DependencyTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Helper for one-off dependency checks with optional logging.\n */\nexport const startDependency = async (\n dependency: string,\n startFn: () => Promise<void>,\n options?: {\n logger?: Logger;\n successMessage?: string;\n timeoutMs?: number;\n },\n): Promise<boolean> => {\n const { logger, successMessage, timeoutMs } = options ?? {};\n const startTime = Date.now();\n\n try {\n await withTimeout(startFn(), timeoutMs);\n logger?.info({ dependency, durationMs: Date.now() - startTime }, successMessage);\n return true;\n } catch (error) {\n logger?.warn(\n { dependency, durationMs: Date.now() - startTime, ...normalizeErrorContext(error) },\n 'Unable to reach dependency',\n );\n return false;\n }\n};\n\n/**\n * Executes dependency checks with optional timeouts.\n */\nexport class DependencyChecker {\n private readonly logger?: Logger;\n private readonly defaultTimeoutMs?: number;\n\n constructor(options?: { logger?: Logger; defaultTimeoutMs?: number }) {\n this.logger = options?.logger;\n this.defaultTimeoutMs = options?.defaultTimeoutMs;\n }\n\n async check(dependency: DependencyCheck): Promise<DependencyCheckResult> {\n const start = Date.now();\n const timeoutMs = dependency.timeoutMs ?? this.defaultTimeoutMs;\n\n try {\n await withTimeout(dependency.check(), timeoutMs);\n\n if (dependency.successMessage) {\n this.logger?.info(\n { dependency: dependency.name, durationMs: Date.now() - start },\n dependency.successMessage,\n );\n }\n\n return {\n name: dependency.name,\n ok: true,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut: false,\n };\n } catch (error) {\n const timedOut = error instanceof DependencyTimeoutError;\n\n this.logger?.warn(\n {\n dependency: dependency.name,\n durationMs: Date.now() - start,\n timedOut,\n ...normalizeErrorContext(error),\n },\n 'Dependency check failed',\n );\n\n return {\n name: dependency.name,\n ok: false,\n required: dependency.required ?? true,\n durationMs: Date.now() - start,\n timedOut,\n error,\n };\n }\n }\n\n async checkAll(dependencies: DependencyCheck[]): Promise<DependencyCheckSummary> {\n const results: DependencyCheckResult[] = [];\n\n for (const dependency of dependencies) {\n results.push(await this.check(dependency));\n }\n\n const ok = results.every((result) => result.ok || !result.required);\n\n return { ok, results };\n }\n}\n","import type { GracefulShutdownConfig, Logger } from '../types/config';\n\nexport class ShutdownTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Shutdown task timed out after ${timeoutMs}ms`);\n this.name = 'ShutdownTimeoutError';\n }\n}\n\nexport type ShutdownTask = {\n name: string;\n close: () => Promise<void>;\n timeoutMs?: number;\n};\n\nexport type ShutdownTaskResult = {\n name: string;\n ok: boolean;\n timedOut: boolean;\n durationMs: number;\n error?: unknown;\n};\n\nexport type GracefulShutdownResult = {\n reason: string;\n exitCode: number;\n tasks: ShutdownTaskResult[];\n};\n\nconst normalizeContext = (data: unknown): Record<string, unknown> => {\n if (data === undefined || data === null) return {};\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n};\n\nconst normalizeErrorContext = (error: unknown): Record<string, unknown> => {\n if (error === undefined || error === null) return {};\n if (error instanceof Error) return { err: error };\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n};\n\nconst withTimeout = async <T>(promise: Promise<T>, timeoutMs?: number): Promise<T> => {\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n let timeoutId: NodeJS.Timeout | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new ShutdownTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\n/**\n * Runs shutdown tasks with timeout handling and optional exit.\n */\nexport class GracefulShutdown {\n private readonly logger?: Logger;\n private readonly timeoutMs?: number;\n private readonly exitOnComplete: boolean;\n private readonly exitFn: (code: number) => void;\n private readonly tasks: ShutdownTask[] = [];\n private shuttingDown = false;\n private lastResult?: GracefulShutdownResult;\n\n constructor(options?: GracefulShutdownConfig & { logger?: Logger }) {\n this.logger = options?.logger;\n this.timeoutMs = options?.timeoutMs;\n this.exitOnComplete = options?.exitOnComplete ?? false;\n this.exitFn = options?.exitFn ?? process.exit;\n }\n\n /**\n * Register a shutdown task.\n */\n register(task: ShutdownTask): void {\n this.tasks.push(task);\n }\n\n /**\n * Execute all shutdown tasks and return the aggregated result.\n */\n async shutdown(reason: string, exitCode = 1): Promise<GracefulShutdownResult> {\n if (this.shuttingDown && this.lastResult) {\n return this.lastResult;\n }\n\n this.shuttingDown = true;\n this.logger?.info({ reason }, 'Shutting down gracefully');\n\n const results: ShutdownTaskResult[] = [];\n\n for (const task of this.tasks) {\n const start = Date.now();\n const timeoutMs = task.timeoutMs ?? this.timeoutMs;\n\n try {\n await withTimeout(task.close(), timeoutMs);\n results.push({\n name: task.name,\n ok: true,\n timedOut: false,\n durationMs: Date.now() - start,\n });\n this.logger?.info(\n { task: task.name, durationMs: Date.now() - start },\n 'Shutdown task completed',\n );\n } catch (error) {\n const timedOut = error instanceof ShutdownTimeoutError;\n results.push({\n name: task.name,\n ok: false,\n timedOut,\n durationMs: Date.now() - start,\n error,\n });\n this.logger?.warn(\n {\n task: task.name,\n timedOut,\n durationMs: Date.now() - start,\n ...normalizeErrorContext(error),\n },\n 'Shutdown task failed',\n );\n }\n }\n\n const failed = results.some((result) => !result.ok || result.timedOut);\n const finalExitCode = failed ? exitCode : 0;\n\n if (failed) {\n const failedTasks = results\n .filter((result) => !result.ok || result.timedOut)\n .map((result) => result.name);\n this.logger?.error(\n normalizeContext({ failedTasks }),\n 'Shutdown completed with failures',\n );\n } else {\n this.logger?.info({}, 'Shutdown completed');\n }\n\n const result = { reason, exitCode: finalExitCode, tasks: results };\n this.lastResult = result;\n\n if (this.exitOnComplete) {\n this.exitFn(finalExitCode);\n }\n\n return result;\n }\n}\n","import type { Logger } from '../types/config';\n\nexport type SignalHandlerOptions = {\n shutdown: (reason: string, exitCode?: number) => void | Promise<void>;\n signals?: NodeJS.Signals[];\n logger?: Logger;\n exitCode?: number;\n};\n\n/**\n * Register process signal handlers and return an unregister function.\n */\nexport const registerSignalHandlers = (\n options: SignalHandlerOptions,\n): (() => void) => {\n const signals = options.signals ?? ['SIGINT', 'SIGTERM'];\n const handlers = new Map<NodeJS.Signals, () => void>();\n\n for (const signal of signals) {\n const handler = () => {\n options.logger?.info({ signal }, 'Shutdown signal received');\n void options.shutdown(`Signal ${signal} received`, options.exitCode ?? 0);\n };\n\n handlers.set(signal, handler);\n process.on(signal, handler);\n }\n\n return () => {\n for (const [signal, handler] of handlers.entries()) {\n process.off(signal, handler);\n }\n };\n};\n","export * from './bootstrap';\nexport * from './types';\nexport * from './firebase';\nexport * from './pubsub';\nexport * from './lifecycle';\nexport * from './eventstore';\nexport { realtimeDBInlineProjection } from '@emmett-community/emmett-google-realtime-db';\nexport {\n ApiE2ESpecification,\n ApiSpecification,\n createFirebaseAuthSecurityHandlers,\n existingStream,\n expectNewEvents,\n expectResponse,\n NoContent,\n OK,\n on,\n type ImportedHandlerModules,\n type TestRequest,\n} from '@emmett-community/emmett-expressjs-with-openapi';\n"],"mappings":"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","names":["normalizeContext","normalizeErrorContext","safeLog","normalizeErrorContext","normalizeContext","normalizeErrorContext","withTimeout","result","normalizeContext","normalizeErrorContext","registerSignalHandlers"]}
|