@trigger.dev/core 3.0.0-beta.44 → 3.0.0-beta.46

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 (61) hide show
  1. package/dist/{catalog-EP9DGAGm.d.ts → catalog-9G8AqnI9.d.ts} +2 -2
  2. package/dist/{catalog-Gjy5NtAB.d.mts → catalog-Y0mRLMtJ.d.mts} +2 -2
  3. package/dist/{manager-S98VaLUy.d.mts → common-55Mqj8JP.d.mts} +24 -16
  4. package/dist/{manager-S98VaLUy.d.ts → common-55Mqj8JP.d.ts} +24 -16
  5. package/dist/manager-2AqSY67c.d.mts +18 -0
  6. package/dist/manager-6NRInm7C.d.ts +18 -0
  7. package/dist/{messages-xJbR1Vai.d.mts → messages-nXkzt5CT.d.mts} +211 -70
  8. package/dist/{messages-xJbR1Vai.d.ts → messages-nXkzt5CT.d.ts} +211 -70
  9. package/dist/{schemas-Sb0sJcEt.d.mts → schemas-CeAee_C2.d.mts} +3 -0
  10. package/dist/{schemas-Sb0sJcEt.d.ts → schemas-CeAee_C2.d.ts} +3 -0
  11. package/dist/v3/dev/index.d.mts +2 -1
  12. package/dist/v3/dev/index.d.ts +2 -1
  13. package/dist/v3/dev/index.js.map +1 -1
  14. package/dist/v3/dev/index.mjs.map +1 -1
  15. package/dist/v3/index.d.mts +64 -4571
  16. package/dist/v3/index.d.ts +64 -4571
  17. package/dist/v3/index.js +63 -47
  18. package/dist/v3/index.js.map +1 -1
  19. package/dist/v3/index.mjs +62 -48
  20. package/dist/v3/index.mjs.map +1 -1
  21. package/dist/v3/otel/index.js +1 -1
  22. package/dist/v3/otel/index.js.map +1 -1
  23. package/dist/v3/otel/index.mjs +1 -1
  24. package/dist/v3/otel/index.mjs.map +1 -1
  25. package/dist/v3/prod/index.d.mts +4 -3
  26. package/dist/v3/prod/index.d.ts +4 -3
  27. package/dist/v3/prod/index.js +7 -131
  28. package/dist/v3/prod/index.js.map +1 -1
  29. package/dist/v3/prod/index.mjs +7 -131
  30. package/dist/v3/prod/index.mjs.map +1 -1
  31. package/dist/v3/schemas/index.d.mts +4633 -0
  32. package/dist/v3/schemas/index.d.ts +4633 -0
  33. package/dist/v3/schemas/index.js +2015 -0
  34. package/dist/v3/schemas/index.js.map +1 -0
  35. package/dist/v3/schemas/index.mjs +1878 -0
  36. package/dist/v3/schemas/index.mjs.map +1 -0
  37. package/dist/v3/utils/timers.d.mts +6 -0
  38. package/dist/v3/utils/timers.d.ts +6 -0
  39. package/dist/v3/utils/timers.js +31 -0
  40. package/dist/v3/utils/timers.js.map +1 -0
  41. package/dist/v3/utils/timers.mjs +28 -0
  42. package/dist/v3/utils/timers.mjs.map +1 -0
  43. package/dist/v3/workers/index.d.mts +6 -6
  44. package/dist/v3/workers/index.d.ts +6 -6
  45. package/dist/v3/workers/index.js +26 -5
  46. package/dist/v3/workers/index.js.map +1 -1
  47. package/dist/v3/workers/index.mjs +26 -5
  48. package/dist/v3/workers/index.mjs.map +1 -1
  49. package/dist/v3/zodNamespace.js +41 -18
  50. package/dist/v3/zodNamespace.js.map +1 -1
  51. package/dist/v3/zodNamespace.mjs +42 -19
  52. package/dist/v3/zodNamespace.mjs.map +1 -1
  53. package/dist/v3/zodSocket.d.mts +8 -3
  54. package/dist/v3/zodSocket.d.ts +8 -3
  55. package/dist/v3/zodSocket.js +56 -25
  56. package/dist/v3/zodSocket.js.map +1 -1
  57. package/dist/v3/zodSocket.mjs +57 -26
  58. package/dist/v3/zodSocket.mjs.map +1 -1
  59. package/dist/v3/zodfetch.d.mts +1 -1
  60. package/dist/v3/zodfetch.d.ts +1 -1
  61. package/package.json +18 -2
@@ -169,35 +169,51 @@ var messageSchema = zod.z.object({
169
169
  type: zod.z.string(),
170
170
  payload: zod.z.unknown()
171
171
  });
172
- var _schema2, _handlers;
172
+ var _schema2, _handlers, _logger;
173
173
  var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
174
174
  constructor(options) {
175
175
  __privateAdd(this, _schema2, void 0);
176
176
  __privateAdd(this, _handlers, void 0);
177
+ __privateAdd(this, _logger, void 0);
177
178
  __privateSet(this, _schema2, options.schema);
178
179
  __privateSet(this, _handlers, options.handlers);
180
+ __privateSet(this, _logger, options.logger ?? new SimpleStructuredLogger("socket-message-handler", LogLevel.info));
179
181
  }
180
182
  async handleMessage(message) {
181
- const parsedMessage = this.parseMessage(message);
183
+ const parseResult = this.parseMessage(message);
184
+ if (!parseResult.success) {
185
+ __privateGet(this, _logger).error("Failed to parse message, skipping handler", {
186
+ rawMessage: message,
187
+ error: parseResult.reason
188
+ });
189
+ return;
190
+ }
182
191
  if (!__privateGet(this, _handlers)) {
183
192
  throw new Error("No handlers provided");
184
193
  }
185
- const handler = __privateGet(this, _handlers)[parsedMessage.type];
194
+ const { type, payload } = parseResult.data;
195
+ const handler = __privateGet(this, _handlers)[type];
186
196
  if (!handler) {
187
- console.error(`No handler for message type: ${String(parsedMessage.type)}`);
197
+ console.error(`No handler for message type: ${String(type)}`);
188
198
  return;
189
199
  }
190
- const ack = await handler(parsedMessage.payload);
200
+ const ack = await handler(payload);
191
201
  return ack;
192
202
  }
193
203
  parseMessage(message) {
194
204
  const parsedMessage = messageSchema.safeParse(message);
195
205
  if (!parsedMessage.success) {
196
- throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);
206
+ return {
207
+ success: false,
208
+ reason: `Failed to parse message: ${zodValidationError.fromZodError(parsedMessage.error).toString()}`
209
+ };
197
210
  }
198
211
  const schema = __privateGet(this, _schema2)[parsedMessage.data.type]["message"];
