@hubert.legec/firestore-storage-nest
v0.0.8
Published
A NestJS module that simplifies integration with Firestore database and makes testing easier
Maintainers
Readme
firestore-storage-nest
A NestJS module for easy integration with Firestore in NestJS applications, built for use with firestore-storage v7. It provides a shared Firestore instance via dependency injection and, for tests, an in-memory Firestore so you can run tests without the Firebase Emulator.
Published on npm.
Features
- Production: Register Firestore once with
forRootAsyncand inject it anywhere with@Inject(FIRESTORE). - Testing: Use
withMemoryStorage()for an in-memory Firestore (powered by @firebase-bridge/firestore-admin, Apache-2.0). No emulator required. - Repository helpers:
EntityRepository,ModelTransformer, and path helpers (pathToDocumentIds,pathToCollectionIds) for building repositories on top of firestore-storage v7.
Installation
pnpm add firestore-storage-nest firestore-storage firestore-storage-core @google-cloud/firestore
# or
npm i firestore-storage-nest firestore-storage firestore-storage-core @google-cloud/firestoreFor tests using the built-in in-memory Firestore, also install the optional dependency:
pnpm add -D @firebase-bridge/firestore-admin
# or rely on the package’s optional dependencyPeer dependencies: @nestjs/common (≥10), @google-cloud/firestore (≥6), firestore-storage (≥7), firestore-storage-core (≥7).
Production usage
Register the module with your Firestore instance (e.g. from firebase-admin):
import { Module } from "@nestjs/common";
import { FirestoreStorageNestModule, FIRESTORE } from "firestore-storage-nest";
import { getFirestore } from "firebase-admin/firestore";
@Module({
imports: [
{
...FirestoreStorageNestModule.forRootAsync({
useFactory: () => getFirestore(),
}),
global: true,
},
],
})
export class AppModule {}Inject the Firestore instance where needed:
import { Inject, Injectable } from "@nestjs/common";
import { FIRESTORE } from "firestore-storage-nest";
import type { Firestore } from "@google-cloud/firestore";
@Injectable()
export class MyService {
constructor(@Inject(FIRESTORE) private readonly firestore: Firestore) {}
}Testing with in-memory Firestore
Use the built-in in-memory Firestore so tests don’t need the Firebase Emulator:
import { Test } from "@nestjs/testing";
import {
FirestoreStorageNestModule,
TestFirestoreClearService,
} from "firestore-storage-nest";
const module = await Test.createTestingModule({
imports: [FirestoreStorageNestModule.withMemoryStorage()],
// ... your providers
}).compile();
// In beforeEach: clear collections between tests
const clearService = module.get(TestFirestoreClearService);
await clearService.clear("users");
await clearService.clear("posts");For a custom in-memory instance, use:
FirestoreStorageNestModule.withMemoryStorage({
useFactory: () => yourCustomFirestore,
})createMemoryFirestore() from this package returns a real Firestore-compatible instance (from @firebase-bridge/firestore-admin).
Running tests against the Firebase Emulator
To confirm compatibility with real Firestore, run the same test suite against the Firestore emulator:
- Start the emulator:
firebase emulators:start --only firestore(default port 8080). - Run tests with the emulator:
FIRESTORE_EMULATOR_HOST=localhost:8080 pnpm test(ornpm run test:emulatorif you add that script).
The package’s integration tests use a helper that switches to the emulator when FIRESTORE_EMULATOR_HOST is set, so the same tests run with in-memory Firestore by default and with the emulator when that env var is set.
Repository helpers
EntityRepository<E, M>– Abstract base for entity repositories (varargs API over firestore-storage v7).ModelTransformer<E, M>– Interface for converting between entityEand firestore-storage modelM.pathToDocumentIds(path, ids)/pathToCollectionIds(path, ids)– Build v7DocumentIds/CollectionIdsfrom an ordered list of ids.Id– Type alias for entity id (string).
API summary
| Export | Description |
|--------|-------------|
| FIRESTORE | Injection token for the Firestore instance |
| FirestoreStorageNestModule | Module with forRootAsync(options) and withMemoryStorage(options?) |
| TestFirestoreClearService | Service to clear collections in tests |
| createMemoryFirestore() | Returns an in-memory Firestore instance |
| EntityRepository, ModelTransformer, pathToDocumentIds, pathToCollectionIds, Id | Repository and path helpers |
Development
From the repo:
pnpm test– run tests (in-memory Firestore).pnpm test:emulator– run the same tests against the Firestore emulator (setFIRESTORE_EMULATOR_HOST=localhost:8080; start the emulator first).
The tests in test/ demonstrate root and nested entity CRUD (create, update, fetch, list, delete) using EntityRepository, withMemoryStorage, and TestFirestoreClearService.
Releasing
Releases are automated via GitHub Actions (.github/workflows/release.yml). To publish:
- Set the version in
package.json(e.g.0.0.2). - Commit, push to
main, then create and push a tag matching that version:git tag v0.0.2 && git push origin v0.0.2.
The workflow will: publish the package to npm (using the version in package.json), create a GitHub Release from the tag with generated release notes, then bump the version on main (patch increment) and push the commit.
Required: Add an NPM_TOKEN repository secret (Settings → Secrets and variables → Actions). Use an npm automation token or granular access token with “Publish packages” permission.
License
MIT
