77import type { Snapshot } from 'effect-firebase' ;
88import { UnknownException } from 'effect/Cause' ;
99import { getFirestore } from 'firebase-admin/firestore' ;
10- import { converter , fromFirestoreDocumentData } from './converter.js' ;
10+ import { App } from '../app.js' ;
11+ import { fromFirestoreDocumentData , makeConverter } from './converter.js' ;
1112import { buildQuery } from './query-builder.js' ;
1213
1314const packSnapshot = makeSnapshotPacker ( fromFirestoreDocumentData ) ;
@@ -20,105 +21,111 @@ const mapError = (error: unknown) =>
2021/**
2122 * Live Firestore service using the admin SDK.
2223 */
23- export const layer = Layer . succeed (
24+ export const layer = Layer . effect (
2425 FirestoreService ,
25- FirestoreService . of ( {
26- get : ( path , options ) =>
27- Effect . tryPromise ( {
28- try : ( ) => getFirestore ( ) . doc ( path ) . get ( ) ,
29- catch : ( error ) => mapError ( error ) ,
30- } ) . pipe ( Effect . map ( ( snapshot ) => packSnapshot ( snapshot , options ) ) ) ,
31- add : ( path , data ) =>
32- Effect . tryPromise ( {
33- try : async ( ) => {
34- const ref = await getFirestore ( )
35- . collection ( path )
36- . withConverter ( converter )
37- . add ( data ) ;
38- return { id : ref . id , path : ref . path } ;
39- } ,
40- catch : ( error ) => mapError ( error ) ,
41- } ) ,
42- set : ( path , data , options ) =>
43- Effect . tryPromise ( {
44- try : ( ) =>
45- getFirestore ( )
46- . doc ( path )
47- . withConverter ( converter )
48- . set ( data , options || { } ) ,
49- catch : ( error ) => mapError ( error ) ,
50- } ) ,
51- update : ( path , data ) =>
52- Effect . tryPromise ( {
53- try : ( ) => getFirestore ( ) . doc ( path ) . update ( converter . toFirestore ( data ) ) ,
54- catch : ( error ) => mapError ( error ) ,
55- } ) ,
56- remove : ( path ) =>
57- Effect . tryPromise ( {
58- try : ( ) => getFirestore ( ) . doc ( path ) . withConverter ( converter ) . delete ( ) ,
59- catch : ( error ) => mapError ( error ) ,
60- } ) ,
61- query : ( collectionPath , constraints ) =>
62- Effect . tryPromise ( {
63- try : async ( ) => {
64- const query = buildQuery ( collectionPath , constraints ) ;
65- const snapshot = await query . get ( ) ;
66- return Arr . filterMap (
67- snapshot . docs ,
68- ( doc ) : Option . Option < Snapshot > => packSnapshot ( doc )
69- ) ;
70- } ,
71- catch : ( error ) => mapError ( error ) ,
72- } ) ,
73- streamDoc : ( path , options ) =>
74- Stream . asyncScoped < Option . Option < Snapshot > , FirestoreError > ( ( emit ) =>
75- Effect . acquireRelease (
76- Effect . sync ( ( ) => {
77- const docRef = getFirestore ( ) . doc ( path ) ;
78- return docRef . onSnapshot (
79- ( snapshot ) => {
80- emit . single ( packSnapshot ( snapshot , options ) ) ;
81- } ,
82- ( error ) => {
83- const mappedError = mapError ( error ) ;
84- if ( mappedError . _tag === 'FirestoreError' ) {
85- emit . fail ( mappedError ) ;
86- } else {
87- // Convert UnknownException to FirestoreError
88- emit . fail ( FirestoreError . fromError ( error as Error ) ) ;
89- }
90- }
26+ Effect . gen ( function * ( ) {
27+ const app = yield * App ;
28+ const db = getFirestore ( app . getApp ( ) ) ;
29+ const converter = makeConverter ( db ) ;
30+
31+ return FirestoreService . of ( {
32+ get : ( path , options ) =>
33+ Effect . tryPromise ( {
34+ try : ( ) => db . doc ( path ) . get ( ) ,
35+ catch : ( error ) => mapError ( error ) ,
36+ } ) . pipe ( Effect . map ( ( snapshot ) => packSnapshot ( snapshot , options ) ) ) ,
37+ add : ( path , data ) =>
38+ Effect . tryPromise ( {
39+ try : async ( ) => {
40+ const ref = await db
41+ . collection ( path )
42+ . withConverter ( converter )
43+ . add ( data ) ;
44+ return { id : ref . id , path : ref . path } ;
45+ } ,
46+ catch : ( error ) => mapError ( error ) ,
47+ } ) ,
48+ set : ( path , data , options ) =>
49+ Effect . tryPromise ( {
50+ try : ( ) =>
51+ db
52+ . doc ( path )
53+ . withConverter ( converter )
54+ . set ( data , options || { } ) ,
55+ catch : ( error ) => mapError ( error ) ,
56+ } ) ,
57+ update : ( path , data ) =>
58+ Effect . tryPromise ( {
59+ try : ( ) => db . doc ( path ) . update ( converter . toFirestore ( data ) ) ,
60+ catch : ( error ) => mapError ( error ) ,
61+ } ) ,
62+ remove : ( path ) =>
63+ Effect . tryPromise ( {
64+ try : ( ) => db . doc ( path ) . withConverter ( converter ) . delete ( ) ,
65+ catch : ( error ) => mapError ( error ) ,
66+ } ) ,
67+ query : ( collectionPath , constraints ) =>
68+ Effect . tryPromise ( {
69+ try : async ( ) => {
70+ const query = buildQuery ( db , collectionPath , constraints ) ;
71+ const snapshot = await query . get ( ) ;
72+ return Arr . filterMap (
73+ snapshot . docs ,
74+ ( doc ) : Option . Option < Snapshot > => packSnapshot ( doc )
9175 ) ;
92- } ) ,
93- ( unsubscribe ) => Effect . sync ( ( ) => unsubscribe ( ) )
94- )
95- ) ,
96- streamQuery : ( collectionPath , constraints , options ) =>
97- Stream . asyncScoped < ReadonlyArray < Snapshot > , FirestoreError > ( ( emit ) =>
98- Effect . acquireRelease (
99- Effect . sync ( ( ) => {
100- const query = buildQuery ( collectionPath , constraints ) ;
101- return query . onSnapshot (
102- ( snapshot ) => {
103- const snapshots = Arr . filterMap (
104- snapshot . docs ,
105- ( doc ) : Option . Option < Snapshot > => packSnapshot ( doc , options )
106- ) ;
107- emit . single ( snapshots ) ;
108- } ,
109- ( error ) => {
110- const mappedError = mapError ( error ) ;
111- if ( mappedError . _tag === 'FirestoreError' ) {
112- emit . fail ( mappedError ) ;
113- } else {
114- // Convert UnknownException to FirestoreError
115- emit . fail ( FirestoreError . fromError ( error as Error ) ) ;
76+ } ,
77+ catch : ( error ) => mapError ( error ) ,
78+ } ) ,
79+ streamDoc : ( path , options ) =>
80+ Stream . asyncScoped < Option . Option < Snapshot > , FirestoreError > ( ( emit ) =>
81+ Effect . acquireRelease (
82+ Effect . sync ( ( ) => {
83+ const docRef = db . doc ( path ) ;
84+ return docRef . onSnapshot (
85+ ( snapshot ) => {
86+ emit . single ( packSnapshot ( snapshot , options ) ) ;
87+ } ,
88+ ( error ) => {
89+ const mappedError = mapError ( error ) ;
90+ if ( mappedError . _tag === 'FirestoreError' ) {
91+ emit . fail ( mappedError ) ;
92+ } else {
93+ // Convert UnknownException to FirestoreError
94+ emit . fail ( FirestoreError . fromError ( error as Error ) ) ;
95+ }
11696 }
117- }
118- ) ;
119- } ) ,
120- ( unsubscribe ) => Effect . sync ( ( ) => unsubscribe ( ) )
121- )
122- ) ,
97+ ) ;
98+ } ) ,
99+ ( unsubscribe ) => Effect . sync ( ( ) => unsubscribe ( ) )
100+ )
101+ ) ,
102+ streamQuery : ( collectionPath , constraints , options ) =>
103+ Stream . asyncScoped < ReadonlyArray < Snapshot > , FirestoreError > ( ( emit ) =>
104+ Effect . acquireRelease (
105+ Effect . sync ( ( ) => {
106+ const query = buildQuery ( db , collectionPath , constraints ) ;
107+ return query . onSnapshot (
108+ ( snapshot ) => {
109+ const snapshots = Arr . filterMap (
110+ snapshot . docs ,
111+ ( doc ) : Option . Option < Snapshot > => packSnapshot ( doc , options )
112+ ) ;
113+ emit . single ( snapshots ) ;
114+ } ,
115+ ( error ) => {
116+ const mappedError = mapError ( error ) ;
117+ if ( mappedError . _tag === 'FirestoreError' ) {
118+ emit . fail ( mappedError ) ;
119+ } else {
120+ // Convert UnknownException to FirestoreError
121+ emit . fail ( FirestoreError . fromError ( error as Error ) ) ;
122+ }
123+ }
124+ ) ;
125+ } ) ,
126+ ( unsubscribe ) => Effect . sync ( ( ) => unsubscribe ( ) )
127+ )
128+ ) ,
129+ } ) ;
123130 } )
124131) ;
0 commit comments