UNPKG

firebase-functions

Version:
211 lines (209 loc) 6.94 kB
import { __export } from "../../_virtual/rolldown_runtime.mjs"; import { initV2Endpoint } from "../../runtime/manifest.mjs"; import { convertIfPresent, convertInvoker } from "../../common/encoding.mjs"; import { withInit } from "../../common/onInit.mjs"; import { withErrorHandler } from "../../common/providers/https.mjs"; import { normalizePath } from "../../common/utilities/path.mjs"; import { wrapTraceContext } from "../trace.mjs"; import { getGlobalOptions, optionsToEndpoint } from "../options.mjs"; import { PathPattern } from "../../common/utilities/path-pattern.mjs"; import express from "express"; import fs from "fs"; //#region src/v2/providers/dataconnect.ts var dataconnect_exports = /* @__PURE__ */ __export({ initGraphqlServer: () => initGraphqlServer, mutationExecutedEventType: () => mutationExecutedEventType, onGraphRequest: () => onGraphRequest, onMutationExecuted: () => onMutationExecuted }); /** @internal */ const mutationExecutedEventType = "google.firebase.dataconnect.connector.v1.mutationExecuted"; /** * Event handler that triggers when a mutation is executed in Firebase Data Connect. * * @param mutationOrOpts - Options or string mutation path. * @param handler - Event handler which is run every time a mutation is executed. */ function onMutationExecuted(mutationOrOpts, handler) { return onOperation(mutationExecutedEventType, mutationOrOpts, handler); } function getOpts(mutationOrOpts) { const operationRegex = new RegExp("services/([^/]+)/connectors/([^/]*)/operations/([^/]+)"); let service; let connector; let operation; let opts; if (typeof mutationOrOpts === "string") { const path = normalizePath(mutationOrOpts); const match = path.match(operationRegex); if (!match) { throw new Error(`Invalid operation path: ${path}`); } service = match[1]; connector = match[2]; operation = match[3]; opts = {}; } else { service = mutationOrOpts.service; connector = mutationOrOpts.connector; operation = mutationOrOpts.operation; opts = { ...mutationOrOpts }; delete opts.service; delete opts.connector; delete opts.operation; } return { service, connector, operation, opts }; } function makeEndpoint(eventType, opts, service, connector, operation) { const baseOpts = optionsToEndpoint(getGlobalOptions()); const specificOpts = optionsToEndpoint(opts); const eventFilters = {}; const eventFilterPathPatterns = {}; if (service) { if (service.hasWildcards()) { eventFilterPathPatterns.service = service.getValue(); } else { eventFilters.service = service.getValue(); } } if (connector) { if (connector.hasWildcards()) { eventFilterPathPatterns.connector = connector.getValue(); } else { eventFilters.connector = connector.getValue(); } } if (operation) { if (operation.hasWildcards()) { eventFilterPathPatterns.operation = operation.getValue(); } else { eventFilters.operation = operation.getValue(); } } return { ...initV2Endpoint(getGlobalOptions(), opts), platform: "gcfv2", ...baseOpts, ...specificOpts, labels: { ...baseOpts?.labels, ...specificOpts?.labels }, eventTrigger: { eventType, eventFilters, eventFilterPathPatterns, retry: opts.retry ?? false } }; } function makeParams(event, service, connector, operation) { return { ...service?.extractMatches(event.service), ...connector?.extractMatches(event.connector), ...operation?.extractMatches(event.operation) }; } function onOperation(eventType, mutationOrOpts, handler) { const { service, connector, operation, opts } = getOpts(mutationOrOpts); const servicePattern = service ? new PathPattern(service) : undefined; const connectorPattern = connector ? new PathPattern(connector) : undefined; const operationPattern = operation ? new PathPattern(operation) : undefined; const func = (raw) => { const event = raw; const params = makeParams(event, servicePattern, connectorPattern, operationPattern); const { authtype, authid, service: service$1, connector: connector$1, operation: operation$1,...rest } = event; const dataConnectEvent = { ...rest, authType: authtype, authId: authid, params }; return wrapTraceContext(withInit(handler))(dataConnectEvent); }; func.run = handler; func.__endpoint = makeEndpoint(eventType, opts, servicePattern, connectorPattern, operationPattern); return func; } /** @hidden */ async function initGraphqlServer(opts) { if (!opts.schema && !opts.schemaFilePath || opts.schema && opts.schemaFilePath) { throw new Error("Exactly one of 'schema' or 'schemaFilePath' must be provided."); } if (opts.schemaFilePath) { opts.schema = fs.readFileSync(opts.schemaFilePath, "utf-8"); } if (!opts.resolvers.query && !opts.resolvers.mutation) { throw new Error("At least one query or mutation resolver must be provided."); } const apolloResolvers = {}; if (opts.resolvers.query) { apolloResolvers.Query = opts.resolvers.query; } if (opts.resolvers.mutation) { apolloResolvers.Mutation = opts.resolvers.mutation; } try { const { ApolloServer } = await import("@apollo/server"); const { expressMiddleware } = await import("@as-integrations/express4"); const serverPromise$1 = (async () => { const app = express(); const server = new ApolloServer({ typeDefs: opts.schema, resolvers: apolloResolvers }); await server.start(); app.use(`/${opts.path ?? "graphql"}`, express.json(), expressMiddleware(server)); return app; })(); return serverPromise$1; } catch (e) { if (e instanceof Error) { throw new Error("Error initializing GraphQL server: " + e.message); } else { throw e; } } } let serverPromise = null; /** * @hidden * Handles HTTPS GraphQL requests. * @param {GraphqlServerOptions} opts - Options for configuring the GraphQL server. * @returns {HttpsFunction} A function you can export and deploy. */ function onGraphRequest(opts) { const handler = wrapTraceContext(withInit(withErrorHandler(async (req, res) => { serverPromise = serverPromise ?? initGraphqlServer(opts); const app = await serverPromise; app(req, res); }))); const globalOpts = getGlobalOptions(); const baseOpts = optionsToEndpoint(globalOpts); const specificOpts = optionsToEndpoint(opts); const endpoint = { ...initV2Endpoint(globalOpts, opts), platform: "gcfv2", ...baseOpts, ...specificOpts, labels: { ...baseOpts?.labels, ...specificOpts?.labels }, dataConnectGraphqlTrigger: {} }; convertIfPresent(endpoint.dataConnectGraphqlTrigger, globalOpts, "invoker", "invoker", convertInvoker); convertIfPresent(endpoint.dataConnectGraphqlTrigger, opts, "invoker", "invoker", convertInvoker); if (opts.schemaFilePath) { endpoint.dataConnectGraphqlTrigger.schemaFilePath = opts.schemaFilePath; } handler.__endpoint = endpoint; return handler; } //#endregion export { dataconnect_exports, initGraphqlServer, mutationExecutedEventType, onGraphRequest, onMutationExecuted };