@emmett-community/emmett-google-services-bootstrap 0.1.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 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, { observability });
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;
@@ -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 { getFirestoreEventStore } from "@emmett-community/emmett-google-firestore";
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, { observability });
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"]}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@emmett-community/emmett-google-services-bootstrap",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
- "description": "Service bootstrap for event-driven apps using Google Cloud (Firebase, PubSub)",
7
+ "description": "Service bootstrap for event-driven apps using Google Cloud (Firestore, Realtime DB, PubSub)",
8
8
  "scripts": {
9
9
  "build": "tsup",
10
10
  "build:ts": "tsc",
@@ -57,20 +57,21 @@
57
57
  "dist"
58
58
  ],
59
59
  "dependencies": {
60
- "@event-driven-io/emmett": "^0.39.0",
61
- "@emmett-community/emmett-google-firestore": "^0.4.0",
62
- "@emmett-community/emmett-google-pubsub": "^0.3.0",
63
- "@emmett-community/emmett-google-realtime-db": "^0.5.0",
60
+ "@emmett-community/emmett-expressjs-with-openapi": "^0.8.0",
61
+ "@emmett-community/emmett-google-firestore": "^0.5.0",
62
+ "@emmett-community/emmett-google-pubsub": "^0.4.0",
63
+ "@emmett-community/emmett-google-realtime-db": "^0.7.0",
64
64
  "@emmett-community/emmett-observability": "^0.3.0",
65
- "@emmett-community/emmett-expressjs-with-openapi": "^0.7.0",
65
+ "@event-driven-io/emmett": "^0.39.0",
66
66
  "@google-cloud/pubsub": "^4.9.0",
67
+ "@my-f-startup/firebase-auth-express": "^0.1.0",
67
68
  "express": "^4.19.2",
68
69
  "express-async-errors": "^3.1.1",
69
70
  "express-openapi-validator": "^5.6.0",
70
71
  "firebase-admin": "^13.6.0",
71
- "@my-f-startup/firebase-auth-express": "^0.1.0",
72
72
  "http-problem-details": "^0.1.7",
73
- "pino-http": "^9.0.0"
73
+ "pino-http": "^9.0.0",
74
+ "pino-pretty": "^13.1.3"
74
75
  },
75
76
  "devDependencies": {
76
77
  "@types/express": "^4.17.21",