{"version":3,"file":"index.mjs","names":["firebaseOnMessagePublished","onMessagePublished","firebaseOnMessagePublished","handlerOptions: HandlerOptions","onMessagePublished"],"sources":["../src/constants.ts","../src/utils/should-drop-event.ts","../src/handler.ts","../src/publisher.ts","../src/factory.ts"],"sourcesContent":["export const HOUR_MINUTES = 60;\nexport const MINUTE_MS = 60 * 1000;\n\n/** Default options for Pubsub handlers */\nexport const defaultHandlerOptions = {\n  retry: true,\n  retryMaxAgeMinutes: undefined, // No limit on retry age by default\n  memory: \"512MiB\",\n  cpu: 1,\n  timeoutSeconds: 20,\n  maxInstances: 250,\n  markEvent: false,\n  vpcConnector: undefined,\n} as const;\n","import type { CloudEvent } from \"firebase-functions/v2\";\n\nexport function shouldDropEvent(\n  event: CloudEvent<unknown>,\n  maxAgeMinutes?: number,\n) {\n  // If maxAgeMinutes is undefined, we don't drop events based on age\n  if (maxAgeMinutes === undefined) {\n    return false;\n  }\n\n  const maxAgeMs = maxAgeMinutes * 60 * 1000;\n  const eventAge = Date.now() - Date.parse(event.time);\n\n  if (eventAge > maxAgeMs) {\n    /** Dropping event due to max age reached */\n    console.error(\n      new Error(\n        `Dropping event ${event.type} for ${event.source} because max age (${String(maxAgeMinutes)} minutes) was reached.`,\n      ),\n    );\n    return true;\n  }\n\n  return false;\n}\n\nexport function getEventAgeSeconds(event: CloudEvent<unknown>) {\n  return (Date.now() - Date.parse(event.time)) / 1000;\n}\n","import { onMessagePublished as firebaseOnMessagePublished } from \"firebase-functions/v2/pubsub\";\nimport { got } from \"get-or-throw\";\nimport { defaultHandlerOptions } from \"./constants\";\nimport type {\n  EventMarkingFunctions,\n  HandlerOptions,\n  PubsubTopicPayload,\n  SchemaRecord,\n} from \"./types\";\nimport { shouldDropEvent } from \"./utils\";\n\n/**\n * Creates a factory function for generating type-safe Pubsub handlers\n *\n * @param schemas - Zod schemas for each topic\n * @param region - GCP region\n * @param eventMarkingFunctions - Optional functions for tracking processed\n *   events\n * @param defaultOptions - Default options for all handlers\n * @returns A factory function for creating handlers\n */\nexport function createHandlerFactory<Schemas extends SchemaRecord<string>>(\n  schemas: Schemas,\n  region: string,\n  eventMarkingFunctions?: EventMarkingFunctions,\n  defaultOptions: HandlerOptions = defaultHandlerOptions,\n  onMessagePublished = firebaseOnMessagePublished,\n) {\n  return <T extends keyof Schemas & string>({\n    topic,\n    handler,\n    options = {},\n  }: {\n    topic: T;\n    handler: (payload: PubsubTopicPayload<Schemas, T>) => Promise<void>;\n    options?: HandlerOptions;\n  }) => {\n    const { retryMaxAgeMinutes, markEvent, ...mergedOptions } = {\n      ...defaultOptions,\n      ...options,\n    };\n\n    // Determine if we can mark events\n    const canMarkEvents = markEvent && eventMarkingFunctions !== undefined;\n\n    return onMessagePublished(\n      {\n        ...mergedOptions,\n        topic,\n        region,\n      },\n      async (event) => {\n        // Use internal shouldDropEvent implementation\n        if (shouldDropEvent(event, retryMaxAgeMinutes)) {\n          return;\n        }\n\n        // Check if event was already processed, but only if both conditions are met:\n        // 1. markEvent option is true\n        // 2. Event marking functions are available\n        if (canMarkEvents && event.id) {\n          if (await eventMarkingFunctions.isEventProcessed(event.id)) {\n            /**\n             * This should happen very rarely, so we log an error just to notice\n             * how often it happens.\n             */\n            console.error(\n              new Error(\n                `(Not an error) Pubsub event ${event.id} was already processed`,\n              ),\n            );\n            return;\n          }\n        }\n\n        const schema = got(schemas, topic);\n        // Type assertion to avoid unsafe assignment\n        const messageData = event.data.message.json as unknown;\n        const result = schema.safeParse(messageData);\n\n        if (!result.success) {\n          console.error(\n            new Error(`Zod validation error for topic ${topic}`),\n            result.error.flatten(),\n          );\n          return;\n        }\n\n        await handler(result.data as PubsubTopicPayload<Schemas, T>);\n\n        // Mark event as processed, but only if both conditions are met\n        if (canMarkEvents && event.id) {\n          await eventMarkingFunctions.markEventAsProcessed(event.id);\n        }\n      },\n    );\n  };\n}\n","import { PubSub } from \"@google-cloud/pubsub\";\nimport type { PubsubTopicPayload, SchemaRecord } from \"./types\";\n\n/**\n * Creates a factory function that produces type-safe publishers for specific\n * topics\n *\n * @param pubsubClient - Google Cloud Pubsub client\n * @returns A factory function for creating publishers\n */\nexport function createPublisherFactory<Schemas extends SchemaRecord<string>>(\n  pubsubClient: PubSub,\n) {\n  return <T extends keyof Schemas & string>(topicName: T) => {\n    /**\n     * Publishes a message to the specified topic\n     *\n     * @param data - The data to publish, must conform to the topic's schema\n     * @returns Promise that resolves when the message is published\n     */\n    return async (data: PubsubTopicPayload<Schemas, T>) => {\n      const topic = pubsubClient.topic(topicName);\n      await topic.publishMessage({ json: data });\n    };\n  };\n}\n","import type { PubSub } from \"@google-cloud/pubsub\";\nimport { onMessagePublished as firebaseOnMessagePublished } from \"firebase-functions/v2/pubsub\";\nimport { defaultHandlerOptions } from \"./constants\";\nimport { createHandlerFactory } from \"./handler\";\nimport { createPublisherFactory } from \"./publisher\";\nimport type {\n  HandlerOptions,\n  SchemaRecord,\n  TypedPubsubClient,\n  TypedPubsubOptions,\n} from \"./types\";\n\n/**\n * Creates a type-safe Pubsub client for handling messages with schema\n * validation\n *\n * @param pubsubClient - Google Cloud Pubsub client instance\n * @param schemas - Zod schemas for validating messages for each topic\n * @param region - GCP region for the Pubsub functions\n * @param options - Global defaults for all handlers\n * @returns Type-safe Pubsub client with publisher and handler factories\n */\nexport function createTypedPubsub<Schemas extends SchemaRecord<string>>({\n  client,\n  schemas,\n  region,\n  options = {},\n  onMessagePublished = firebaseOnMessagePublished,\n}: {\n  client: PubSub;\n  schemas: Schemas;\n  region: string;\n  options?: TypedPubsubOptions;\n  onMessagePublished?: typeof firebaseOnMessagePublished;\n}): TypedPubsubClient<Schemas> {\n  // Merge default handler options\n  const handlerOptions: HandlerOptions = {\n    ...defaultHandlerOptions,\n    ...options.defaultHandlerOptions,\n  };\n\n  return {\n    createPublisher: createPublisherFactory<Schemas>(client),\n    createHandler: createHandlerFactory(\n      schemas,\n      region,\n      options.eventMarkingFunctions,\n      handlerOptions,\n      onMessagePublished,\n    ),\n  };\n}\n"],"mappings":";;;;;AACA,MAAa,YAAY,KAAK;;AAG9B,MAAa,wBAAwB;CACnC,OAAO;CACP,oBAAoB;CACpB,QAAQ;CACR,KAAK;CACL,gBAAgB;CAChB,cAAc;CACd,WAAW;CACX,cAAc;CACf;;;;ACXD,SAAgB,gBACd,OACA,eACA;AAEA,KAAI,kBAAkB,OACpB,QAAO;CAGT,MAAM,WAAW,gBAAgB,KAAK;AAGtC,KAFiB,KAAK,KAAK,GAAG,KAAK,MAAM,MAAM,KAAK,GAErC,UAAU;;AAEvB,UAAQ,sBACN,IAAI,MACF,kBAAkB,MAAM,KAAK,OAAO,MAAM,OAAO,oBAAoB,OAAO,cAAc,CAAC,wBAC5F,CACF;AACD,SAAO;;AAGT,QAAO;;;;;;;;;;;;;;;ACHT,SAAgB,qBACd,SACA,QACA,uBACA,iBAAiC,uBACjC,uBAAqBA,oBACrB;AACA,SAA0C,EACxC,OACA,SACA,UAAU,EAAE,OAKR;EACJ,MAAM,EAAE,oBAAoB,WAAW,GAAG,kBAAkB;GAC1D,GAAG;GACH,GAAG;GACJ;EAGD,MAAM,gBAAgB,aAAa,0BAA0B;AAE7D,SAAOC,qBACL;GACE,GAAG;GACH;GACA;GACD,EACD,OAAO,UAAU;AAEf,OAAI,gBAAgB,OAAO,mBAAmB,CAC5C;AAMF,OAAI,iBAAiB,MAAM,IACzB;QAAI,MAAM,sBAAsB,iBAAiB,MAAM,GAAG,EAAE;;;;;AAK1D,aAAQ,sBACN,IAAI,MACF,+BAA+B,MAAM,GAAG,wBACzC,CACF;AACD;;;GAIJ,MAAM,SAAS,IAAI,SAAS,MAAM;GAElC,MAAM,cAAc,MAAM,KAAK,QAAQ;GACvC,MAAM,SAAS,OAAO,UAAU,YAAY;AAE5C,OAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,sBACN,IAAI,MAAM,kCAAkC,QAAQ,EACpD,OAAO,MAAM,SAAS,CACvB;AACD;;AAGF,SAAM,QAAQ,OAAO,KAAuC;AAG5D,OAAI,iBAAiB,MAAM,GACzB,OAAM,sBAAsB,qBAAqB,MAAM,GAAG;IAG/D;;;;;;;;;;;;;ACrFL,SAAgB,uBACd,cACA;AACA,SAA0C,cAAiB;;;;;;;AAOzD,SAAO,OAAO,SAAyC;AAErD,SADc,aAAa,MAAM,UAAU,CAC/B,eAAe,EAAE,MAAM,MAAM,CAAC;;;;;;;;;;;;;;;;;ACAhD,SAAgB,kBAAwD,EACtE,QACA,SACA,QACA,UAAU,EAAE,EACZ,2CAAqBC,sBAOQ;CAE7B,MAAMC,iBAAiC;EACrC,GAAG;EACH,GAAG,QAAQ;EACZ;AAED,QAAO;EACL,iBAAiB,uBAAgC,OAAO;EACxD,eAAe,qBACb,SACA,QACA,QAAQ,uBACR,gBACAC,qBACD;EACF"}