@genkit-ai/firebase
Version:
Genkit AI framework plugin for Firebase including Firestore trace/state store and deployment helpers for Cloud Functions for Firebase.
1 lines • 6.79 kB
Source Map (JSON)
{"version":3,"sources":["../../src/stream-manager/rtdb.ts"],"sourcesContent":["/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { App } from 'firebase-admin/app';\nimport { Database, getDatabase } from 'firebase-admin/database';\nimport {\n GenkitError,\n StreamNotFoundError,\n type ActionStreamInput,\n type ActionStreamSubscriber,\n type StreamManager,\n} from 'genkit/beta';\n\nexport interface RtdbStreamManagerOptions {\n firebaseApp?: App;\n db?: Database;\n refPrefix?: string;\n timeout?: number;\n}\n\nclass RtdbActionStream<S, O> implements ActionStreamInput<S, O> {\n private db: Database;\n private streamRef: string;\n private metadataRef: string;\n\n constructor(db: Database, streamRef: string) {\n this.db = db;\n this.streamRef = `${streamRef}/stream`;\n this.metadataRef = `${streamRef}/metadata`;\n }\n\n private async update(): Promise<void> {\n await this.db.ref(this.metadataRef).update({ updatedAt: Date.now() });\n }\n\n async write(chunk: S): Promise<void> {\n await this.db.ref(this.streamRef).push({ type: 'chunk', chunk });\n await this.update();\n }\n\n async done(output: O): Promise<void> {\n await this.db.ref(this.streamRef).push({ type: 'done', output });\n await this.update();\n }\n\n async error(err: any): Promise<void> {\n const serializableError = {\n message: err.message,\n stack: err.stack,\n ...err,\n };\n await this.db\n .ref(this.streamRef)\n .push({ type: 'error', err: serializableError });\n await this.update();\n }\n}\n\nexport class RtdbStreamManager implements StreamManager {\n private db: Database;\n private refRoot: string;\n private timeout: number;\n\n constructor(opts: RtdbStreamManagerOptions) {\n this.refRoot = opts.refPrefix ?? 'genkit-streams';\n // refRoot should have a trailing slash for simplicity.\n if (this.refRoot && !this.refRoot.endsWith('/')) {\n this.refRoot += '/';\n }\n this.db =\n opts.db ??\n (opts.firebaseApp ? getDatabase(opts.firebaseApp) : getDatabase());\n this.timeout = opts.timeout ?? 60000;\n }\n\n async open<S, O>(streamId: string): Promise<ActionStreamInput<S, O>> {\n const streamRef = this.refRoot + streamId;\n await this.db.ref(streamRef).remove();\n await this.db.ref(`${streamRef}/metadata`).set({ createdAt: Date.now() });\n return new RtdbActionStream(this.db, streamRef);\n }\n\n async subscribe<S, O>(\n streamId: string,\n callbacks: ActionStreamSubscriber<S, O>\n ): Promise<{\n unsubscribe: () => void;\n }> {\n const streamRef = this.db.ref(`${this.refRoot}${streamId}`);\n const snapshot = await streamRef.get();\n if (!snapshot.exists()) {\n throw new StreamNotFoundError(`Stream ${streamId} not found.`);\n }\n const streamDataRef = streamRef.child('stream');\n let timeoutId: NodeJS.Timeout;\n const resetTimeout = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n callbacks.onError?.(\n new GenkitError({\n status: 'DEADLINE_EXCEEDED',\n message: 'Stream timed out.',\n })\n );\n unsubscribe();\n }, this.timeout);\n };\n const handleEvent = (snapshot) => {\n resetTimeout();\n if (!snapshot.exists()) {\n return;\n }\n const event = snapshot.val();\n if (event.type === 'chunk') {\n callbacks.onChunk?.(event.chunk);\n } else if (event.type === 'done') {\n clearTimeout(timeoutId);\n callbacks.onDone?.(event.output);\n unsubscribe();\n } else if (event.type === 'error') {\n clearTimeout(timeoutId);\n callbacks.onError?.(event.err);\n unsubscribe();\n }\n };\n const unsubscribe = () => {\n streamDataRef.off('child_added', handleEvent);\n };\n streamDataRef.on('child_added', handleEvent);\n resetTimeout();\n return { unsubscribe };\n }\n}\n"],"mappings":"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","names":["snapshot"]}