@ecsbase/firebase
v1.0.0
Published
@ecsbase/firebase — reusable building block.
Readme
@ecsbase/firebase
Brand-agnostic Firebase Firestore toolkit: a typed DataService with retry,
a pluggable read-through CacheDataService, a date-partitioned path helper,
and an InjectionToken-based path registry for multi-project apps.
Works in both Angular 20 (DI) and plain Node.js (manual instantiation).
Install
pnpm add @ecsbase/firebase @angular/fire firebasePeer dependencies
@angular/common^20.0.0@angular/core^20.0.0@angular/fire^20.0.0@ecsbase/utilsworkspace:*firebase^11.0.0
Quick start — Angular
import { ApplicationConfig } from '@angular/core';
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { getFirestore } from 'firebase/firestore';
import {
provideEcsbaseFirestore,
provideFirestorePaths,
provideCacheAdapter,
DataService,
CacheDataService,
} from '@ecsbase/firebase';
import { IndexedDbCacheAdapter } from '@ecsbase/firebase/indexeddb';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ /* config */ })),
// Register Firestore under the brand-agnostic ECSBASE_FIRESTORE token.
// Do NOT use @angular/fire's `provideFirestore()` here — its `Firestore`
// class identity differs from `firebase/firestore`'s, breaking DataService DI.
provideEcsbaseFirestore(() => getFirestore()),
provideFirestorePaths({
clients: 'clients',
orders: 'tenants/{tid}/orders',
}),
provideCacheAdapter(() => new IndexedDbCacheAdapter()),
],
};
// Anywhere
constructor(
private data: DataService,
private cached: CacheDataService,
) {}
await this.data.list('clients');
await this.cached.read('clients/abc', 60_000);Quick start — Node.js
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { DataService, CacheDataService, InMemoryCacheAdapter } from '@ecsbase/firebase';
const app = initializeApp({
/* config */
});
const data = DataService.create(getFirestore(app));
const cached = CacheDataService.create(data, new InMemoryCacheAdapter());
await data.list('clients');Cache adapters
InMemoryCacheAdapter— default; Node/browser/SSR safeIndexedDbCacheAdapter— browser-only, persistent (import from@ecsbase/firebase/indexeddb)- Implement
CacheAdapterfor custom storage (Redis, file, etc.)
Models
All read / list results carry id and path automatically. Define your
Firestore models against the exported dbObject base type so updates and
deletes can use the document's own path:
import type { dbObject } from '@ecsbase/firebase';
export class Client implements dbObject {
id = '';
path = '';
name = '';
}DataService.read<T> and DataService.list<T> default T to dbObject, so
omitting the explicit type still yields { id, path } on every record.
Multi-project
Use DataServiceFactory when one app talks to multiple Firestore instances:
import { provideDataServices, DataServiceFactory } from '@ecsbase/firebase';
providers: [provideDataServices({ tenant: tenantFs, shared: sharedFs })];
// ...
constructor(f: DataServiceFactory) {
f.for('tenant').read('clients/abc');
f.forCached('shared').list('catalog');
}Date-partitioned paths
import { buildDayPath, buildMonthPath } from '@ecsbase/firebase';
buildDayPath('events', Date.now()); // 'events/2026/05/21' (UTC)
buildMonthPath('logs', Date.now(), 'America/New_York');API
DataService—read,list,create,set,update,delete,batchSet,resolvePathCacheDataService— same surface plus TTL,invalidate,invalidatePrefixCacheMetricsService— signals:hits,misses,writes,hitRatedbObject— base type for Firestore models (id,path)provideFirestorePaths,FIRESTORE_PATHSprovideCacheAdapter,CACHE_ADAPTER,InMemoryCacheAdapterprovideDataService,DATA_SERVICE_CONFIG— retry tuningprovideDataServices,DataServiceFactory— multi-projectbuildDayPath,buildMonthPath,buildYearPath,DatePathFormatter
Inputs / Outputs
| Name | Type | Default | Description | | ---- | ---- | ------- | ----------- |
Playground
Live demos:
- /firebase — provider
- cache adapter walkthrough.
- /firebase-live —
full CRUD against the shared
ecs-baseFirestore project. Cross-validate from Node withpnpm test-firebase(see docs/testing-guide.md).
Run pnpm start:playground then visit http://localhost:4200/firebase.
License
MIT — see LICENSE at the repository root.