199
212
  if (!schema) {
200
- throw new Error(`Unknown message type: ${parsedMessage.data.type}`);
213
+ return {
214
+ success: false,
215
+ reason: `Unknown message type: ${parsedMessage.data.type}`
216
+ };
201
217
  }
202
218
  const messageWithVersion = {
203
219
  version: parsedMessage.data.version,
@@ -209,11 +225,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
209
225
  message,
210
226
  payload: messageWithVersion
211
227
  });
212
- throw parsedPayload.error instanceof zod.ZodError ? zodValidationError.fromZodError(parsedPayload.error) : parsedPayload.error;
228
+ return {
229
+ success: false,
230
+ reason: zodValidationError.fromZodError(parsedPayload.error).toString()
231
+ };
213
232
  }
214
233
  return {
215
- type: parsedMessage.data.type,
216
- payload: parsedPayload.data
234
+ success: true,
235
+ data: {
236
+ type: parsedMessage.data.type,
237
+ payload: parsedPayload.data
238
+ }
217
239
  };
218
240
  }
219
241
  registerHandlers(emitter, logger) {
@@ -261,16 +283,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
261
283
  };
262
284
  _schema2 = new WeakMap();
263
285
  _handlers = new WeakMap();
286
+ _logger = new WeakMap();
264
287
  __name(_ZodSocketMessageHandler, "ZodSocketMessageHandler");
265
288
  var ZodSocketMessageHandler = _ZodSocketMessageHandler;
266
289
 
267
290
  // src/v3/zodNamespace.ts
