Firebase integration for Effect. Provides schemas, models, repositories, and Cloud Functions helpers built on Effect's type system.
Warning
Main contains the beta for 1.0, currently in active development.
| Package | Description |
|---|---|
| effect-firebase | Core schemas, models, and query builder |
| @effect-firebase/admin | Firebase Admin SDK + Cloud Functions |
| @effect-firebase/client | Firebase Client SDK |
| @effect-firebase/mock | In-memory mock for testing |
- React patterns — atoms, live queries, mutations, forms, and testing from React
- Migration guide — upgrading from earlier versions
npm install effect-firebase effect
# Pick one or more SDK packages:
npm install @effect-firebase/admin firebase-admin firebase-functions
npm install @effect-firebase/client firebase
npm install --save-dev @effect-firebase/mockimport { Schema } from 'effect';
import { Model } from 'effect-firebase';
const PostId = Schema.String.pipe(Schema.brand('PostId'));
const AuthorId = Schema.String.pipe(Schema.brand('AuthorId'));
class PostModel extends Model.Class<PostModel>('PostModel')({
id: Model.GeneratedByDb(PostId),
createdAt: Model.DateTimeInsert,
updatedAt: Model.DateTimeUpdate,
author: Model.Reference(AuthorId, 'authors'),
title: Schema.String,
content: Schema.String,
status: Schema.Literal('draft', 'published'),
}) {}import { Effect } from 'effect';
import { Model, Query } from 'effect-firebase';
export const PostRepository = Model.makeRepository(PostModel, {
collectionPath: 'posts',
idField: 'id',
spanPrefix: 'PostRepository',
}).pipe(
Effect.map((repo) => ({
...repo,
published: () =>
repo.queryStream(
Query.and(
Query.where('status', '==', 'published'),
Query.orderBy('createdAt', 'desc')
)
),
}))
);import { Effect } from 'effect';
import { initializeApp } from 'firebase/app';
import { Client } from '@effect-firebase/client';
const program = Effect.gen(function* () {
const repo = yield* PostRepository;
const postId = yield* repo.add({
title: 'Hello',
content: '...',
status: 'draft',
});
const posts = yield* repo.query(Query.where('status', '==', 'published'));
return { postId, posts };
}).pipe(
Effect.provide(PostRepository),
Effect.provide(
Client.layer({ app: initializeApp({ projectId: 'my-project' }) })
)
);import { Effect } from 'effect';
import { Firestore } from 'effect-firebase';
// Atomic read-modify-write across repositories
Firestore.withTransaction(
Effect.gen(function* () {
const repo = yield* PostRepository;
const post = yield* repo.getById(postId);
yield* repo.update(postId, { status: 'published' });
})
);
// Stage many writes and commit them atomically
Firestore.withBatch(
Effect.gen(function* () {
const repo = yield* PostRepository;
yield* Effect.forEach(ids, (id) => repo.update(id, { status: 'archived' }));
})
);import { Effect, Layer } from 'effect';
import { initializeApp } from 'firebase-admin/app';
import { Admin, FunctionsRuntime, onCallEffect } from '@effect-firebase/admin';
const runtime = FunctionsRuntime.make(
Layer.mergeAll(Admin.layer({ app: initializeApp() }), PostRepository)
);
export const createPost = onCallEffect({ runtime }, (request) =>
Effect.gen(function* () {
const repo = yield* PostRepository;
const postId = yield* repo.add({
title: request.data.title,
content: request.data.content,
author: AuthorId.make(request.auth!.uid),
status: 'draft',
});
return { postId };
})
);import { Effect } from 'effect';
import { layer as mockFirestore } from '@effect-firebase/mock';
await Effect.runPromise(
Effect.gen(function* () {
const repo = yield* PostRepository;
const postId = yield* repo.add({
title: 'Test',
content: '...',
status: 'draft',
});
const post = yield* repo.getById(postId);
expect(post.title).toBe('Test');
}).pipe(Effect.provide(PostRepository), Effect.provide(mockFirestore))
);@effect-firebase/admin provides Effect wrappers for all major Cloud Functions trigger types:
onRequestEffect— HTTPonCallEffect— CallableonDocumentCreatedEffect,onDocumentUpdatedEffect,onDocumentDeletedEffect,onDocumentWrittenEffect— Firestore triggersonMessagePublishedEffect— Pub/SubonTaskDispatchedEffect— Cloud Tasks
pnpm install
pnpm nx run-many -t build
pnpm nx run-many -t testThe repo includes a full example app with Firebase emulator support:
pnpm example:emulator # Terminal 1
pnpm example:hosting # Terminal 2MIT. The Model/Repository pattern is adapted from @effect/sql.