@emmett-community/emmett-google-services-bootstrap
v0.3.0
Published
Service bootstrap for event-driven apps using Google Cloud (Firestore, Realtime DB, PubSub)
Downloads
259
Maintainers
Readme
@emmett-community/emmett-google-services-bootstrap
Service bootstrap for event-driven apps using Google Cloud. This package wires Firebase Admin, Firestore event store, Realtime DB projections, PubSub message bus, and lifecycle utilities so services can start with minimal boilerplate.
Features
- ✅ One orchestrator to initialize Firebase, PubSub, and event store wiring
- ✅ Realtime DB projections hooked automatically
- ✅ Built-in dependency checks and graceful shutdown
- ✅ OpenAPI-ready app creation with sensible defaults
- ✅ Auth security handlers available without extra service deps
- ✅ No side effects on import
Why this package exists
Most Emmett services repeat the same bootstrap work: Firebase Admin init, Firestore event store setup, PubSub wiring, and shutdown logic. This package centralizes that boilerplate into a single, explicit orchestrator.
How it relates to other emmett-community packages
- It is for application entrypoints (service
index.ts). - It composes existing packages (firestore, pubsub, realtime-db, observability, expressjs-with-openapi).
- It keeps domain code untouched and wiring centralized.
Installation
npm install @emmett-community/emmett-google-services-bootstrapMinimal service dependencies:
{
"dependencies": {
"@emmett-community/emmett-google-services-bootstrap": "^0.1.0"
},
"devDependencies": {
"@types/express": "^4.17.21"
}
}Quick start
import { ServiceBootstrap } from '@emmett-community/emmett-google-services-bootstrap';
import { userDetailsProjection } from './projections/userDetailsProjection';
import { setupUserDataRemovalSubscriber } from './subscriptions/userDataRemovalSubscriber';
const bootstrap = new ServiceBootstrap({
serviceName: 'user-service',
projections: [userDetailsProjection],
});
await bootstrap.startApi({
port: Number(process.env.PORT ?? 3000),
openApiPath: './openapi.yml',
handlersPath: './handlers',
initializeHandlers: (handlers, ctx) => {
handlers.users.initializeHandlers(
ctx.eventStore,
ctx.database,
ctx.messageBus,
ctx.getCurrentTime,
);
},
beforeStart: (ctx) => {
setupUserDataRemovalSubscriber({
eventStore: ctx.eventStore,
messageBus: ctx.messageBus,
auth: ctx.auth,
getCurrentTime: ctx.getCurrentTime,
});
},
});Configuration
Environment variables
FIRESTORE_PROJECT_ID: Firebase project id (fallback toGCLOUD_PROJECT/GOOGLE_CLOUD_PROJECT)demo-projectfallback: if project id is missing and any emulator host is configured, defaults todemo-project(also used for PubSub)FIRESTORE_EMULATOR_HOST: Firestore emulator hostFIREBASE_DATABASE_EMULATOR_HOST: Realtime DB emulator hostPUBSUB_PROJECT_ID: PubSub project idPUBSUB_EMULATOR_HOST: PubSub emulator hostLOG_LEVEL: default log level for built-in loggerNODE_ENV: forwarded to logging helpers
Options
import type { ServiceBootstrapConfig } from '@emmett-community/emmett-google-services-bootstrap';
const config: ServiceBootstrapConfig = {
serviceName: 'user-service',
firebase: {
projectId: 'demo-project',
databaseURL: 'https://demo-project-default-rtdb.firebaseio.com',
},
pubsub: {
projectId: 'demo-project',
topicPrefix: 'user-service',
autoCreateResources: true,
},
eventStore: {
collections: {
streams: 'user-service-streams',
counters: '_user-service-counters',
},
},
projections: [],
observability: {
createLogger: true,
logLevel: 'info',
},
includeDefaultDependencyChecks: true,
autoStartMessageBus: true,
shutdownOnDependencyFailure: true,
};Event store collection names
eventStore.collections.streams: Firestore collection that stores stream metadata (defaults to"streams").eventStore.collections.counters: Firestore collection for shared counters (defaults to"_counters").
API
ServiceBootstrap
initialize()initializes Firebase, PubSub, and the event store.start()runs dependency checks and returns the same context asinitialize().createApp()returns an Express app wired with OpenAPI validation.shutdown(reason, exitCode?)runs graceful shutdown tasks.registerSignalHandlers()installs SIGINT/SIGTERM handlers.startApi()initializes, runs checks, creates the app, and starts the HTTP server.
Lifecycle utilities
DependencyCheckerandstartDependency()for health checks.GracefulShutdownfor ordered shutdown tasks.registerSignalHandlers()to attach process signals.
What this package intentionally does NOT do
- Hide application infrastructure choices behind magic defaults
- Create domain handlers or business rules
- Start HTTP servers automatically (use
startApi()if you want the helper) - Require any specific deployment model
Testing
npm run test:unit
npm run test:int
npm run test:e2eContributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Made with ❤️ by the Emmett Community
