@trigger.dev/core 3.0.0-beta.37 → 3.0.0-beta.38

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 (37) hide show
  1. package/dist/{catalog-dRKTgwQ7.d.ts → catalog-Tdea4K0I.d.mts} +43 -3
  2. package/dist/{catalog-XTlJQaMn.d.mts → catalog-yeAHwmSe.d.ts} +43 -3
  3. package/dist/{manager-JkbddlcO.d.mts → manager-S98VaLUy.d.mts} +244 -1
  4. package/dist/{manager-JkbddlcO.d.ts → manager-S98VaLUy.d.ts} +244 -1
  5. package/dist/{messages-9lty-Du5.d.mts → messages-BD0yXLtn.d.mts} +2370 -141
  6. package/dist/{messages-9lty-Du5.d.ts → messages-BD0yXLtn.d.ts} +2370 -141
  7. package/dist/{schemas-r4ZP9S-F.d.mts → schemas-XNxZYXOy.d.mts} +199 -33
  8. package/dist/{schemas-r4ZP9S-F.d.ts → schemas-XNxZYXOy.d.ts} +199 -33
  9. package/dist/v3/dev/index.d.mts +1 -1
  10. package/dist/v3/dev/index.d.ts +1 -1
  11. package/dist/v3/index.d.mts +117 -52
  12. package/dist/v3/index.d.ts +117 -52
  13. package/dist/v3/index.js +204 -58
  14. package/dist/v3/index.js.map +1 -1
  15. package/dist/v3/index.mjs +199 -58
  16. package/dist/v3/index.mjs.map +1 -1
  17. package/dist/v3/otel/index.js +15 -5
  18. package/dist/v3/otel/index.js.map +1 -1
  19. package/dist/v3/otel/index.mjs +15 -5
  20. package/dist/v3/otel/index.mjs.map +1 -1
  21. package/dist/v3/prod/index.d.mts +2 -2
  22. package/dist/v3/prod/index.d.ts +2 -2
  23. package/dist/v3/prod/index.js.map +1 -1
  24. package/dist/v3/prod/index.mjs.map +1 -1
  25. package/dist/v3/workers/index.d.mts +54 -8
  26. package/dist/v3/workers/index.d.ts +54 -8
  27. package/dist/v3/workers/index.js +404 -43
  28. package/dist/v3/workers/index.js.map +1 -1
  29. package/dist/v3/workers/index.mjs +402 -44
  30. package/dist/v3/workers/index.mjs.map +1 -1
  31. package/dist/v3/zodIpc.js.map +1 -1
  32. package/dist/v3/zodIpc.mjs.map +1 -1
  33. package/dist/v3/zodMessageHandler.d.mts +1 -1
  34. package/dist/v3/zodMessageHandler.d.ts +1 -1
  35. package/dist/v3/zodfetch.d.mts +1 -1
  36. package/dist/v3/zodfetch.d.ts +1 -1
  37. package/package.json +1 -1
@@ -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\";\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 // console.error(\"dropping invalid packet\", packet);\n return;\n }\n\n // console.log(\"<-\", packet);\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 // console.log(\"->\", 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 await this.#sender({ type, payload, version: \"v1\" });\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 await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\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};\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 await this.#sender({ type, payload, version: \"v1\" });\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 await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\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\";\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 // console.error(\"dropping invalid packet\", packet);\n return;\n }\n\n // console.log(\"<-\", packet);\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 // console.log(\"->\", 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 await this.#sender({ type, payload, version: \"v1\" });\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 await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\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};\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 await this.#sender({ type, payload, version: \"v1\" });\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 await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
@@ -29,8 +29,8 @@ declare const ZodMessageSchema: z.ZodObject<{
29
29
  type: z.ZodString;
30
30
  payload: z.ZodUnknown;
31
31
  }, "strip", z.ZodTypeAny, {
32
- version: "v1";
33
32
  type: string;
33
+ version: "v1";
34
34
  payload?: unknown;
35
35
  }, {
36
36
  type: string;
@@ -29,8 +29,8 @@ declare const ZodMessageSchema: z.ZodObject<{
29
29
  type: z.ZodString;
30
30
  payload: z.ZodUnknown;
31
31
  }, "strip", z.ZodTypeAny, {
32
- version: "v1";
33
32
  type: string;
33
+ version: "v1";
34
34
  payload?: unknown;
35
35
  }, {
36
36
  type: string;
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { R as RetryOptions } from '../schemas-r4ZP9S-F.mjs';
2
+ import { R as RetryOptions } from '../schemas-XNxZYXOy.mjs';
3
3
  import { Readable } from 'node:stream';
4
4
 
5
5
  interface CursorPageParams {
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { R as RetryOptions } from '../schemas-r4ZP9S-F.js';
2
+ import { R as RetryOptions } from '../schemas-XNxZYXOy.js';
3
3
  import { Readable } from 'node:stream';
4
4
 
5
5
  interface CursorPageParams {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trigger.dev/core",
3
- "version": "3.0.0-beta.37",
3
+ "version": "3.0.0-beta.38",
4
4
  "description": "Core code used across the Trigger.dev SDK and platform",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",