268
- var _logger, _handler;
291
+ var _logger2, _handler;
269
292
  var _ZodNamespace = class _ZodNamespace {
270
293
  constructor(opts) {
271
- __privateAdd(this, _logger, void 0);
294
+ __privateAdd(this, _logger2, void 0);
272
295
  __privateAdd(this, _handler, void 0);
273
- __privateSet(this, _logger, opts.logger ?? new SimpleStructuredLogger(opts.name));
296
+ __privateSet(this, _logger2, opts.logger ?? new SimpleStructuredLogger(opts.name));
274
297
  __privateSet(this, _handler, new ZodSocketMessageHandler({
275
298
  schema: opts.clientMessages,
276
299
  handlers: opts.handlers
@@ -292,7 +315,7 @@ var _ZodNamespace = class _ZodNamespace {
292
315
  });
293
316
  if (opts.preAuth) {
294
317
  this.namespace.use(async (socket, next) => {
295
- const logger = __privateGet(this, _logger).child({
318
+ const logger = __privateGet(this, _logger2).child({
296
319
  socketId: socket.id,
297
320
  socketStage: "preAuth"
298
321
  });
@@ -303,7 +326,7 @@ var _ZodNamespace = class _ZodNamespace {
303
326
  }
304
327
  if (opts.authToken) {
305
328
  this.namespace.use((socket, next) => {
306
- const logger = __privateGet(this, _logger).child({
329
+ const logger = __privateGet(this, _logger2).child({
307
330
  socketId: socket.id,
308
331
  socketStage: "auth"
309
332
  });
@@ -322,7 +345,7 @@ var _ZodNamespace = class _ZodNamespace {
322
345
  }
323
346
  if (opts.postAuth) {
324
347
  this.namespace.use(async (socket, next) => {
325
- const logger = __privateGet(this, _logger).child({
348
+ const logger = __privateGet(this, _logger2).child({
326
349
  socketId: socket.id,
327
350
  socketStage: "auth"
328
351
  });
@@ -332,7 +355,7 @@ var _ZodNamespace = class _ZodNamespace {
332
355
  });
333
356
  }
334
357
  this.namespace.on("connection", async (socket) => {
335
- const logger = __privateGet(this, _logger).child({
358
+ const logger = __privateGet(this, _logger2).child({
336
359
  socketId: socket.id,
337
360
  socketStage: "connection"
338
361
  });
@@ -364,7 +387,7 @@ var _ZodNamespace = class _ZodNamespace {
364
387
  return this.namespace.fetchSockets();
365
388
  }
366
389
  };
367
- _logger = new WeakMap();
390
+ _logger2 = new WeakMap();
368
391
  _handler = new WeakMap();
369
392
  __name(_ZodNamespace, "ZodNamespace");
370
393
  var ZodNamespace = _ZodNamespace;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/v3/zodMessageHandler.ts","../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts","../../src/v3/zodNamespace.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageSender","options","schema","sender","send","parsedPayload","safeParse","success","console","forwardMessage","parsedMessage","JSON","stringify","data","io","ZodError","LogLevel","SimpleStructuredLogger","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","args","warn","loggerFunction","structuredLog","length","timestamp","Date","fromZodError","messageSchema","_schema","ZodSocketMessageHandler","handlers","handleMessage","parseMessage","handler","String","ack","messageWithVersion","registerHandlers","emitter","logger","eventName","Object","keys","on","callback","hasCallback","stack","ZodNamespace","opts","clientMessages","namespace","of","serverMessages","Promise","resolve","reject","emit","err","preAuth","use","socket","next","socketId","id","socketStage","authToken","auth","handshake","disconnect","token","postAuth","reason","description","onDisconnect","onError","onConnection","fetchSockets"],"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","import type { Socket } from \"socket.io-client\";\nimport { io } from \"socket.io-client\";\nimport { ZodError, z } from \"zod\";\nimport { EventEmitterLike, ZodMessageValueSchema } from \"./zodMessageHandler\";\nimport { LogLevel, SimpleStructuredLogger, StructuredLogger } from \"./utils/structuredLogger\";\nimport { fromZodError } from \"zod-validation-error\";\n\nexport interface ZodSocketMessageCatalogSchema {\n [key: string]:\n | {\n message: ZodMessageValueSchema<any>;\n }\n | {\n message: ZodMessageValueSchema<any>;\n callback?: ZodMessageValueSchema<any>;\n };\n}\n\nexport type ZodMessageCatalogToSocketIoEvents<TCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TCatalog]: SocketMessageHasCallback<TCatalog, K> extends true\n ? (\n message: z.infer<GetSocketMessageSchema<TCatalog, K>>,\n callback: (ack: z.infer<GetSocketCallbackSchema<TCatalog, K>>) => void\n ) => void\n : (message: z.infer<GetSocketMessageSchema<TCatalog, K>>) => void;\n};\n\nexport type GetSocketMessageSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = TRPCCatalog[TMessageType][\"message\"];\n\nexport type InferSocketMessageSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = z.infer<GetSocketMessageSchema<TRPCCatalog, TMessageType>>;\n\nexport type GetSocketCallbackSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = TRPCCatalog[TMessageType] extends { callback: any }\n ? TRPCCatalog[TMessageType][\"callback\"]\n : never;\n\nexport type InferSocketCallbackSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = z.infer<GetSocketCallbackSchema<TRPCCatalog, TMessageType>>;\n\nexport type SocketMessageHasCallback<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = GetSocketCallbackSchema<TRPCCatalog, TMessageType> extends never ? false : true;\n\nexport type ZodSocketMessageHandlers<TCatalogSchema extends ZodSocketMessageCatalogSchema> =\n Partial<{\n [K in keyof TCatalogSchema]: (\n payload: z.infer<GetSocketMessageSchema<TCatalogSchema, K>>\n ) => Promise<\n SocketMessageHasCallback<TCatalogSchema, K> extends true\n ? z.input<GetSocketCallbackSchema<TCatalogSchema, K>>\n : void\n >;\n }>;\n\nexport type ZodSocketMessageHandlerOptions<TMessageCatalog extends ZodSocketMessageCatalogSchema> =\n {\n schema: TMessageCatalog;\n handlers?: ZodSocketMessageHandlers<TMessageCatalog>;\n };\n\ntype MessageFromSocketSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>;\n};\n\nexport type MessagesFromSocketCatalog<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSocketSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nconst messageSchema = z.object({\n version: z.string(),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport class ZodSocketMessageHandler<TRPCCatalog extends ZodSocketMessageCatalogSchema> {\n #schema: TRPCCatalog;\n #handlers: ZodSocketMessageHandlers<TRPCCatalog> | undefined;\n\n constructor(options: ZodSocketMessageHandlerOptions<TRPCCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\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): MessagesFromSocketCatalog<TRPCCatalog> {\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 messageWithVersion = {\n version: parsedMessage.data.version,\n ...(typeof parsedMessage.data.payload === \"object\" ? parsedMessage.data.payload : {}),\n };\n\n const parsedPayload = schema.safeParse(messageWithVersion);\n\n if (!parsedPayload.success) {\n console.error(\"Failed to parse message payload\", {\n message,\n payload: messageWithVersion,\n });\n\n throw parsedPayload.error instanceof ZodError\n ? fromZodError(parsedPayload.error)\n : 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.#handlers)) {\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 try {\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 } catch (error) {\n log.error(\"Error while handling message\", {\n error:\n error instanceof Error\n ? {\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n return;\n }\n\n if (callback && typeof callback === \"function\") {\n callback(ack);\n }\n });\n }\n }\n}\n\nexport type ZodSocketMessageSenderOptions<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n schema: TMessageCatalog;\n socket: ZodSocket<any, TMessageCatalog>;\n};\n\nexport type GetSocketMessagesWithCallback<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: SocketMessageHasCallback<TMessageCatalog, K> extends true\n ? K\n : never;\n}[keyof TMessageCatalog];\n\nexport type GetSocketMessagesWithoutCallback<\n TMessageCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n [K in keyof TMessageCatalog]: SocketMessageHasCallback<TMessageCatalog, K> extends true\n ? never\n : K;\n}[keyof TMessageCatalog];\n\nexport class ZodSocketMessageSender<TMessageCatalog extends ZodSocketMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #socket: ZodSocket<any, TMessageCatalog>;\n\n constructor(options: ZodSocketMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#socket = options.socket;\n }\n\n public send<K extends GetSocketMessagesWithoutCallback<TMessageCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>\n ): void {\n const schema = this.#schema[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 Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n // @ts-expect-error\n this.#socket.emit(type, { payload, version: \"v1\" });\n\n return;\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TMessageCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TMessageCatalog, K>>> {\n const schema = this.#schema[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 Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n // @ts-expect-error\n const callbackResult = await this.#socket.emitWithAck(type, { payload, version: \"v1\" });\n\n return callbackResult;\n }\n}\n\nexport type ZodSocket<\n TListenEvents extends ZodSocketMessageCatalogSchema,\n TEmitEvents extends ZodSocketMessageCatalogSchema,\n> = Socket<\n ZodMessageCatalogToSocketIoEvents<TListenEvents>,\n ZodMessageCatalogToSocketIoEvents<TEmitEvents>\n>;\n\ninterface ZodSocketConnectionOptions<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n> {\n host: string;\n port?: number;\n secure?: boolean;\n namespace: string;\n clientMessages: TClientMessages;\n serverMessages: TServerMessages;\n extraHeaders?: {\n [header: string]: string;\n };\n handlers?: ZodSocketMessageHandlers<TServerMessages>;\n authToken?: string;\n onConnection?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n handler: ZodSocketMessageHandler<TServerMessages>,\n sender: ZodSocketMessageSender<TClientMessages>,\n logger: StructuredLogger\n ) => Promise<void>;\n onDisconnect?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n reason: Socket.DisconnectReason,\n description: any,\n logger: StructuredLogger\n ) => Promise<void>;\n onError?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n err: Error,\n logger: StructuredLogger\n ) => Promise<void>;\n}\n\nexport class ZodSocketConnection<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n> {\n #sender: ZodSocketMessageSender<TClientMessages>;\n socket: ZodSocket<TServerMessages, TClientMessages>;\n\n #handler: ZodSocketMessageHandler<TServerMessages>;\n #logger: StructuredLogger;\n\n constructor(opts: ZodSocketConnectionOptions<TClientMessages, TServerMessages>) {\n const uri = `${opts.secure ? \"wss\" : \"ws\"}://${opts.host}:${\n opts.port ?? (opts.secure ? \"443\" : \"80\")\n }/${opts.namespace}`;\n\n const logger = new SimpleStructuredLogger(opts.namespace, LogLevel.info);\n logger.log(\"new zod socket\", { uri });\n\n this.socket = io(uri, {\n transports: [\"websocket\"],\n auth: {\n token: opts.authToken,\n },\n extraHeaders: opts.extraHeaders,\n reconnectionDelay: 500,\n reconnectionDelayMax: 1000,\n });\n\n this.#logger = logger.child({\n socketId: this.socket.id,\n });\n\n this.#handler = new ZodSocketMessageHandler({\n schema: opts.serverMessages,\n handlers: opts.handlers,\n });\n this.#handler.registerHandlers(this.socket, this.#logger);\n\n this.#sender = new ZodSocketMessageSender({\n schema: opts.clientMessages,\n socket: this.socket,\n });\n\n this.socket.on(\"connect_error\", async (error) => {\n this.#logger.error(`connect_error: ${error}`);\n\n if (opts.onError) {\n await opts.onError(this.socket, error, this.#logger);\n }\n });\n\n this.socket.on(\"connect\", async () => {\n this.#logger.info(\"connect\");\n\n if (opts.onConnection) {\n await opts.onConnection(this.socket, this.#handler, this.#sender, this.#logger);\n }\n });\n\n this.socket.on(\"disconnect\", async (reason, description) => {\n this.#logger.info(\"disconnect\", { reason, description });\n\n if (opts.onDisconnect) {\n await opts.onDisconnect(this.socket, reason, description, this.#logger);\n }\n });\n }\n\n close() {\n this.socket.close();\n }\n\n connect() {\n this.socket.connect();\n }\n\n get send() {\n return this.#sender.send.bind(this.#sender);\n }\n\n get sendWithAck() {\n return this.#sender.sendWithAck.bind(this.#sender);\n }\n}\n\nfunction createLogger(prefix: string) {\n return (...args: any[]) => console.log(prefix, ...args);\n}\n","type StructuredArgs = (Record<string, unknown> | undefined)[];\n\nexport interface StructuredLogger {\n log: (message: string, ...args: StructuredArgs) => any;\n error: (message: string, ...args: StructuredArgs) => any;\n warn: (message: string, ...args: StructuredArgs) => any;\n info: (message: string, ...args: StructuredArgs) => any;\n debug: (message: string, ...args: StructuredArgs) => any;\n child: (fields: Record<string, unknown>) => StructuredLogger;\n}\n\nexport enum LogLevel {\n \"log\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n}\n\nexport class SimpleStructuredLogger implements StructuredLogger {\n constructor(\n private name: string,\n private level: LogLevel = [\"1\", \"true\"].includes(process.env.DEBUG ?? \"\")\n ? LogLevel.debug\n : LogLevel.info,\n private fields?: Record<string, unknown>\n ) {}\n\n child(fields: Record<string, unknown>, level?: LogLevel) {\n return new SimpleStructuredLogger(this.name, level, { ...this.fields, ...fields });\n }\n\n log(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.log) return;\n\n this.#structuredLog(console.log, message, \"log\", ...args);\n }\n\n error(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.error) return;\n\n this.#structuredLog(console.error, message, \"error\", ...args);\n }\n\n warn(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.warn) return;\n\n this.#structuredLog(console.warn, message, \"warn\", ...args);\n }\n\n info(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.info) return;\n\n this.#structuredLog(console.info, message, \"info\", ...args);\n }\n\n debug(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.debug) return;\n\n this.#structuredLog(console.debug, message, \"debug\", ...args);\n }\n\n #structuredLog(\n loggerFunction: (message: string, ...args: any[]) => void,\n message: string,\n level: string,\n ...args: StructuredArgs\n ) {\n const structuredLog = {\n ...(args.length === 1 ? args[0] : args),\n ...this.fields,\n timestamp: new Date(),\n name: this.name,\n message,\n level,\n };\n\n loggerFunction(JSON.stringify(structuredLog));\n }\n}\n","import type { DisconnectReason, Namespace, Server, Socket } from \"socket.io\";\nimport { ZodMessageSender } from \"./zodMessageHandler\";\nimport {\n ZodMessageCatalogToSocketIoEvents,\n ZodSocketMessageCatalogSchema,\n ZodSocketMessageHandler,\n ZodSocketMessageHandlers,\n} from \"./zodSocket\";\nimport type { DefaultEventsMap, EventsMap } from \"socket.io/dist/typed-events\";\nimport { z } from \"zod\";\nimport { SimpleStructuredLogger, StructuredLogger } from \"./utils/structuredLogger\";\n\ninterface ExtendedError extends Error {\n data?: any;\n}\n\nexport type ZodNamespaceSocket<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n TSocketData extends z.ZodObject<any, any, any> = any,\n> = Socket<\n ZodMessageCatalogToSocketIoEvents<TClientMessages>,\n ZodMessageCatalogToSocketIoEvents<TServerMessages>,\n TServerSideEvents,\n z.infer<TSocketData>\n>;\n\ninterface ZodNamespaceOptions<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n TSocketData extends z.ZodObject<any, any, any> = any,\n> {\n io: Server;\n name: string;\n clientMessages: TClientMessages;\n serverMessages: TServerMessages;\n socketData?: TSocketData;\n handlers?: ZodSocketMessageHandlers<TClientMessages>;\n authToken?: string;\n logger?: StructuredLogger;\n preAuth?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n next: (err?: ExtendedError) => void,\n logger: StructuredLogger\n ) => Promise<void>;\n postAuth?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n next: (err?: ExtendedError) => void,\n logger: StructuredLogger\n ) => Promise<void>;\n onConnection?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n handler: ZodSocketMessageHandler<TClientMessages>,\n sender: ZodMessageSender<TServerMessages>,\n logger: StructuredLogger\n ) => Promise<void>;\n onDisconnect?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n reason: DisconnectReason,\n description: any,\n logger: StructuredLogger\n ) => Promise<void>;\n onError?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n err: Error,\n logger: StructuredLogger\n ) => Promise<void>;\n}\n\nexport class ZodNamespace<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TSocketData extends z.ZodObject<any, any, any> = any,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n> {\n #logger: StructuredLogger;\n #handler: ZodSocketMessageHandler<TClientMessages>;\n sender: ZodMessageSender<TServerMessages>;\n\n io: Server;\n namespace: Namespace<\n ZodMessageCatalogToSocketIoEvents<TClientMessages>,\n ZodMessageCatalogToSocketIoEvents<TServerMessages>,\n TServerSideEvents,\n z.infer<TSocketData>\n >;\n\n constructor(\n opts: ZodNamespaceOptions<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>\n ) {\n this.#logger = opts.logger ?? new SimpleStructuredLogger(opts.name);\n\n this.#handler = new ZodSocketMessageHandler({\n schema: opts.clientMessages,\n handlers: opts.handlers,\n });\n\n this.io = opts.io;\n\n this.namespace = this.io.of(opts.name);\n\n // FIXME: There's a bug here, this sender should not accept Socket schemas with callbacks\n this.sender = new ZodMessageSender({\n schema: opts.serverMessages,\n sender: async (message) => {\n return new Promise((resolve, reject) => {\n try {\n // @ts-expect-error\n this.namespace.emit(message.type, message.payload);\n resolve();\n } catch (err) {\n reject(err);\n }\n });\n },\n });\n\n if (opts.preAuth) {\n this.namespace.use(async (socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"preAuth\" });\n\n if (typeof opts.preAuth === \"function\") {\n await opts.preAuth(socket, next, logger);\n }\n });\n }\n\n if (opts.authToken) {\n this.namespace.use((socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"auth\" });\n\n const { auth } = socket.handshake;\n\n if (!(\"token\" in auth)) {\n logger.error(\"no token\");\n return socket.disconnect(true);\n }\n\n if (auth.token !== opts.authToken) {\n logger.error(\"invalid token\");\n return socket.disconnect(true);\n }\n\n logger.info(\"success\");\n\n next();\n });\n }\n\n if (opts.postAuth) {\n this.namespace.use(async (socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"auth\" });\n\n if (typeof opts.postAuth === \"function\") {\n await opts.postAuth(socket, next, logger);\n }\n });\n }\n\n this.namespace.on(\"connection\", async (socket) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"connection\" });\n logger.info(\"connected\");\n\n this.#handler.registerHandlers(socket, logger);\n\n socket.on(\"disconnect\", async (reason, description) => {\n logger.info(\"disconnect\", { reason, description });\n\n if (opts.onDisconnect) {\n await opts.onDisconnect(socket, reason, description, logger);\n }\n });\n\n socket.on(\"error\", async (error) => {\n logger.error(\"error\", { error });\n\n if (opts.onError) {\n await opts.onError(socket, error, logger);\n }\n });\n\n if (opts.onConnection) {\n await opts.onConnection(socket, this.#handler, this.sender, logger);\n }\n });\n }\n\n fetchSockets() {\n return this.namespace.fetchSockets();\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/v3/zodMessageHandler.ts","../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts","../../src/v3/zodNamespace.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageSender","options","schema","sender","send","parsedPayload","safeParse","success","console","forwardMessage","parsedMessage","JSON","stringify","data","io","LogLevel","SimpleStructuredLogger","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","args","warn","loggerFunction","structuredLog","length","timestamp","Date","fromZodError","messageSchema","_schema","ZodSocketMessageHandler","handlers","logger","handleMessage","parseResult","parseMessage","rawMessage","reason","handler","String","ack","toString","messageWithVersion","registerHandlers","emitter","eventName","Object","keys","on","callback","hasCallback","stack","_logger","ZodNamespace","opts","clientMessages","namespace","of","serverMessages","Promise","resolve","reject","emit","err","preAuth","use","socket","next","socketId","id","socketStage","authToken","auth","handshake","disconnect","token","postAuth","description","onDisconnect","onError","onConnection","fetchSockets"],"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","import type { ManagerOptions, Socket, SocketOptions } from \"socket.io-client\";\nimport { io } from \"socket.io-client\";\nimport { ZodError, z } from \"zod\";\nimport { EventEmitterLike, ZodMessageValueSchema } from \"./zodMessageHandler\";\nimport { LogLevel, SimpleStructuredLogger, StructuredLogger } from \"./utils/structuredLogger\";\nimport { fromZodError } from \"zod-validation-error\";\n\nexport interface ZodSocketMessageCatalogSchema {\n [key: string]:\n | {\n message: ZodMessageValueSchema<any>;\n }\n | {\n message: ZodMessageValueSchema<any>;\n callback?: ZodMessageValueSchema<any>;\n };\n}\n\nexport type ZodMessageCatalogToSocketIoEvents<TCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TCatalog]: SocketMessageHasCallback<TCatalog, K> extends true\n ? (\n message: z.infer<GetSocketMessageSchema<TCatalog, K>>,\n callback: (ack: z.infer<GetSocketCallbackSchema<TCatalog, K>>) => void\n ) => void\n : (message: z.infer<GetSocketMessageSchema<TCatalog, K>>) => void;\n};\n\nexport type GetSocketMessageSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = TRPCCatalog[TMessageType][\"message\"];\n\nexport type InferSocketMessageSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = z.infer<GetSocketMessageSchema<TRPCCatalog, TMessageType>>;\n\nexport type GetSocketCallbackSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = TRPCCatalog[TMessageType] extends { callback: any }\n ? TRPCCatalog[TMessageType][\"callback\"]\n : never;\n\nexport type InferSocketCallbackSchema<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = z.infer<GetSocketCallbackSchema<TRPCCatalog, TMessageType>>;\n\nexport type SocketMessageHasCallback<\n TRPCCatalog extends ZodSocketMessageCatalogSchema,\n TMessageType extends keyof TRPCCatalog,\n> = GetSocketCallbackSchema<TRPCCatalog, TMessageType> extends never ? false : true;\n\nexport type ZodSocketMessageHandlers<TCatalogSchema extends ZodSocketMessageCatalogSchema> =\n Partial<{\n [K in keyof TCatalogSchema]: (\n payload: z.infer<GetSocketMessageSchema<TCatalogSchema, K>>\n ) => Promise<\n SocketMessageHasCallback<TCatalogSchema, K> extends true\n ? z.input<GetSocketCallbackSchema<TCatalogSchema, K>>\n : void\n >;\n }>;\n\nexport type ZodSocketMessageHandlerOptions<TMessageCatalog extends ZodSocketMessageCatalogSchema> =\n {\n schema: TMessageCatalog;\n handlers?: ZodSocketMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n };\n\ntype MessageFromSocketSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>;\n};\n\nexport type MessagesFromSocketCatalog<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSocketSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nconst messageSchema = z.object({\n version: z.string(),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport class ZodSocketMessageHandler<TRPCCatalog extends ZodSocketMessageCatalogSchema> {\n #schema: TRPCCatalog;\n #handlers: ZodSocketMessageHandlers<TRPCCatalog> | undefined;\n #logger: StructuredLogger;\n\n constructor(options: ZodSocketMessageHandlerOptions<TRPCCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.handlers;\n this.#logger =\n options.logger ?? new SimpleStructuredLogger(\"socket-message-handler\", LogLevel.info);\n }\n\n public async handleMessage(message: unknown) {\n const parseResult = this.parseMessage(message);\n\n if (!parseResult.success) {\n this.#logger.error(\"Failed to parse message, skipping handler\", {\n rawMessage: message,\n error: parseResult.reason,\n });\n return;\n }\n\n if (!this.#handlers) {\n throw new Error(\"No handlers provided\");\n }\n\n const { type, payload } = parseResult.data;\n\n const handler = this.#handlers[type];\n\n if (!handler) {\n console.error(`No handler for message type: ${String(type)}`);\n return;\n }\n\n const ack = await handler(payload);\n\n return ack;\n }\n\n private parseMessage(message: unknown):\n | {\n success: true;\n data: MessagesFromSocketCatalog<TRPCCatalog>;\n }\n | {\n success: false;\n reason?: string;\n } {\n const parsedMessage = messageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n reason: `Failed to parse message: ${fromZodError(parsedMessage.error).toString()}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type][\"message\"];\n\n if (!schema) {\n return {\n success: false,\n reason: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const messageWithVersion = {\n version: parsedMessage.data.version,\n ...(typeof parsedMessage.data.payload === \"object\" ? parsedMessage.data.payload : {}),\n };\n\n const parsedPayload = schema.safeParse(messageWithVersion);\n\n if (!parsedPayload.success) {\n console.error(\"Failed to parse message payload\", {\n message,\n payload: messageWithVersion,\n });\n\n return {\n success: false,\n reason: fromZodError(parsedPayload.error).toString(),\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.#handlers)) {\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 try {\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 } catch (error) {\n log.error(\"Error while handling message\", {\n error:\n error instanceof Error\n ? {\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n return;\n }\n\n if (callback && typeof callback === \"function\") {\n callback(ack);\n }\n });\n }\n }\n}\n\nexport type ZodSocketMessageSenderOptions<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n schema: TMessageCatalog;\n socket: ZodSocket<any, TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type GetSocketMessagesWithCallback<TMessageCatalog extends ZodSocketMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: SocketMessageHasCallback<TMessageCatalog, K> extends true\n ? K\n : never;\n}[keyof TMessageCatalog];\n\nexport type GetSocketMessagesWithoutCallback<\n TMessageCatalog extends ZodSocketMessageCatalogSchema,\n> = {\n [K in keyof TMessageCatalog]: SocketMessageHasCallback<TMessageCatalog, K> extends true\n ? never\n : K;\n}[keyof TMessageCatalog];\n\nexport class ZodSocketMessageSender<TMessageCatalog extends ZodSocketMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #socket: ZodSocket<any, TMessageCatalog>;\n #logger: StructuredLogger;\n\n constructor(options: ZodSocketMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#socket = options.socket;\n this.#logger = options.logger ?? new SimpleStructuredLogger(\"zod-socket-sender\", LogLevel.info);\n }\n\n public send<K extends GetSocketMessagesWithoutCallback<TMessageCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>\n ): void {\n const schema = this.#schema[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 this.#logger.error(\"Failed to parse message payload, will not send\", {\n error: parsedPayload.error,\n });\n return;\n }\n\n // @ts-expect-error\n this.#socket.emit(type, { payload, version: \"v1\" });\n\n return;\n }\n\n public async sendWithAck<K extends GetSocketMessagesWithCallback<TMessageCatalog>>(\n type: K,\n payload: z.input<GetSocketMessageSchema<TMessageCatalog, K>>\n ): Promise<z.infer<GetSocketCallbackSchema<TMessageCatalog, K>>> {\n const schema = this.#schema[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 Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n // @ts-expect-error\n const callbackResult = await this.#socket.emitWithAck(type, { payload, version: \"v1\" });\n\n return callbackResult;\n }\n}\n\nexport type ZodSocket<\n TListenEvents extends ZodSocketMessageCatalogSchema,\n TEmitEvents extends ZodSocketMessageCatalogSchema,\n> = Omit<\n Socket<\n ZodMessageCatalogToSocketIoEvents<TListenEvents>,\n ZodMessageCatalogToSocketIoEvents<TEmitEvents>\n >,\n \"timeout\"\n> & {\n timeout: (\n timeout: number\n ) => Socket<\n ZodMessageCatalogToSocketIoEvents<TListenEvents>,\n ZodMessageCatalogToSocketIoEvents<TEmitEvents>\n >;\n};\n\ninterface ZodSocketConnectionOptions<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n> {\n host: string;\n port?: number;\n secure?: boolean;\n namespace: string;\n clientMessages: TClientMessages;\n serverMessages: TServerMessages;\n extraHeaders?: {\n [header: string]: string;\n };\n handlers?: ZodSocketMessageHandlers<TServerMessages>;\n authToken?: string;\n ioOptions?: Partial<ManagerOptions & SocketOptions>;\n onConnection?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n handler: ZodSocketMessageHandler<TServerMessages>,\n sender: ZodSocketMessageSender<TClientMessages>,\n logger: StructuredLogger\n ) => Promise<void>;\n onDisconnect?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n reason: Socket.DisconnectReason,\n description: any,\n logger: StructuredLogger\n ) => Promise<void>;\n onError?: (\n socket: ZodSocket<TServerMessages, TClientMessages>,\n err: Error,\n logger: StructuredLogger\n ) => Promise<void>;\n}\n\nexport class ZodSocketConnection<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n> {\n #sender: ZodSocketMessageSender<TClientMessages>;\n socket: ZodSocket<TServerMessages, TClientMessages>;\n\n #handler: ZodSocketMessageHandler<TServerMessages>;\n #logger: StructuredLogger;\n\n constructor(opts: ZodSocketConnectionOptions<TClientMessages, TServerMessages>) {\n const uri = `${opts.secure ? \"wss\" : \"ws\"}://${opts.host}:${\n opts.port ?? (opts.secure ? \"443\" : \"80\")\n }/${opts.namespace}`;\n\n const logger = new SimpleStructuredLogger(opts.namespace, LogLevel.info);\n logger.log(\"new zod socket\", { uri });\n\n this.socket = io(uri, {\n transports: [\"websocket\"],\n auth: {\n token: opts.authToken,\n },\n extraHeaders: opts.extraHeaders,\n reconnectionDelay: 500,\n reconnectionDelayMax: 1000,\n ...opts.ioOptions,\n });\n\n this.#logger = logger.child({\n socketId: this.socket.id,\n });\n\n this.#handler = new ZodSocketMessageHandler({\n schema: opts.serverMessages,\n handlers: opts.handlers,\n });\n this.#handler.registerHandlers(this.socket, this.#logger);\n\n this.#sender = new ZodSocketMessageSender({\n schema: opts.clientMessages,\n socket: this.socket,\n logger: this.#logger,\n });\n\n this.socket.on(\"connect_error\", async (error) => {\n this.#logger.error(`connect_error: ${error}`);\n\n if (opts.onError) {\n await opts.onError(this.socket, error, this.#logger);\n }\n });\n\n this.socket.on(\"connect\", async () => {\n this.#logger.info(\"connect\");\n\n if (opts.onConnection) {\n await opts.onConnection(this.socket, this.#handler, this.#sender, this.#logger);\n }\n });\n\n this.socket.on(\"disconnect\", async (reason, description) => {\n this.#logger.info(\"disconnect\", { reason, description });\n\n if (opts.onDisconnect) {\n await opts.onDisconnect(this.socket, reason, description, this.#logger);\n }\n });\n }\n\n close() {\n this.socket.close();\n }\n\n connect() {\n this.socket.connect();\n }\n\n get send() {\n return this.#sender.send.bind(this.#sender);\n }\n\n get sendWithAck() {\n return this.#sender.sendWithAck.bind(this.#sender);\n }\n}\n","type StructuredArgs = (Record<string, unknown> | undefined)[];\n\nexport interface StructuredLogger {\n log: (message: string, ...args: StructuredArgs) => any;\n error: (message: string, ...args: StructuredArgs) => any;\n warn: (message: string, ...args: StructuredArgs) => any;\n info: (message: string, ...args: StructuredArgs) => any;\n debug: (message: string, ...args: StructuredArgs) => any;\n child: (fields: Record<string, unknown>) => StructuredLogger;\n}\n\nexport enum LogLevel {\n \"log\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n}\n\nexport class SimpleStructuredLogger implements StructuredLogger {\n constructor(\n private name: string,\n private level: LogLevel = [\"1\", \"true\"].includes(process.env.DEBUG ?? \"\")\n ? LogLevel.debug\n : LogLevel.info,\n private fields?: Record<string, unknown>\n ) {}\n\n child(fields: Record<string, unknown>, level?: LogLevel) {\n return new SimpleStructuredLogger(this.name, level, { ...this.fields, ...fields });\n }\n\n log(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.log) return;\n\n this.#structuredLog(console.log, message, \"log\", ...args);\n }\n\n error(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.error) return;\n\n this.#structuredLog(console.error, message, \"error\", ...args);\n }\n\n warn(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.warn) return;\n\n this.#structuredLog(console.warn, message, \"warn\", ...args);\n }\n\n info(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.info) return;\n\n this.#structuredLog(console.info, message, \"info\", ...args);\n }\n\n debug(message: string, ...args: StructuredArgs) {\n if (this.level < LogLevel.debug) return;\n\n this.#structuredLog(console.debug, message, \"debug\", ...args);\n }\n\n #structuredLog(\n loggerFunction: (message: string, ...args: any[]) => void,\n message: string,\n level: string,\n ...args: StructuredArgs\n ) {\n const structuredLog = {\n ...(args.length === 1 ? args[0] : args),\n ...this.fields,\n timestamp: new Date(),\n name: this.name,\n message,\n level,\n };\n\n loggerFunction(JSON.stringify(structuredLog));\n }\n}\n","import type { DisconnectReason, Namespace, Server, Socket } from \"socket.io\";\nimport { ZodMessageSender } from \"./zodMessageHandler\";\nimport {\n ZodMessageCatalogToSocketIoEvents,\n ZodSocketMessageCatalogSchema,\n ZodSocketMessageHandler,\n ZodSocketMessageHandlers,\n} from \"./zodSocket\";\nimport type { DefaultEventsMap, EventsMap } from \"socket.io/dist/typed-events\";\nimport { z } from \"zod\";\nimport { SimpleStructuredLogger, StructuredLogger } from \"./utils/structuredLogger\";\n\ninterface ExtendedError extends Error {\n data?: any;\n}\n\nexport type ZodNamespaceSocket<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n TSocketData extends z.ZodObject<any, any, any> = any,\n> = Socket<\n ZodMessageCatalogToSocketIoEvents<TClientMessages>,\n ZodMessageCatalogToSocketIoEvents<TServerMessages>,\n TServerSideEvents,\n z.infer<TSocketData>\n>;\n\ninterface ZodNamespaceOptions<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n TSocketData extends z.ZodObject<any, any, any> = any,\n> {\n io: Server;\n name: string;\n clientMessages: TClientMessages;\n serverMessages: TServerMessages;\n socketData?: TSocketData;\n handlers?: ZodSocketMessageHandlers<TClientMessages>;\n authToken?: string;\n logger?: StructuredLogger;\n preAuth?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n next: (err?: ExtendedError) => void,\n logger: StructuredLogger\n ) => Promise<void>;\n postAuth?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n next: (err?: ExtendedError) => void,\n logger: StructuredLogger\n ) => Promise<void>;\n onConnection?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n handler: ZodSocketMessageHandler<TClientMessages>,\n sender: ZodMessageSender<TServerMessages>,\n logger: StructuredLogger\n ) => Promise<void>;\n onDisconnect?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n reason: DisconnectReason,\n description: any,\n logger: StructuredLogger\n ) => Promise<void>;\n onError?: (\n socket: ZodNamespaceSocket<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>,\n err: Error,\n logger: StructuredLogger\n ) => Promise<void>;\n}\n\nexport class ZodNamespace<\n TClientMessages extends ZodSocketMessageCatalogSchema,\n TServerMessages extends ZodSocketMessageCatalogSchema,\n TSocketData extends z.ZodObject<any, any, any> = any,\n TServerSideEvents extends EventsMap = DefaultEventsMap,\n> {\n #logger: StructuredLogger;\n #handler: ZodSocketMessageHandler<TClientMessages>;\n sender: ZodMessageSender<TServerMessages>;\n\n io: Server;\n namespace: Namespace<\n ZodMessageCatalogToSocketIoEvents<TClientMessages>,\n ZodMessageCatalogToSocketIoEvents<TServerMessages>,\n TServerSideEvents,\n z.infer<TSocketData>\n >;\n\n constructor(\n opts: ZodNamespaceOptions<TClientMessages, TServerMessages, TServerSideEvents, TSocketData>\n ) {\n this.#logger = opts.logger ?? new SimpleStructuredLogger(opts.name);\n\n this.#handler = new ZodSocketMessageHandler({\n schema: opts.clientMessages,\n handlers: opts.handlers,\n });\n\n this.io = opts.io;\n\n this.namespace = this.io.of(opts.name);\n\n // FIXME: There's a bug here, this sender should not accept Socket schemas with callbacks\n this.sender = new ZodMessageSender({\n schema: opts.serverMessages,\n sender: async (message) => {\n return new Promise((resolve, reject) => {\n try {\n // @ts-expect-error\n this.namespace.emit(message.type, message.payload);\n resolve();\n } catch (err) {\n reject(err);\n }\n });\n },\n });\n\n if (opts.preAuth) {\n this.namespace.use(async (socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"preAuth\" });\n\n if (typeof opts.preAuth === \"function\") {\n await opts.preAuth(socket, next, logger);\n }\n });\n }\n\n if (opts.authToken) {\n this.namespace.use((socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"auth\" });\n\n const { auth } = socket.handshake;\n\n if (!(\"token\" in auth)) {\n logger.error(\"no token\");\n return socket.disconnect(true);\n }\n\n if (auth.token !== opts.authToken) {\n logger.error(\"invalid token\");\n return socket.disconnect(true);\n }\n\n logger.info(\"success\");\n\n next();\n });\n }\n\n if (opts.postAuth) {\n this.namespace.use(async (socket, next) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"auth\" });\n\n if (typeof opts.postAuth === \"function\") {\n await opts.postAuth(socket, next, logger);\n }\n });\n }\n\n this.namespace.on(\"connection\", async (socket) => {\n const logger = this.#logger.child({ socketId: socket.id, socketStage: \"connection\" });\n logger.info(\"connected\");\n\n this.#handler.registerHandlers(socket, logger);\n\n socket.on(\"disconnect\", async (reason, description) => {\n logger.info(\"disconnect\", { reason, description });\n\n if (opts.onDisconnect) {\n await opts.onDisconnect(socket, reason, description, logger);\n }\n });\n\n socket.on(\"error\", async (error) => {\n logger.error(\"error\", { error });\n\n if (opts.onError) {\n await opts.onError(socket, error, logger);\n }\n });\n\n if (opts.onConnection) {\n await opts.onConnection(socket, this.#handler, this.sender, logger);\n }\n });\n }\n\n fetchSockets() {\n return this.namespace.fetchSockets();\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { z, ZodError } from 'zod';
1
+ import { z } from 'zod';
2
2
  import 'socket.io-client';
3
3
  import { fromZodError } from 'zod-validation-error';
4
4
 
@@ -167,35 +167,51 @@ var messageSchema = z.object({
167
167
  type: z.string(),
168
168
  payload: z.unknown()
169
169
  });
170
- var _schema2, _handlers;
170
+ var _schema2, _handlers, _logger;
171
171
  var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
172
172
  constructor(options) {
173
173
  __privateAdd(this, _schema2, void 0);
174
174
  __privateAdd(this, _handlers, void 0);
175
+ __privateAdd(this, _logger, void 0);
175
176
  __privateSet(this, _schema2, options.schema);
176
177
  __privateSet(this, _handlers, options.handlers);
178
+ __privateSet(this, _logger, options.logger ?? new SimpleStructuredLogger("socket-message-handler", LogLevel.info));
177
179
  }
178
180
  async handleMessage(message) {
179
- const parsedMessage = this.parseMessage(message);
181
+ const parseResult = this.parseMessage(message);
182
+ if (!parseResult.success) {
183
+ __privateGet(this, _logger).error("Failed to parse message, skipping handler", {
184
+ rawMessage: message,
185
+ error: parseResult.reason
186
+ });
187
+ return;
188
+ }
180
189
  if (!__privateGet(this, _handlers)) {
181
190
  throw new Error("No handlers provided");
182
191
  }
183
- const handler = __privateGet(this, _handlers)[parsedMessage.type];
192
+ const { type, payload } = parseResult.data;
193
+ const handler = __privateGet(this, _handlers)[type];
184
194
  if (!handler) {
185
- console.error(`No handler for message type: ${String(parsedMessage.type)}`);
195
+ console.error(`No handler for message type: ${String(type)}`);
186
196
  return;
187
197
  }
188
- const ack = await handler(parsedMessage.payload);
198
+ const ack = await handler(payload);
189
199
  return ack;
190
200
  }
191
201
  parseMessage(message) {
192
202
  const parsedMessage = messageSchema.safeParse(message);
193
203
  if (!parsedMessage.success) {
194
- throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);
204
+ return {
205
+ success: false,
206
+ reason: `Failed to parse message: ${fromZodError(parsedMessage.error).toString()}`
207
+ };
195
208
  }
196
209
  const schema = __privateGet(this, _schema2)[parsedMessage.data.type]["message"];
197
210
  if (!schema) {
198
- throw new Error(`Unknown message type: ${parsedMessage.data.type}`);
211
+ return {
212
+ success: false,
213
+ reason: `Unknown message type: ${parsedMessage.data.type}`
214
+ };
199
215
  }
200
216
  const messageWithVersion = {
201
217
  version: parsedMessage.data.version,
@@ -207,11 +223,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
207
223
  message,
208
224
  payload: messageWithVersion
209
225
  });
210
- throw parsedPayload.error instanceof ZodError ? fromZodError(parsedPayload.error) : parsedPayload.error;
226
+ return {
227
+ success: false,
228
+ reason: fromZodError(parsedPayload.error).toString()
229
+ };
211
230
  }
212
231
  return {
213
- type: parsedMessage.data.type,
214
- payload: parsedPayload.data
232
+ success: true,
233
+ data: {
234
+ type: parsedMessage.data.type,
235
+ payload: parsedPayload.data
236
+ }
215
237
  };
216
238
  }
217
239
  registerHandlers(emitter, logger) {
@@ -259,16 +281,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
259
281
  };
260
282
  _schema2 = new WeakMap();
261
283
  _handlers = new WeakMap();
284
+ _logger = new WeakMap();
262
285
  __name(_ZodSocketMessageHandler, "ZodSocketMessageHandler");
263
286
  var ZodSocketMessageHandler = _ZodSocketMessageHandler;
264
287
 
265
288
  // src/v3/zodNamespace.ts
266
- var _logger, _handler;
289
+ var _logger2, _handler;
267
290
  var _ZodNamespace = class _ZodNamespace {
268
291
  constructor(opts) {
269
- __privateAdd(this, _logger, void 0);
292
+ __privateAdd(this, _logger2, void 0);
270
293
  __privateAdd(this, _handler, void 0);
271
- __privateSet(this, _logger, opts.logger ?? new SimpleStructuredLogger(opts.name));
294
+ __privateSet(this, _logger2, opts.logger ?? new SimpleStructuredLogger(opts.name));
272
295
  __privateSet(this, _handler, new ZodSocketMessageHandler({
273
296
  schema: opts.clientMessages,
274
297
  handlers: opts.handlers
@@ -290,7 +313,7 @@ var _ZodNamespace = class _ZodNamespace {
290
313
  });
291
314
  if (opts.preAuth) {
292
315
  this.namespace.use(async (socket, next) => {
293
- const logger = __privateGet(this, _logger).child({
316
+ const logger = __privateGet(this, _logger2).child({
294
317
  socketId: socket.id,
295
318
  socketStage: "preAuth"
296
319
  });
@@ -301,7 +324,7 @@ var _ZodNamespace = class _ZodNamespace {
301
324
  }
302
325
  if (opts.authToken) {
303
326
  this.namespace.use((socket, next) => {
304
- const logger = __privateGet(this, _logger).child({
327
+ const logger = __privateGet(this, _logger2).child({
305
328
  socketId: socket.id,
306
329
  socketStage: "auth"
307
330
  });
@@ -320,7 +343,7 @@ var _ZodNamespace = class _ZodNamespace {
320
343
  }
321
344
  if (opts.postAuth) {
322
345
  this.namespace.use(async (socket, next) => {
323
- const logger = __privateGet(this, _logger).child({
346
+ const logger = __privateGet(this, _logger2).child({
324
347
  socketId: socket.id,
325
348
  socketStage: "auth"
326
349
  });
@@ -330,7 +353,7 @@ var _ZodNamespace = class _ZodNamespace {
330
353
  });
331
354
  }
332
355
  this.namespace.on("connection", async (socket) => {
333
- const logger = __privateGet(this, _logger).child({
356
+ const logger = __privateGet(this, _logger2).child({
334
357
  socketId: socket.id,
335
358
  socketStage: "connection"
336
359
  });
@@ -362,7 +385,7 @@ var _ZodNamespace = class _ZodNamespace {
362
385
  return this.namespace.fetchSockets();
363
386
  }
364
387
  };
365
- _logger = new WeakMap();
388
+ _logger2 = new WeakMap();
366
389
  _handler = new WeakMap();
367
390
  __name(_ZodNamespace, "ZodNamespace");
368
391
  var ZodNamespace = _ZodNamespace;