1
1
import { badRequest } from "../../common/error" ;
2
- import { initializeApp , deleteApp , cert } from "firebase-admin/app" ;
2
+ import { getApps , initializeApp , deleteApp , cert , App } from "firebase-admin/app" ;
3
3
import { getDatabase , Reference } from "firebase-admin/database" ;
4
4
import {
5
5
CollectionReference ,
@@ -64,6 +64,23 @@ function extractCursorValues(values: any[]): any[] {
64
64
) . filter ( value => value !== undefined ) ;
65
65
}
66
66
67
+ const appCache : { [ firestoreId : string ] : any } = { } ; // A cache for storing initialized apps by firestoreId
68
+
69
+ function getOrInitializeApp ( serviceAccount : any , databaseUrl : string , firestoreId : string ) : App {
70
+ const existingApp = getApps ( ) . find ( ( app ) => app . name === firestoreId ) ;
71
+
72
+ if ( existingApp ) {
73
+ return existingApp ; // Return the existing app
74
+ }
75
+
76
+ // Initialize a new app with the given name
77
+ return initializeApp ( {
78
+ credential : cert ( serviceAccount ) ,
79
+ databaseURL : databaseUrl ,
80
+ projectId : firestoreId ,
81
+ } , firestoreId ) ;
82
+ }
83
+
67
84
export async function runFirebasePlugin (
68
85
actionData : ActionDataType ,
69
86
dataSourceConfig : DataSourceDataType
@@ -72,33 +89,29 @@ export async function runFirebasePlugin(
72
89
const { privateKey, databaseUrl, firestoreId } = dataSourceConfig ;
73
90
const serviceAccount = JSON . parse ( privateKey ) ;
74
91
75
- const app = initializeApp ( {
76
- credential : cert ( serviceAccount ) ,
77
- databaseURL : databaseUrl ,
78
- projectId : firestoreId ,
79
- } ) ;
92
+ const app = getOrInitializeApp ( serviceAccount , databaseUrl , firestoreId ) ;
80
93
81
94
const witDbRef = < T > ( fn : ( ref : Reference ) => T ) : T => {
82
95
if ( ! ( "databaseRef" in actionData ) ) {
83
96
throw badRequest ( "not a realtime database action:" + actionName ) ;
84
97
}
85
- const ref = getDatabase ( ) . ref ( actionData . databaseRef ) ;
98
+ const ref = getDatabase ( app ) . ref ( actionData . databaseRef ) ;
86
99
return fn ( ref ) ;
87
100
} ;
88
101
89
102
const withFirestoreCollection = < T > ( fn : ( ref : CollectionReference ) => T ) : T => {
90
103
if ( ! ( "collection" in actionData ) ) {
91
104
throw badRequest ( "not a firestore action with collection:" + actionName ) ;
92
105
}
93
- const ref = getFirestore ( ) . collection ( actionData . collection ) ;
106
+ const ref = getFirestore ( app ) . collection ( actionData . collection ) ;
94
107
return fn ( ref ) ;
95
108
} ;
96
109
97
110
const withFirestoreDoc = < T > ( fn : ( ref : DocumentReference ) => T ) : T => {
98
111
if ( ! ( "collection" in actionData ) || ! ( "documentId" in actionData ) ) {
99
112
throw badRequest ( "not a firestore action with collection and documentId:" + actionName ) ;
100
113
}
101
- const ref = getFirestore ( ) . collection ( actionData . collection ) . doc ( actionData . documentId ) ;
114
+ const ref = getFirestore ( app ) . collection ( actionData . collection ) . doc ( actionData . documentId ) ;
102
115
return fn ( ref ) ;
103
116
} ;
104
117
@@ -130,9 +143,9 @@ export async function runFirebasePlugin(
130
143
if ( actionName === "FS.GetCollections" ) {
131
144
let collections ;
132
145
if ( actionData . parentDocumentId ) {
133
- collections = await getFirestore ( ) . doc ( actionData . parentDocumentId ) . listCollections ( ) ;
146
+ collections = await getFirestore ( app ) . doc ( actionData . parentDocumentId ) . listCollections ( ) ;
134
147
} else {
135
- collections = await getFirestore ( ) . listCollections ( ) ;
148
+ collections = await getFirestore ( app ) . listCollections ( ) ;
136
149
}
137
150
return collections . map ( ( i ) => i . id ) ;
138
151
}
@@ -317,7 +330,8 @@ export async function runFirebasePlugin(
317
330
return successResult ;
318
331
} ) ;
319
332
}
320
- } finally {
321
- deleteApp ( app ) ;
333
+ } catch ( error ) {
334
+ console . error ( `Error in action ${ actionData . actionName } :` , error ) ;
335
+ throw error ;
322
336
}
323
337
}
0 commit comments