@emmett-community/emmett-google-services-bootstrap 0.2.0 → 0.4.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/emmett-google-services-bootstrap/emmett-google-services-bootstrap/dist/chunk-G3V6OOZL.cjs","../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/bootstrap/ServiceBootstrap.ts"],"names":["result","registerSignalHandlers"],"mappings":"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","file":"/home/runner/work/emmett-google-services-bootstrap/emmett-google-services-bootstrap/dist/chunk-G3V6OOZL.cjs","sourcesContent":[null,"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 asEventStore,\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 = asEventStore(\n getFirestoreEventStore(firestore, {\n observability,\n collections,\n }),\n ) as unknown as T;\n\n if (projections && projections.length > 0) {\n return wireRealtimeDBProjections({\n eventStore: baseEventStore,\n database,\n projections,\n observability,\n }) as T;\n }\n\n return baseEventStore;\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 * Register a shutdown task that runs before the ones already registered.\n */\n registerFirst(task: ShutdownTask): void {\n this.tasks.unshift(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","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 { getPubSubMessageBus } 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 * Runs the readiness checks (the same dependencies the startup checks, without starting the\n * message bus again). Used by the `/ready` handler.\n */\n checkReadiness: () => Promise<DependencyCheckSummary>;\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 READINESS_CHECK_TIMEOUT_MS = 3000;\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 // Closed before everything else, so no request reaches a store that is already closing\n this.getShutdownManager().registerFirst({\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 // Event subscriptions are shared by the replicas of the service and survive restarts\n subscriptionId: resolvedConfig.pubsub.subscriptionId,\n // Command subscriptions are shared too, so a command has one handler\n instanceId: resolvedConfig.pubsub.subscriptionId,\n subscriptionOptions: resolvedConfig.pubsub.subscriptionOptions,\n autoCreateResources: resolvedConfig.pubsub.autoCreateResources,\n cleanupOnClose: resolvedConfig.pubsub.cleanupOnClose,\n closePubSubClient: resolvedConfig.pubsub.closePubSubClient,\n observability: { 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 checkReadiness: () => this.checkReadiness(),\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 * Run the readiness checks: the stores and the message bus must answer, plus the configured\n * dependencies. A hung dependency fails the check instead of hanging the probe.\n */\n async checkReadiness(): Promise<DependencyCheckSummary> {\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.buildStoreDependencyChecks(ctx));\n\n if (resolvedConfig.autoStartMessageBus) {\n checks.push({\n name: 'PubSub',\n check: async () => {\n if (!ctx.messageBus.isStarted?.()) {\n throw new Error('Message bus is not started');\n }\n },\n });\n }\n }\n\n checks.push(...resolvedConfig.dependencies);\n\n return this.getDependencyChecker().checkAll(\n checks.map((check) => ({\n ...check,\n timeoutMs: check.timeoutMs ?? READINESS_CHECK_TIMEOUT_MS,\n })),\n );\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:\n this.config.pubsub?.topicPrefix ??\n process.env.PUBSUB_TOPIC_PREFIX ??\n resolvedServiceName,\n subscriptionId:\n this.config.pubsub?.subscriptionId ?? 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 includeRealtimeDatabaseCheck:\n this.config.includeRealtimeDatabaseCheck ?? 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(...this.buildStoreDependencyChecks(ctx));\n\n return checks;\n }\n\n private buildStoreDependencyChecks(\n ctx: ServiceBootstrapContext,\n ): DependencyCheck[] {\n const checks: DependencyCheck[] = [\n {\n name: 'Firestore',\n check: async () => {\n await ctx.firestore.collection('_healthcheck').limit(1).get();\n },\n },\n ];\n\n if (this.resolveConfig().includeRealtimeDatabaseCheck) {\n checks.push({\n name: 'Realtime Database',\n check: async () => {\n await ctx.database.ref('_healthcheck/connection').once('value');\n },\n });\n }\n\n return checks;\n }\n}\n"]}