@trigger.dev/core 3.0.0-beta.47 → 3.0.0-beta.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/dist/api-Pl9fxB8v.d.mts +13879 -0
  2. package/dist/api-sNoooMbT.d.ts +13879 -0
  3. package/dist/{catalog-NxVZnWZh.d.ts → catalog-U7_q4XsM.d.mts} +12 -34
  4. package/dist/{catalog-N-X0Te3W.d.mts → catalog-bSnBE19I.d.ts} +12 -34
  5. package/dist/{common-fIyU5pmz.d.mts → common-CLW82lkt.d.mts} +1 -1
  6. package/dist/{common-fIyU5pmz.d.ts → common-CLW82lkt.d.ts} +1 -1
  7. package/dist/{eventFilterMatches-2kHImluE.d.mts → eventFilter-66NaBAMi.d.mts} +1 -3
  8. package/dist/{eventFilterMatches-2kHImluE.d.ts → eventFilter-66NaBAMi.d.ts} +1 -3
  9. package/dist/eventFilterMatches.d.mts +6 -0
  10. package/dist/eventFilterMatches.d.ts +6 -0
  11. package/dist/eventFilterMatches.js +165 -0
  12. package/dist/eventFilterMatches.js.map +1 -0
  13. package/dist/eventFilterMatches.mjs +163 -0
  14. package/dist/eventFilterMatches.mjs.map +1 -0
  15. package/dist/index.d.mts +14 -16716
  16. package/dist/index.d.ts +14 -16716
  17. package/dist/index.js +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +1 -1
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/json-DBPEJQRe.d.mts +16 -0
  22. package/dist/json-DBPEJQRe.d.ts +16 -0
  23. package/dist/{manager-X_HrWQ7_.d.mts → manager-KvCabW1a.d.mts} +1 -1
  24. package/dist/{manager-2ZQ3_twq.d.ts → manager-OBA35PzR.d.ts} +1 -1
  25. package/dist/replacements.d.mts +22 -0
  26. package/dist/replacements.d.ts +22 -0
  27. package/dist/replacements.js +33 -0
  28. package/dist/replacements.js.map +1 -0
  29. package/dist/replacements.mjs +28 -0
  30. package/dist/replacements.mjs.map +1 -0
  31. package/dist/requestFilter-HNZQEpQb.d.ts +180 -0
  32. package/dist/requestFilter-b5W2_1oP.d.mts +180 -0
  33. package/dist/requestFilterMatches.d.mts +13 -0
  34. package/dist/requestFilterMatches.d.ts +13 -0
  35. package/dist/requestFilterMatches.js +238 -0
  36. package/dist/requestFilterMatches.js.map +1 -0
  37. package/dist/requestFilterMatches.mjs +235 -0
  38. package/dist/requestFilterMatches.mjs.map +1 -0
  39. package/dist/retry.d.mts +10 -0
  40. package/dist/retry.d.ts +10 -0
  41. package/dist/retry.js +100 -0
  42. package/dist/retry.js.map +1 -0
  43. package/dist/retry.mjs +97 -0
  44. package/dist/retry.mjs.map +1 -0
  45. package/dist/schemas/index.d.mts +2611 -0
  46. package/dist/schemas/index.d.ts +2611 -0
  47. package/dist/schemas/index.js +1630 -0
  48. package/dist/schemas/index.js.map +1 -0
  49. package/dist/schemas/index.mjs +1463 -0
  50. package/dist/schemas/index.mjs.map +1 -0
  51. package/dist/{schemas-Zy7mGFgD.d.mts → schemas-WHkFakb3.d.mts} +4 -1
  52. package/dist/{schemas-Zy7mGFgD.d.ts → schemas-WHkFakb3.d.ts} +4 -1
  53. package/dist/taskLogger-CzADe4je.d.ts +33 -0
  54. package/dist/taskLogger-r_AFTX45.d.mts +33 -0
  55. package/dist/types.d.mts +11 -0
  56. package/dist/types.d.ts +11 -0
  57. package/dist/types.js +4 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/types.mjs +3 -0
  60. package/dist/types.mjs.map +1 -0
  61. package/dist/utils.d.mts +7 -0
  62. package/dist/utils.d.ts +7 -0
  63. package/dist/utils.js +33 -0
  64. package/dist/utils.js.map +1 -0
  65. package/dist/utils.mjs +30 -0
  66. package/dist/utils.mjs.map +1 -0
  67. package/dist/v3/dev/index.d.mts +2 -2
  68. package/dist/v3/dev/index.d.ts +2 -2
  69. package/dist/v3/errors.d.mts +39 -0
  70. package/dist/v3/errors.d.ts +39 -0
  71. package/dist/v3/errors.js +204 -0
  72. package/dist/v3/errors.js.map +1 -0
  73. package/dist/v3/errors.mjs +195 -0
  74. package/dist/v3/errors.mjs.map +1 -0
  75. package/dist/v3/index.d.mts +46 -211
  76. package/dist/v3/index.d.ts +46 -211
  77. package/dist/v3/index.js +3 -2
  78. package/dist/v3/index.js.map +1 -1
  79. package/dist/v3/index.mjs +3 -2
  80. package/dist/v3/index.mjs.map +1 -1
  81. package/dist/v3/logger-api.d.mts +24 -0
  82. package/dist/v3/logger-api.d.ts +24 -0
  83. package/dist/v3/logger-api.js +118 -0
  84. package/dist/v3/logger-api.js.map +1 -0
  85. package/dist/v3/logger-api.mjs +116 -0
  86. package/dist/v3/logger-api.mjs.map +1 -0
  87. package/dist/v3/otel/index.js +1 -1
  88. package/dist/v3/otel/index.js.map +1 -1
  89. package/dist/v3/otel/index.mjs +1 -1
  90. package/dist/v3/otel/index.mjs.map +1 -1
  91. package/dist/v3/prod/index.d.mts +3 -3
  92. package/dist/v3/prod/index.d.ts +3 -3
  93. package/dist/v3/schemas/index.d.mts +110 -110
  94. package/dist/v3/schemas/index.d.ts +110 -110
  95. package/dist/v3/schemas/index.js +2 -1
  96. package/dist/v3/schemas/index.js.map +1 -1
  97. package/dist/v3/schemas/index.mjs +2 -1
  98. package/dist/v3/schemas/index.mjs.map +1 -1
  99. package/dist/v3/semanticInternalAttributes.d.mts +56 -0
  100. package/dist/v3/semanticInternalAttributes.d.ts +56 -0
  101. package/dist/v3/semanticInternalAttributes.js +61 -0
  102. package/dist/v3/semanticInternalAttributes.js.map +1 -0
  103. package/dist/v3/semanticInternalAttributes.mjs +59 -0
  104. package/dist/v3/semanticInternalAttributes.mjs.map +1 -0
  105. package/dist/v3/utils/flattenAttributes.d.mts +8 -0
  106. package/dist/v3/utils/flattenAttributes.d.ts +8 -0
  107. package/dist/v3/utils/flattenAttributes.js +131 -0
  108. package/dist/v3/utils/flattenAttributes.js.map +1 -0
  109. package/dist/v3/utils/flattenAttributes.mjs +126 -0
  110. package/dist/v3/utils/flattenAttributes.mjs.map +1 -0
  111. package/dist/v3/utils/ioSerialization.d.mts +21 -0
  112. package/dist/v3/utils/ioSerialization.d.ts +21 -0
  113. package/dist/v3/utils/ioSerialization.js +2348 -0
  114. package/dist/v3/utils/ioSerialization.js.map +1 -0
  115. package/dist/v3/utils/ioSerialization.mjs +2339 -0
  116. package/dist/v3/utils/ioSerialization.mjs.map +1 -0
  117. package/dist/v3/utils/omit.d.mts +3 -0
  118. package/dist/v3/utils/omit.d.ts +3 -0
  119. package/dist/v3/utils/omit.js +20 -0
  120. package/dist/v3/utils/omit.js.map +1 -0
  121. package/dist/v3/utils/omit.mjs +18 -0
  122. package/dist/v3/utils/omit.mjs.map +1 -0
  123. package/dist/v3/utils/retries.d.mts +46 -0
  124. package/dist/v3/utils/retries.d.ts +46 -0
  125. package/dist/v3/utils/retries.js +118 -0
  126. package/dist/v3/utils/retries.js.map +1 -0
  127. package/dist/v3/utils/retries.mjs +113 -0
  128. package/dist/v3/utils/retries.mjs.map +1 -0
  129. package/dist/v3/workers/index.d.mts +7 -6
  130. package/dist/v3/workers/index.d.ts +7 -6
  131. package/dist/v3/workers/index.js +3 -2
  132. package/dist/v3/workers/index.js.map +1 -1
  133. package/dist/v3/workers/index.mjs +3 -2
  134. package/dist/v3/workers/index.mjs.map +1 -1
  135. package/dist/v3/zodIpc.js.map +1 -1
  136. package/dist/v3/zodIpc.mjs.map +1 -1
  137. package/dist/v3/zodMessageHandler.d.mts +16 -3
  138. package/dist/v3/zodMessageHandler.d.ts +16 -3
  139. package/dist/v3/zodMessageHandler.js +59 -13
  140. package/dist/v3/zodMessageHandler.js.map +1 -1
  141. package/dist/v3/zodMessageHandler.mjs +59 -13
  142. package/dist/v3/zodMessageHandler.mjs.map +1 -1
  143. package/dist/v3/zodNamespace.js.map +1 -1
  144. package/dist/v3/zodNamespace.mjs.map +1 -1
  145. package/dist/v3/zodfetch.d.mts +1 -1
  146. package/dist/v3/zodfetch.d.ts +1 -1
  147. package/dist/versions.d.mts +11 -0
  148. package/dist/versions.d.ts +11 -0
  149. package/dist/versions.js +31 -0
  150. package/dist/versions.js.map +1 -0
  151. package/dist/versions.mjs +27 -0
  152. package/dist/versions.mjs.map +1 -0
  153. package/package.json +137 -17
  154. package/dist/{messages-Sggr4tid.d.mts → messages-I-h-zZN9.d.mts} +32 -32
  155. package/dist/{messages-Sggr4tid.d.ts → messages-I-h-zZN9.d.ts} +32 -32
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/v3/zodIpc.ts","../../src/v3/zodMessageHandler.ts"],"names":["randomUUID","z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","messageSchema","ZodIpcMessageHandler","options","schema","handlers","sender","handleMessage","parsedMessage","parseMessage","handler","ack","safeParse","success","JSON","stringify","data","parsedPayload","Packet","discriminatedUnion","sessionId","optional","any","id","number","ZodIpcConnection","opts","Map","listenSchema","send","bind","sendWithAck","connect","emitSchema","timeoutInMs","currentId","Promise","resolve","reject","defaultTimeoutInMs","timeout","setTimeout","reason","set","clearTimeout","process","on","packet","parsedPacket","get","result"],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\nimport {\n GetSocketCallbackSchema,\n GetSocketMessageSchema,\n GetSocketMessagesWithCallback,\n GetSocketMessagesWithoutCallback,\n MessagesFromSocketCatalog,\n SocketMessageHasCallback,\n ZodSocketMessageCatalogSchema,\n} from \"./zodSocket\";\nimport { z } from \"zod\";\nimport { ZodSchemaParsedError } from \"./zodMessageHandler\";\nimport { inspect } from \"node:util\";\n\ninterface ZodIpcMessageSender<TEmitCatalog extends ZodSocketMessageCatalogSchema> {\n send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void>;\n\n sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>>;\n}\n\ntype ZodIpcMessageHandlers<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = Partial<{\n [K in keyof TListenCatalog]: (\n payload: z.infer<GetSocketMessageSchema<TListenCatalog, K>>,\n sender: ZodIpcMessageSender<TEmitCatalog>\n ) => Promise<\n SocketMessageHasCallback<TListenCatalog, K> extends true\n ? z.input<GetSocketCallbackSchema<TListenCatalog, K>>\n : void\n >;\n}>;\n\nconst messageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\ntype ZodIpcMessageHandlerOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n schema: TListenCatalog;\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n sender: ZodIpcMessageSender<TEmitCatalog>;\n};\n\nclass ZodIpcMessageHandler<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #schema: TListenCatalog;\n #handlers: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog> | undefined;\n #sender: ZodIpcMessageSender<TEmitCatalog>;\n\n constructor(options: ZodIpcMessageHandlerOptions<TListenCatalog, TEmitCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\n this.#sender = options.sender;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n // console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload, this.#sender);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessagesFromSocketCatalog<TListenCatalog> {\n const parsedMessage = messageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n}\n\nconst Packet = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"CONNECT\"),\n sessionId: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"ACK\"),\n message: z.any(),\n id: z.number(),\n }),\n z.object({\n type: z.literal(\"EVENT\"),\n message: z.any(),\n id: z.number().optional(),\n }),\n]);\n\ntype Packet = z.infer<typeof Packet>;\n\ninterface ZodIpcConnectionOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n listenSchema: TListenCatalog;\n emitSchema: TEmitCatalog;\n process: {\n send?: (message: any) => any;\n on?: (event: \"message\", listener: (message: any) => void) => void;\n };\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n}\n\nexport class ZodIpcConnection<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #sessionId?: string;\n #messageCounter: number = 0;\n\n #handler: ZodIpcMessageHandler<TListenCatalog, TEmitCatalog>;\n\n #acks: Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason?: any) => void;\n timeout: NodeJS.Timeout;\n }\n > = new Map();\n\n constructor(private opts: ZodIpcConnectionOptions<TListenCatalog, TEmitCatalog>) {\n this.#handler = new ZodIpcMessageHandler({\n schema: opts.listenSchema,\n handlers: opts.handlers,\n sender: {\n send: this.send.bind(this),\n sendWithAck: this.sendWithAck.bind(this),\n },\n });\n\n this.#registerHandlers();\n // this.connect();\n }\n\n async #registerHandlers() {\n if (!this.opts.process.on) {\n return;\n }\n\n this.opts.process.on(\"message\", async (message) => {\n this.#handlePacket(message);\n });\n }\n\n async connect() {\n this.#sendPacket({ type: \"CONNECT\" });\n }\n\n async #handlePacket(packet: Packet): Promise<void> {\n const parsedPacket = Packet.safeParse(packet);\n\n if (!parsedPacket.success) {\n return;\n }\n\n switch (parsedPacket.data.type) {\n case \"ACK\": {\n // Check our list of ACKs and resolve with the message\n const ack = this.#acks.get(parsedPacket.data.id);\n\n if (!ack) {\n return;\n }\n\n clearTimeout(ack.timeout);\n ack.resolve(parsedPacket.data.message);\n\n break;\n }\n case \"CONNECT\": {\n if (!parsedPacket.data.sessionId) {\n // This is a client trying to connect, so we generate and send back a session ID\n const id = randomUUID();\n\n await this.#sendPacket({ type: \"CONNECT\", sessionId: id });\n\n return;\n }\n\n // This is a server replying to our connect message\n if (this.#sessionId) {\n // We're already connected\n return;\n }\n\n this.#sessionId = parsedPacket.data.sessionId;\n\n break;\n }\n case \"EVENT\": {\n const result = await this.#handler.handleMessage(parsedPacket.data.message);\n\n if (typeof parsedPacket.data.id === \"undefined\") {\n return;\n }\n\n // There's an ID so we should ACK\n await this.#sendPacket({\n type: \"ACK\",\n id: parsedPacket.data.id,\n message: result,\n });\n\n break;\n }\n default: {\n break;\n }\n }\n }\n\n async #sendPacket(packet: Packet) {\n await this.opts.process.send?.(packet);\n }\n\n async send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void> {\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n });\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>,\n timeoutInMs?: number\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>> {\n const currentId = this.#messageCounter++;\n\n return new Promise(async (resolve, reject) => {\n const defaultTimeoutInMs = 2000;\n\n // Timeout if the ACK takes too long to get back to us\n const timeout = setTimeout(() => {\n reject(\n JSON.stringify({\n reason: \"sendWithAck() timeout\",\n timeoutInMs: timeoutInMs ?? defaultTimeoutInMs,\n type,\n payload,\n })\n );\n }, timeoutInMs ?? defaultTimeoutInMs);\n\n this.#acks.set(currentId, { resolve, reject, timeout });\n\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n clearTimeout(timeout);\n return reject(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n clearTimeout(timeout);\n return reject(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n id: currentId,\n });\n });\n }\n}\n","import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessageFromCatalog<TMessageCatalog> {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n callback(ack);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
1
+ {"version":3,"sources":["../../src/v3/zodIpc.ts","../../src/v3/zodMessageHandler.ts"],"names":["randomUUID","z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","messageSchema","ZodIpcMessageHandler","options","schema","handlers","sender","handleMessage","parsedMessage","parseMessage","handler","ack","safeParse","success","JSON","stringify","data","parsedPayload","Packet","discriminatedUnion","sessionId","optional","any","id","number","ZodIpcConnection","opts","Map","listenSchema","send","bind","sendWithAck","connect","emitSchema","timeoutInMs","currentId","Promise","resolve","reject","defaultTimeoutInMs","timeout","setTimeout","reason","set","clearTimeout","process","on","packet","parsedPacket","get","result"],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\nimport {\n GetSocketCallbackSchema,\n GetSocketMessageSchema,\n GetSocketMessagesWithCallback,\n GetSocketMessagesWithoutCallback,\n MessagesFromSocketCatalog,\n SocketMessageHasCallback,\n ZodSocketMessageCatalogSchema,\n} from \"./zodSocket\";\nimport { z } from \"zod\";\nimport { ZodSchemaParsedError } from \"./zodMessageHandler\";\nimport { inspect } from \"node:util\";\n\ninterface ZodIpcMessageSender<TEmitCatalog extends ZodSocketMessageCatalogSchema> {\n send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void>;\n\n sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>>;\n}\n\ntype ZodIpcMessageHandlers<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = Partial<{\n [K in keyof TListenCatalog]: (\n payload: z.infer<GetSocketMessageSchema<TListenCatalog, K>>,\n sender: ZodIpcMessageSender<TEmitCatalog>\n ) => Promise<\n SocketMessageHasCallback<TListenCatalog, K> extends true\n ? z.input<GetSocketCallbackSchema<TListenCatalog, K>>\n : void\n >;\n}>;\n\nconst messageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\ntype ZodIpcMessageHandlerOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n schema: TListenCatalog;\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n sender: ZodIpcMessageSender<TEmitCatalog>;\n};\n\nclass ZodIpcMessageHandler<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #schema: TListenCatalog;\n #handlers: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog> | undefined;\n #sender: ZodIpcMessageSender<TEmitCatalog>;\n\n constructor(options: ZodIpcMessageHandlerOptions<TListenCatalog, TEmitCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\n this.#sender = options.sender;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n // console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload, this.#sender);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessagesFromSocketCatalog<TListenCatalog> {\n const parsedMessage = messageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n}\n\nconst Packet = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"CONNECT\"),\n sessionId: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"ACK\"),\n message: z.any(),\n id: z.number(),\n }),\n z.object({\n type: z.literal(\"EVENT\"),\n message: z.any(),\n id: z.number().optional(),\n }),\n]);\n\ntype Packet = z.infer<typeof Packet>;\n\ninterface ZodIpcConnectionOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n listenSchema: TListenCatalog;\n emitSchema: TEmitCatalog;\n process: {\n send?: (message: any) => any;\n on?: (event: \"message\", listener: (message: any) => void) => void;\n };\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n}\n\nexport class ZodIpcConnection<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #sessionId?: string;\n #messageCounter: number = 0;\n\n #handler: ZodIpcMessageHandler<TListenCatalog, TEmitCatalog>;\n\n #acks: Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason?: any) => void;\n timeout: NodeJS.Timeout;\n }\n > = new Map();\n\n constructor(private opts: ZodIpcConnectionOptions<TListenCatalog, TEmitCatalog>) {\n this.#handler = new ZodIpcMessageHandler({\n schema: opts.listenSchema,\n handlers: opts.handlers,\n sender: {\n send: this.send.bind(this),\n sendWithAck: this.sendWithAck.bind(this),\n },\n });\n\n this.#registerHandlers();\n // this.connect();\n }\n\n async #registerHandlers() {\n if (!this.opts.process.on) {\n return;\n }\n\n this.opts.process.on(\"message\", async (message) => {\n this.#handlePacket(message);\n });\n }\n\n async connect() {\n this.#sendPacket({ type: \"CONNECT\" });\n }\n\n async #handlePacket(packet: Packet): Promise<void> {\n const parsedPacket = Packet.safeParse(packet);\n\n if (!parsedPacket.success) {\n return;\n }\n\n switch (parsedPacket.data.type) {\n case \"ACK\": {\n // Check our list of ACKs and resolve with the message\n const ack = this.#acks.get(parsedPacket.data.id);\n\n if (!ack) {\n return;\n }\n\n clearTimeout(ack.timeout);\n ack.resolve(parsedPacket.data.message);\n\n break;\n }\n case \"CONNECT\": {\n if (!parsedPacket.data.sessionId) {\n // This is a client trying to connect, so we generate and send back a session ID\n const id = randomUUID();\n\n await this.#sendPacket({ type: \"CONNECT\", sessionId: id });\n\n return;\n }\n\n // This is a server replying to our connect message\n if (this.#sessionId) {\n // We're already connected\n return;\n }\n\n this.#sessionId = parsedPacket.data.sessionId;\n\n break;\n }\n case \"EVENT\": {\n const result = await this.#handler.handleMessage(parsedPacket.data.message);\n\n if (typeof parsedPacket.data.id === \"undefined\") {\n return;\n }\n\n // There's an ID so we should ACK\n await this.#sendPacket({\n type: \"ACK\",\n id: parsedPacket.data.id,\n message: result,\n });\n\n break;\n }\n default: {\n break;\n }\n }\n }\n\n async #sendPacket(packet: Packet) {\n await this.opts.process.send?.(packet);\n }\n\n async send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void> {\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n });\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>,\n timeoutInMs?: number\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>> {\n const currentId = this.#messageCounter++;\n\n return new Promise(async (resolve, reject) => {\n const defaultTimeoutInMs = 2000;\n\n // Timeout if the ACK takes too long to get back to us\n const timeout = setTimeout(() => {\n reject(\n JSON.stringify({\n reason: \"sendWithAck() timeout\",\n timeoutInMs: timeoutInMs ?? defaultTimeoutInMs,\n type,\n payload,\n })\n );\n }, timeoutInMs ?? defaultTimeoutInMs);\n\n this.#acks.set(currentId, { resolve, reject, timeout });\n\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n clearTimeout(timeout);\n return reject(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n clearTimeout(timeout);\n return reject(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n id: currentId,\n });\n });\n }\n}\n","import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n #logger: StructuredLogger | Console;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n this.#logger = options.logger ?? console;\n }\n\n public async handleMessage(message: unknown): Promise<\n | {\n success: true;\n data: unknown;\n }\n | {\n success: false;\n error: string;\n }\n > {\n const parsedMessage = this.parseMessage(message);\n\n if (!parsedMessage.success) {\n this.#logger.error(parsedMessage.error, { message });\n\n return {\n success: false,\n error: parsedMessage.error,\n };\n }\n\n if (!this.#handlers) {\n this.#logger.error(\"No handlers provided\", { message });\n\n return {\n success: false,\n error: \"No handlers provided\",\n };\n }\n\n const handler = this.#handlers[parsedMessage.data.type];\n\n if (!handler) {\n const error = `No handler for message type: ${String(parsedMessage.data.type)}`;\n\n this.#logger.error(error, { message });\n\n return {\n success: false,\n error,\n };\n }\n\n const ack = await handler(parsedMessage.data.payload);\n\n return {\n success: true,\n data: ack,\n };\n }\n\n public parseMessage(message: unknown):\n | {\n success: true;\n data: MessageFromCatalog<TMessageCatalog>;\n }\n | {\n success: false;\n error: string;\n } {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n return {\n success: false,\n error: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n return {\n success: false,\n error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`,\n };\n }\n\n return {\n success: true,\n data: {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n },\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack: Awaited<ReturnType<ZodMessageHandler<TMessageCatalog>[\"handleMessage\"]>>;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n if (!ack.success) {\n // We don't know the callback type, so we can't do anything else - not all callbacks may accept a success prop\n log.error(\"Failed to handle message, skipping callback\", { message, error: ack.error });\n return;\n }\n\n callback(ack.data);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/v3/zodIpc.ts","../../src/v3/zodMessageHandler.ts"],"names":["randomUUID","z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","messageSchema","ZodIpcMessageHandler","options","schema","handlers","sender","handleMessage","parsedMessage","parseMessage","handler","ack","safeParse","success","JSON","stringify","data","parsedPayload","Packet","discriminatedUnion","sessionId","optional","any","id","number","ZodIpcConnection","opts","Map","listenSchema","send","bind","sendWithAck","connect","emitSchema","timeoutInMs","currentId","Promise","resolve","reject","defaultTimeoutInMs","timeout","setTimeout","reason","set","clearTimeout","process","on","packet","parsedPacket","get","result"],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\nimport {\n GetSocketCallbackSchema,\n GetSocketMessageSchema,\n GetSocketMessagesWithCallback,\n GetSocketMessagesWithoutCallback,\n MessagesFromSocketCatalog,\n SocketMessageHasCallback,\n ZodSocketMessageCatalogSchema,\n} from \"./zodSocket\";\nimport { z } from \"zod\";\nimport { ZodSchemaParsedError } from \"./zodMessageHandler\";\nimport { inspect } from \"node:util\";\n\ninterface ZodIpcMessageSender<TEmitCatalog extends ZodSocketMessageCatalogSchema> {\n send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void>;\n\n sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>>;\n}\n\ntype ZodIpcMessageHandlers<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = Partial<{\n [K in keyof TListenCatalog]: (\n payload: z.infer<GetSocketMessageSchema<TListenCatalog, K>>,\n sender: ZodIpcMessageSender<TEmitCatalog>\n ) => Promise<\n SocketMessageHasCallback<TListenCatalog, K> extends true\n ? z.input<GetSocketCallbackSchema<TListenCatalog, K>>\n : void\n >;\n}>;\n\nconst messageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\ntype ZodIpcMessageHandlerOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n schema: TListenCatalog;\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n sender: ZodIpcMessageSender<TEmitCatalog>;\n};\n\nclass ZodIpcMessageHandler<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #schema: TListenCatalog;\n #handlers: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog> | undefined;\n #sender: ZodIpcMessageSender<TEmitCatalog>;\n\n constructor(options: ZodIpcMessageHandlerOptions<TListenCatalog, TEmitCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\n this.#sender = options.sender;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n // console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload, this.#sender);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessagesFromSocketCatalog<TListenCatalog> {\n const parsedMessage = messageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n}\n\nconst Packet = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"CONNECT\"),\n sessionId: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"ACK\"),\n message: z.any(),\n id: z.number(),\n }),\n z.object({\n type: z.literal(\"EVENT\"),\n message: z.any(),\n id: z.number().optional(),\n }),\n]);\n\ntype Packet = z.infer<typeof Packet>;\n\ninterface ZodIpcConnectionOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n listenSchema: TListenCatalog;\n emitSchema: TEmitCatalog;\n process: {\n send?: (message: any) => any;\n on?: (event: \"message\", listener: (message: any) => void) => void;\n };\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n}\n\nexport class ZodIpcConnection<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #sessionId?: string;\n #messageCounter: number = 0;\n\n #handler: ZodIpcMessageHandler<TListenCatalog, TEmitCatalog>;\n\n #acks: Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason?: any) => void;\n timeout: NodeJS.Timeout;\n }\n > = new Map();\n\n constructor(private opts: ZodIpcConnectionOptions<TListenCatalog, TEmitCatalog>) {\n this.#handler = new ZodIpcMessageHandler({\n schema: opts.listenSchema,\n handlers: opts.handlers,\n sender: {\n send: this.send.bind(this),\n sendWithAck: this.sendWithAck.bind(this),\n },\n });\n\n this.#registerHandlers();\n // this.connect();\n }\n\n async #registerHandlers() {\n if (!this.opts.process.on) {\n return;\n }\n\n this.opts.process.on(\"message\", async (message) => {\n this.#handlePacket(message);\n });\n }\n\n async connect() {\n this.#sendPacket({ type: \"CONNECT\" });\n }\n\n async #handlePacket(packet: Packet): Promise<void> {\n const parsedPacket = Packet.safeParse(packet);\n\n if (!parsedPacket.success) {\n return;\n }\n\n switch (parsedPacket.data.type) {\n case \"ACK\": {\n // Check our list of ACKs and resolve with the message\n const ack = this.#acks.get(parsedPacket.data.id);\n\n if (!ack) {\n return;\n }\n\n clearTimeout(ack.timeout);\n ack.resolve(parsedPacket.data.message);\n\n break;\n }\n case \"CONNECT\": {\n if (!parsedPacket.data.sessionId) {\n // This is a client trying to connect, so we generate and send back a session ID\n const id = randomUUID();\n\n await this.#sendPacket({ type: \"CONNECT\", sessionId: id });\n\n return;\n }\n\n // This is a server replying to our connect message\n if (this.#sessionId) {\n // We're already connected\n return;\n }\n\n this.#sessionId = parsedPacket.data.sessionId;\n\n break;\n }\n case \"EVENT\": {\n const result = await this.#handler.handleMessage(parsedPacket.data.message);\n\n if (typeof parsedPacket.data.id === \"undefined\") {\n return;\n }\n\n // There's an ID so we should ACK\n await this.#sendPacket({\n type: \"ACK\",\n id: parsedPacket.data.id,\n message: result,\n });\n\n break;\n }\n default: {\n break;\n }\n }\n }\n\n async #sendPacket(packet: Packet) {\n await this.opts.process.send?.(packet);\n }\n\n async send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void> {\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n });\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>,\n timeoutInMs?: number\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>> {\n const currentId = this.#messageCounter++;\n\n return new Promise(async (resolve, reject) => {\n const defaultTimeoutInMs = 2000;\n\n // Timeout if the ACK takes too long to get back to us\n const timeout = setTimeout(() => {\n reject(\n JSON.stringify({\n reason: \"sendWithAck() timeout\",\n timeoutInMs: timeoutInMs ?? defaultTimeoutInMs,\n type,\n payload,\n })\n );\n }, timeoutInMs ?? defaultTimeoutInMs);\n\n this.#acks.set(currentId, { resolve, reject, timeout });\n\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n clearTimeout(timeout);\n return reject(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n clearTimeout(timeout);\n return reject(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n id: currentId,\n });\n });\n }\n}\n","import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessageFromCatalog<TMessageCatalog> {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n callback(ack);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
1
+ {"version":3,"sources":["../../src/v3/zodIpc.ts","../../src/v3/zodMessageHandler.ts"],"names":["randomUUID","z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","messageSchema","ZodIpcMessageHandler","options","schema","handlers","sender","handleMessage","parsedMessage","parseMessage","handler","ack","safeParse","success","JSON","stringify","data","parsedPayload","Packet","discriminatedUnion","sessionId","optional","any","id","number","ZodIpcConnection","opts","Map","listenSchema","send","bind","sendWithAck","connect","emitSchema","timeoutInMs","currentId","Promise","resolve","reject","defaultTimeoutInMs","timeout","setTimeout","reason","set","clearTimeout","process","on","packet","parsedPacket","get","result"],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\nimport {\n GetSocketCallbackSchema,\n GetSocketMessageSchema,\n GetSocketMessagesWithCallback,\n GetSocketMessagesWithoutCallback,\n MessagesFromSocketCatalog,\n SocketMessageHasCallback,\n ZodSocketMessageCatalogSchema,\n} from \"./zodSocket\";\nimport { z } from \"zod\";\nimport { ZodSchemaParsedError } from \"./zodMessageHandler\";\nimport { inspect } from \"node:util\";\n\ninterface ZodIpcMessageSender<TEmitCatalog extends ZodSocketMessageCatalogSchema> {\n send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void>;\n\n sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>>;\n}\n\ntype ZodIpcMessageHandlers<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = Partial<{\n [K in keyof TListenCatalog]: (\n payload: z.infer<GetSocketMessageSchema<TListenCatalog, K>>,\n sender: ZodIpcMessageSender<TEmitCatalog>\n ) => Promise<\n SocketMessageHasCallback<TListenCatalog, K> extends true\n ? z.input<GetSocketCallbackSchema<TListenCatalog, K>>\n : void\n >;\n}>;\n\nconst messageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\ntype ZodIpcMessageHandlerOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n schema: TListenCatalog;\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n sender: ZodIpcMessageSender<TEmitCatalog>;\n};\n\nclass ZodIpcMessageHandler<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #schema: TListenCatalog;\n #handlers: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog> | undefined;\n #sender: ZodIpcMessageSender<TEmitCatalog>;\n\n constructor(options: ZodIpcMessageHandlerOptions<TListenCatalog, TEmitCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\n this.#sender = options.sender;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n // console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload, this.#sender);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessagesFromSocketCatalog<TListenCatalog> {\n const parsedMessage = messageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n}\n\nconst Packet = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"CONNECT\"),\n sessionId: z.string().optional(),\n }),\n z.object({\n type: z.literal(\"ACK\"),\n message: z.any(),\n id: z.number(),\n }),\n z.object({\n type: z.literal(\"EVENT\"),\n message: z.any(),\n id: z.number().optional(),\n }),\n]);\n\ntype Packet = z.infer<typeof Packet>;\n\ninterface ZodIpcConnectionOptions<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n listenSchema: TListenCatalog;\n emitSchema: TEmitCatalog;\n process: {\n send?: (message: any) => any;\n on?: (event: \"message\", listener: (message: any) => void) => void;\n };\n handlers?: ZodIpcMessageHandlers<TListenCatalog, TEmitCatalog>;\n}\n\nexport class ZodIpcConnection<\n TListenCatalog extends ZodSocketMessageCatalogSchema,\n TEmitCatalog extends ZodSocketMessageCatalogSchema,\n> {\n #sessionId?: string;\n #messageCounter: number = 0;\n\n #handler: ZodIpcMessageHandler<TListenCatalog, TEmitCatalog>;\n\n #acks: Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason?: any) => void;\n timeout: NodeJS.Timeout;\n }\n > = new Map();\n\n constructor(private opts: ZodIpcConnectionOptions<TListenCatalog, TEmitCatalog>) {\n this.#handler = new ZodIpcMessageHandler({\n schema: opts.listenSchema,\n handlers: opts.handlers,\n sender: {\n send: this.send.bind(this),\n sendWithAck: this.sendWithAck.bind(this),\n },\n });\n\n this.#registerHandlers();\n // this.connect();\n }\n\n async #registerHandlers() {\n if (!this.opts.process.on) {\n return;\n }\n\n this.opts.process.on(\"message\", async (message) => {\n this.#handlePacket(message);\n });\n }\n\n async connect() {\n this.#sendPacket({ type: \"CONNECT\" });\n }\n\n async #handlePacket(packet: Packet): Promise<void> {\n const parsedPacket = Packet.safeParse(packet);\n\n if (!parsedPacket.success) {\n return;\n }\n\n switch (parsedPacket.data.type) {\n case \"ACK\": {\n // Check our list of ACKs and resolve with the message\n const ack = this.#acks.get(parsedPacket.data.id);\n\n if (!ack) {\n return;\n }\n\n clearTimeout(ack.timeout);\n ack.resolve(parsedPacket.data.message);\n\n break;\n }\n case \"CONNECT\": {\n if (!parsedPacket.data.sessionId) {\n // This is a client trying to connect, so we generate and send back a session ID\n const id = randomUUID();\n\n await this.#sendPacket({ type: \"CONNECT\", sessionId: id });\n\n return;\n }\n\n // This is a server replying to our connect message\n if (this.#sessionId) {\n // We're already connected\n return;\n }\n\n this.#sessionId = parsedPacket.data.sessionId;\n\n break;\n }\n case \"EVENT\": {\n const result = await this.#handler.handleMessage(parsedPacket.data.message);\n\n if (typeof parsedPacket.data.id === \"undefined\") {\n return;\n }\n\n // There's an ID so we should ACK\n await this.#sendPacket({\n type: \"ACK\",\n id: parsedPacket.data.id,\n message: result,\n });\n\n break;\n }\n default: {\n break;\n }\n }\n }\n\n async #sendPacket(packet: Packet) {\n await this.opts.process.send?.(packet);\n }\n\n async send<K extends GetSocketMessagesWithoutCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>\n ): Promise<void> {\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n });\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TEmitCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TEmitCatalog, K>>,\n timeoutInMs?: number\n ): Promise<z.infer<GetSocketCallbackSchema<TEmitCatalog, K>>> {\n const currentId = this.#messageCounter++;\n\n return new Promise(async (resolve, reject) => {\n const defaultTimeoutInMs = 2000;\n\n // Timeout if the ACK takes too long to get back to us\n const timeout = setTimeout(() => {\n reject(\n JSON.stringify({\n reason: \"sendWithAck() timeout\",\n timeoutInMs: timeoutInMs ?? defaultTimeoutInMs,\n type,\n payload,\n })\n );\n }, timeoutInMs ?? defaultTimeoutInMs);\n\n this.#acks.set(currentId, { resolve, reject, timeout });\n\n const schema = this.opts.emitSchema[type][\"message\"];\n\n if (!schema) {\n clearTimeout(timeout);\n return reject(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n clearTimeout(timeout);\n return reject(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sendPacket({\n type: \"EVENT\",\n message: {\n type,\n payload,\n version: \"v1\",\n },\n id: currentId,\n });\n });\n }\n}\n","import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n #logger: StructuredLogger | Console;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n this.#logger = options.logger ?? console;\n }\n\n public async handleMessage(message: unknown): Promise<\n | {\n success: true;\n data: unknown;\n }\n | {\n success: false;\n error: string;\n }\n > {\n const parsedMessage = this.parseMessage(message);\n\n if (!parsedMessage.success) {\n this.#logger.error(parsedMessage.error, { message });\n\n return {\n success: false,\n error: parsedMessage.error,\n };\n }\n\n if (!this.#handlers) {\n this.#logger.error(\"No handlers provided\", { message });\n\n return {\n success: false,\n error: \"No handlers provided\",\n };\n }\n\n const handler = this.#handlers[parsedMessage.data.type];\n\n if (!handler) {\n const error = `No handler for message type: ${String(parsedMessage.data.type)}`;\n\n this.#logger.error(error, { message });\n\n return {\n success: false,\n error,\n };\n }\n\n const ack = await handler(parsedMessage.data.payload);\n\n return {\n success: true,\n data: ack,\n };\n }\n\n public parseMessage(message: unknown):\n | {\n success: true;\n data: MessageFromCatalog<TMessageCatalog>;\n }\n | {\n success: false;\n error: string;\n } {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n return {\n success: false,\n error: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n return {\n success: false,\n error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`,\n };\n }\n\n return {\n success: true,\n data: {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n },\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack: Awaited<ReturnType<ZodMessageHandler<TMessageCatalog>[\"handleMessage\"]>>;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n if (!ack.success) {\n // We don't know the callback type, so we can't do anything else - not all callbacks may accept a success prop\n log.error(\"Failed to handle message, skipping callback\", { message, error: ack.error });\n return;\n }\n\n callback(ack.data);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
@@ -16,6 +16,7 @@ type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partia
16
16
  type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {
17
17
  schema: TMessageCatalog;
18
18
  messages?: ZodMessageHandlers<TMessageCatalog>;
19
+ logger?: StructuredLogger;
19
20
  };
20
21
  type MessageFromSchema<K extends keyof TMessageCatalog, TMessageCatalog extends ZodMessageCatalogSchema> = {
21
22
  type: K;
@@ -29,8 +30,8 @@ declare const ZodMessageSchema: z.ZodObject<{
29
30
  type: z.ZodString;
30
31
  payload: z.ZodUnknown;
31
32
  }, "strip", z.ZodTypeAny, {
32
- version: "v1";
33
33
  type: string;
34
+ version: "v1";
34
35
  payload?: unknown;
35
36
  }, {
36
37
  type: string;
@@ -43,8 +44,20 @@ interface EventEmitterLike {
43
44
  declare class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {
44
45
  #private;
45
46
  constructor(options: ZodMessageHandlerOptions<TMessageCatalog>);
46
- handleMessage(message: unknown): Promise<any>;
47
- parseMessage(message: unknown): MessageFromCatalog<TMessageCatalog>;
47
+ handleMessage(message: unknown): Promise<{
48
+ success: true;
49
+ data: unknown;
50
+ } | {
51
+ success: false;
52
+ error: string;
53
+ }>;
54
+ parseMessage(message: unknown): {
55
+ success: true;
56
+ data: MessageFromCatalog<TMessageCatalog>;
57
+ } | {
58
+ success: false;
59
+ error: string;
60
+ };
48
61
  registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger): void;
49
62
  }
50
63
  type ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {
@@ -16,6 +16,7 @@ type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partia
16
16
  type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {
17
17
  schema: TMessageCatalog;
18
18
  messages?: ZodMessageHandlers<TMessageCatalog>;
19
+ logger?: StructuredLogger;
19
20
  };
20
21
  type MessageFromSchema<K extends keyof TMessageCatalog, TMessageCatalog extends ZodMessageCatalogSchema> = {
21
22
  type: K;
@@ -29,8 +30,8 @@ declare const ZodMessageSchema: z.ZodObject<{
29
30
  type: z.ZodString;
30
31
  payload: z.ZodUnknown;
31
32
  }, "strip", z.ZodTypeAny, {
32
- version: "v1";
33
33
  type: string;
34
+ version: "v1";
34
35
  payload?: unknown;
35
36
  }, {
36
37
  type: string;
@@ -43,8 +44,20 @@ interface EventEmitterLike {
43
44
  declare class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {
44
45
  #private;
45
46
  constructor(options: ZodMessageHandlerOptions<TMessageCatalog>);
46
- handleMessage(message: unknown): Promise<any>;
47
- parseMessage(message: unknown): MessageFromCatalog<TMessageCatalog>;
47
+ handleMessage(message: unknown): Promise<{
48
+ success: true;
49
+ data: unknown;
50
+ } | {
51
+ success: false;
52
+ error: string;
53
+ }>;
54
+ parseMessage(message: unknown): {
55
+ success: true;
56
+ data: MessageFromCatalog<TMessageCatalog>;
57
+ } | {
58
+ success: false;
59
+ error: string;
60
+ };
48
61
  registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger): void;
49
62
  }
50
63
  type ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {
@@ -36,43 +36,81 @@ var ZodMessageSchema = zod.z.object({
36
36
  type: zod.z.string(),
37
37
  payload: zod.z.unknown()
38
38
  });
39
- var _schema, _handlers;
39
+ var _schema, _handlers, _logger;
40
40
  var _ZodMessageHandler = class _ZodMessageHandler {
41
41
  constructor(options) {
42
42
  __privateAdd(this, _schema, void 0);
43
43
  __privateAdd(this, _handlers, void 0);
44
+ __privateAdd(this, _logger, void 0);
44
45
  __privateSet(this, _schema, options.schema);
45
46
  __privateSet(this, _handlers, options.messages);
47
+ __privateSet(this, _logger, options.logger ?? console);
46
48
  }
47
49
  async handleMessage(message) {
48
50
  const parsedMessage = this.parseMessage(message);
51
+ if (!parsedMessage.success) {
52
+ __privateGet(this, _logger).error(parsedMessage.error, {
53
+ message
54
+ });
55
+ return {
56
+ success: false,
57
+ error: parsedMessage.error
58
+ };
59
+ }
49
60
  if (!__privateGet(this, _handlers)) {
50
- throw new Error("No handlers provided");
61
+ __privateGet(this, _logger).error("No handlers provided", {
62
+ message
63
+ });
64
+ return {
65
+ success: false,
66
+ error: "No handlers provided"
67
+ };
51
68
  }
52
- const handler = __privateGet(this, _handlers)[parsedMessage.type];
69
+ const handler = __privateGet(this, _handlers)[parsedMessage.data.type];
53
70
  if (!handler) {
54
- console.error(`No handler for message type: ${String(parsedMessage.type)}`);
55
- return;
71
+ const error = `No handler for message type: ${String(parsedMessage.data.type)}`;
72
+ __privateGet(this, _logger).error(error, {
73
+ message
74
+ });
75
+ return {
76
+ success: false,
77
+ error
78
+ };
56
79
  }
57
- const ack = await handler(parsedMessage.payload);
58
- return ack;
80
+ const ack = await handler(parsedMessage.data.payload);
81
+ return {
82
+ success: true,
83
+ data: ack
84
+ };
59
85
  }
60
86
  parseMessage(message) {
61
87
  const parsedMessage = ZodMessageSchema.safeParse(message);
62
88
  if (!parsedMessage.success) {
63
- throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);
89
+ return {
90
+ success: false,
91
+ error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`
92
+ };
64
93
  }
65
94
  const schema = __privateGet(this, _schema)[parsedMessage.data.type];
66
95
  if (!schema) {
67
- throw new Error(`Unknown message type: ${parsedMessage.data.type}`);
96
+ return {
97
+ success: false,
98
+ error: `Unknown message type: ${parsedMessage.data.type}`
99
+ };
68
100
  }
69
101
  const parsedPayload = schema.safeParse(parsedMessage.data.payload);
70
102
  if (!parsedPayload.success) {
71
- throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);
103
+ return {
104
+ success: false,
105
+ error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`
106
+ };
72
107
  }
73
108
  return {
74
- type: parsedMessage.data.type,
75
- payload: parsedPayload.data
109
+ success: true,
110
+ data: {
111
+ type: parsedMessage.data.type,
112
+ payload: parsedPayload.data
113
+ }
76
114
  };
77
115
  }
78
116
  registerHandlers(emitter, logger) {
@@ -102,7 +140,14 @@ var _ZodMessageHandler = class _ZodMessageHandler {
102
140
  });
103
141
  }
104
142
  if (callback && typeof callback === "function") {
105
- callback(ack);
143
+ if (!ack.success) {
144
+ log.error("Failed to handle message, skipping callback", {
145
+ message,
146
+ error: ack.error
147
+ });
148
+ return;
149
+ }
150
+ callback(ack.data);
106
151
  }
107
152
  });
108
153
  }
@@ -110,6 +155,7 @@ var _ZodMessageHandler = class _ZodMessageHandler {
110
155
  };
111
156
  _schema = new WeakMap();
112
157
  _handlers = new WeakMap();
158
+ _logger = new WeakMap();
113
159
  __name(_ZodMessageHandler, "ZodMessageHandler");
114
160
  var ZodMessageHandler = _ZodMessageHandler;
115
161
  var _schema2, _sender;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/v3/zodMessageHandler.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageHandler","options","schema","messages","handleMessage","parsedMessage","parseMessage","handler","console","String","ack","safeParse","success","JSON","stringify","data","parsedPayload","registerHandlers","emitter","logger","log","info","eventName","Object","keys","on","callback","hasCallback","_schema","ZodMessageSender","sender","send","forwardMessage"],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n }\n\n public async handleMessage(message: unknown) {\n const parsedMessage = this.parseMessage(message);\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const handler = this.#handlers[parsedMessage.type];\n\n if (!handler) {\n console.error(`No handler for message type: ${String(parsedMessage.type)}`);\n return;\n }\n\n const ack = await handler(parsedMessage.payload);\n\n return ack;\n }\n\n public parseMessage(message: unknown): MessageFromCatalog<TMessageCatalog> {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n return {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n callback(ack);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
1
+ {"version":3,"sources":["../../src/v3/zodMessageHandler.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageHandler","options","schema","messages","logger","console","handleMessage","parsedMessage","parseMessage","success","handler","data","String","ack","safeParse","JSON","stringify","parsedPayload","registerHandlers","emitter","log","info","eventName","Object","keys","on","callback","hasCallback","_schema","ZodMessageSender","sender","send","forwardMessage"],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n #logger: StructuredLogger | Console;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n this.#logger = options.logger ?? console;\n }\n\n public async handleMessage(message: unknown): Promise<\n | {\n success: true;\n data: unknown;\n }\n | {\n success: false;\n error: string;\n }\n > {\n const parsedMessage = this.parseMessage(message);\n\n if (!parsedMessage.success) {\n this.#logger.error(parsedMessage.error, { message });\n\n return {\n success: false,\n error: parsedMessage.error,\n };\n }\n\n if (!this.#handlers) {\n this.#logger.error(\"No handlers provided\", { message });\n\n return {\n success: false,\n error: \"No handlers provided\",\n };\n }\n\n const handler = this.#handlers[parsedMessage.data.type];\n\n if (!handler) {\n const error = `No handler for message type: ${String(parsedMessage.data.type)}`;\n\n this.#logger.error(error, { message });\n\n return {\n success: false,\n error,\n };\n }\n\n const ack = await handler(parsedMessage.data.payload);\n\n return {\n success: true,\n data: ack,\n };\n }\n\n public parseMessage(message: unknown):\n | {\n success: true;\n data: MessageFromCatalog<TMessageCatalog>;\n }\n | {\n success: false;\n error: string;\n } {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n return {\n success: false,\n error: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n return {\n success: false,\n error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`,\n };\n }\n\n return {\n success: true,\n data: {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n },\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack: Awaited<ReturnType<ZodMessageHandler<TMessageCatalog>[\"handleMessage\"]>>;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n if (!ack.success) {\n // We don't know the callback type, so we can't do anything else - not all callbacks may accept a success prop\n log.error(\"Failed to handle message, skipping callback\", { message, error: ack.error });\n return;\n }\n\n callback(ack.data);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
@@ -34,43 +34,81 @@ var ZodMessageSchema = z.object({
34
34
  type: z.string(),
35
35
  payload: z.unknown()
36
36
  });
37
- var _schema, _handlers;
37
+ var _schema, _handlers, _logger;
38
38
  var _ZodMessageHandler = class _ZodMessageHandler {
39
39
  constructor(options) {
40
40
  __privateAdd(this, _schema, void 0);
41
41
  __privateAdd(this, _handlers, void 0);
42
+ __privateAdd(this, _logger, void 0);
42
43
  __privateSet(this, _schema, options.schema);
43
44
  __privateSet(this, _handlers, options.messages);
45
+ __privateSet(this, _logger, options.logger ?? console);
44
46
  }
45
47
  async handleMessage(message) {
46
48
  const parsedMessage = this.parseMessage(message);
49
+ if (!parsedMessage.success) {
50
+ __privateGet(this, _logger).error(parsedMessage.error, {
51
+ message
52
+ });
53
+ return {
54
+ success: false,
55
+ error: parsedMessage.error
56
+ };
57
+ }
47
58
  if (!__privateGet(this, _handlers)) {
48
- throw new Error("No handlers provided");
59
+ __privateGet(this, _logger).error("No handlers provided", {
60
+ message
61
+ });
62
+ return {
63
+ success: false,
64
+ error: "No handlers provided"
65
+ };
49
66
  }
50
- const handler = __privateGet(this, _handlers)[parsedMessage.type];
67
+ const handler = __privateGet(this, _handlers)[parsedMessage.data.type];
51
68
  if (!handler) {
52
- console.error(`No handler for message type: ${String(parsedMessage.type)}`);
53
- return;
69
+ const error = `No handler for message type: ${String(parsedMessage.data.type)}`;
70
+ __privateGet(this, _logger).error(error, {
71
+ message
72
+ });
73
+ return {
74
+ success: false,
75
+ error
76
+ };
54
77
  }
55
- const ack = await handler(parsedMessage.payload);
56
- return ack;
78
+ const ack = await handler(parsedMessage.data.payload);
79
+ return {
80
+ success: true,
81
+ data: ack
82
+ };
57
83
  }
58
84
  parseMessage(message) {
59
85
  const parsedMessage = ZodMessageSchema.safeParse(message);
60
86
  if (!parsedMessage.success) {
61
- throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);
87
+ return {
88
+ success: false,
89
+ error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`
90
+ };
62
91
  }
63
92
  const schema = __privateGet(this, _schema)[parsedMessage.data.type];
64
93
  if (!schema) {
65
- throw new Error(`Unknown message type: ${parsedMessage.data.type}`);
94
+ return {
95
+ success: false,
96
+ error: `Unknown message type: ${parsedMessage.data.type}`
97
+ };
66
98
  }
67
99
  const parsedPayload = schema.safeParse(parsedMessage.data.payload);
68
100
  if (!parsedPayload.success) {
69
- throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);
101
+ return {
102
+ success: false,
103
+ error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`
104
+ };
70
105
  }
71
106
  return {
72
- type: parsedMessage.data.type,
73
- payload: parsedPayload.data
107
+ success: true,
108
+ data: {
109
+ type: parsedMessage.data.type,
110
+ payload: parsedPayload.data
111
+ }
74
112
  };
75
113
  }
76
114
  registerHandlers(emitter, logger) {
@@ -100,7 +138,14 @@ var _ZodMessageHandler = class _ZodMessageHandler {
100
138
  });
101
139
  }
102
140
  if (callback && typeof callback === "function") {
103
- callback(ack);
141
+ if (!ack.success) {
142
+ log.error("Failed to handle message, skipping callback", {
143
+ message,
144
+ error: ack.error
145
+ });
146
+ return;
147
+ }
148
+ callback(ack.data);
104
149
  }
105
150
  });
106
151
  }
@@ -108,6 +153,7 @@ var _ZodMessageHandler = class _ZodMessageHandler {
108
153
  };
109
154
  _schema = new WeakMap();
110
155
  _handlers = new WeakMap();
156
+ _logger = new WeakMap();
111
157
  __name(_ZodMessageHandler, "ZodMessageHandler");
112
158
  var ZodMessageHandler = _ZodMessageHandler;
113
159
  var _schema2, _sender;