@trigger.dev/core 0.0.0-prerelease-20240603154820 → 0.0.0-prerelease-20240723165848
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.
- package/dist/api-Pl9fxB8v.d.mts +13879 -0
- package/dist/api-sNoooMbT.d.ts +13879 -0
- package/dist/{catalog-dRKTgwQ7.d.ts → catalog-H7yFiZ60.d.mts} +52 -52
- package/dist/{catalog-XTlJQaMn.d.mts → catalog-h79CG5Wy.d.ts} +52 -52
- package/dist/{manager-JkbddlcO.d.mts → common-CLW82lkt.d.mts} +280 -16
- package/dist/{manager-JkbddlcO.d.ts → common-CLW82lkt.d.ts} +280 -16
- package/dist/{eventFilterMatches-2kHImluE.d.mts → eventFilter-66NaBAMi.d.mts} +1 -3
- package/dist/{eventFilterMatches-2kHImluE.d.ts → eventFilter-66NaBAMi.d.ts} +1 -3
- package/dist/eventFilterMatches.d.mts +6 -0
- package/dist/eventFilterMatches.d.ts +6 -0
- package/dist/eventFilterMatches.js +165 -0
- package/dist/eventFilterMatches.js.map +1 -0
- package/dist/eventFilterMatches.mjs +163 -0
- package/dist/eventFilterMatches.mjs.map +1 -0
- package/dist/index.d.mts +14 -16716
- package/dist/index.d.ts +14 -16716
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/json-DBPEJQRe.d.mts +16 -0
- package/dist/json-DBPEJQRe.d.ts +16 -0
- package/dist/manager-KvCabW1a.d.mts +18 -0
- package/dist/manager-OBA35PzR.d.ts +18 -0
- package/dist/{messages-6_-q72KG.d.mts → messages-JvHJ83wv.d.mts} +2978 -291
- package/dist/{messages-6_-q72KG.d.ts → messages-JvHJ83wv.d.ts} +2978 -291
- package/dist/replacements.d.mts +22 -0
- package/dist/replacements.d.ts +22 -0
- package/dist/replacements.js +33 -0
- package/dist/replacements.js.map +1 -0
- package/dist/replacements.mjs +28 -0
- package/dist/replacements.mjs.map +1 -0
- package/dist/requestFilter-HNZQEpQb.d.ts +180 -0
- package/dist/requestFilter-b5W2_1oP.d.mts +180 -0
- package/dist/requestFilterMatches.d.mts +13 -0
- package/dist/requestFilterMatches.d.ts +13 -0
- package/dist/requestFilterMatches.js +238 -0
- package/dist/requestFilterMatches.js.map +1 -0
- package/dist/requestFilterMatches.mjs +235 -0
- package/dist/requestFilterMatches.mjs.map +1 -0
- package/dist/retry.d.mts +10 -0
- package/dist/retry.d.ts +10 -0
- package/dist/retry.js +100 -0
- package/dist/retry.js.map +1 -0
- package/dist/retry.mjs +97 -0
- package/dist/retry.mjs.map +1 -0
- package/dist/schemas/index.d.mts +2611 -0
- package/dist/schemas/index.d.ts +2611 -0
- package/dist/schemas/index.js +1630 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/index.mjs +1463 -0
- package/dist/schemas/index.mjs.map +1 -0
- package/dist/{schemas-r4ZP9S-F.d.mts → schemas-C9ssfehv.d.mts} +270 -33
- package/dist/{schemas-r4ZP9S-F.d.ts → schemas-C9ssfehv.d.ts} +270 -33
- package/dist/taskLogger-CzADe4je.d.ts +33 -0
- package/dist/taskLogger-r_AFTX45.d.mts +33 -0
- package/dist/tracer-N0p2Fuuv.d.mts +23 -0
- package/dist/tracer-N0p2Fuuv.d.ts +23 -0
- package/dist/types.d.mts +11 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +3 -0
- package/dist/types.mjs.map +1 -0
- package/dist/utils.d.mts +7 -0
- package/dist/utils.d.ts +7 -0
- package/dist/utils.js +33 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.mjs +30 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/v3/dev/index.d.mts +2 -1
- package/dist/v3/dev/index.d.ts +2 -1
- package/dist/v3/dev/index.js.map +1 -1
- package/dist/v3/dev/index.mjs.map +1 -1
- package/dist/v3/errors.d.mts +39 -0
- package/dist/v3/errors.d.ts +39 -0
- package/dist/v3/errors.js +204 -0
- package/dist/v3/errors.js.map +1 -0
- package/dist/v3/errors.mjs +195 -0
- package/dist/v3/errors.mjs.map +1 -0
- package/dist/v3/index.d.mts +172 -4737
- package/dist/v3/index.d.ts +172 -4737
- package/dist/v3/index.js +871 -620
- package/dist/v3/index.js.map +1 -1
- package/dist/v3/index.mjs +856 -620
- package/dist/v3/index.mjs.map +1 -1
- package/dist/v3/logger-api.d.mts +24 -0
- package/dist/v3/logger-api.d.ts +24 -0
- package/dist/v3/logger-api.js +118 -0
- package/dist/v3/logger-api.js.map +1 -0
- package/dist/v3/logger-api.mjs +116 -0
- package/dist/v3/logger-api.mjs.map +1 -0
- package/dist/v3/otel/index.js +36 -12
- package/dist/v3/otel/index.js.map +1 -1
- package/dist/v3/otel/index.mjs +36 -12
- package/dist/v3/otel/index.mjs.map +1 -1
- package/dist/v3/prod/index.d.mts +4 -3
- package/dist/v3/prod/index.d.ts +4 -3
- package/dist/v3/prod/index.js +7 -131
- package/dist/v3/prod/index.js.map +1 -1
- package/dist/v3/prod/index.mjs +7 -131
- package/dist/v3/prod/index.mjs.map +1 -1
- package/dist/v3/schemas/index.d.mts +4807 -0
- package/dist/v3/schemas/index.d.ts +4807 -0
- package/dist/v3/schemas/index.js +2065 -0
- package/dist/v3/schemas/index.js.map +1 -0
- package/dist/v3/schemas/index.mjs +1924 -0
- package/dist/v3/schemas/index.mjs.map +1 -0
- package/dist/v3/semanticInternalAttributes.d.mts +56 -0
- package/dist/v3/semanticInternalAttributes.d.ts +56 -0
- package/dist/v3/semanticInternalAttributes.js +61 -0
- package/dist/v3/semanticInternalAttributes.js.map +1 -0
- package/dist/v3/semanticInternalAttributes.mjs +59 -0
- package/dist/v3/semanticInternalAttributes.mjs.map +1 -0
- package/dist/v3/utils/durations.d.mts +15 -0
- package/dist/v3/utils/durations.d.ts +15 -0
- package/dist/v3/utils/durations.js +93 -0
- package/dist/v3/utils/durations.js.map +1 -0
- package/dist/v3/utils/durations.mjs +82 -0
- package/dist/v3/utils/durations.mjs.map +1 -0
- package/dist/v3/utils/flattenAttributes.d.mts +8 -0
- package/dist/v3/utils/flattenAttributes.d.ts +8 -0
- package/dist/v3/utils/flattenAttributes.js +131 -0
- package/dist/v3/utils/flattenAttributes.js.map +1 -0
- package/dist/v3/utils/flattenAttributes.mjs +126 -0
- package/dist/v3/utils/flattenAttributes.mjs.map +1 -0
- package/dist/v3/utils/ioSerialization.d.mts +21 -0
- package/dist/v3/utils/ioSerialization.d.ts +21 -0
- package/dist/v3/utils/ioSerialization.js +2403 -0
- package/dist/v3/utils/ioSerialization.js.map +1 -0
- package/dist/v3/utils/ioSerialization.mjs +2394 -0
- package/dist/v3/utils/ioSerialization.mjs.map +1 -0
- package/dist/v3/utils/omit.d.mts +3 -0
- package/dist/v3/utils/omit.d.ts +3 -0
- package/dist/v3/utils/omit.js +20 -0
- package/dist/v3/utils/omit.js.map +1 -0
- package/dist/v3/utils/omit.mjs +18 -0
- package/dist/v3/utils/omit.mjs.map +1 -0
- package/dist/v3/utils/retries.d.mts +46 -0
- package/dist/v3/utils/retries.d.ts +46 -0
- package/dist/v3/utils/retries.js +118 -0
- package/dist/v3/utils/retries.js.map +1 -0
- package/dist/v3/utils/retries.mjs +113 -0
- package/dist/v3/utils/retries.mjs.map +1 -0
- package/dist/v3/utils/timers.d.mts +6 -0
- package/dist/v3/utils/timers.d.ts +6 -0
- package/dist/v3/utils/timers.js +31 -0
- package/dist/v3/utils/timers.js.map +1 -0
- package/dist/v3/utils/timers.mjs +28 -0
- package/dist/v3/utils/timers.mjs.map +1 -0
- package/dist/v3/workers/index.d.mts +56 -8
- package/dist/v3/workers/index.d.ts +56 -8
- package/dist/v3/workers/index.js +755 -279
- package/dist/v3/workers/index.js.map +1 -1
- package/dist/v3/workers/index.mjs +753 -280
- package/dist/v3/workers/index.mjs.map +1 -1
- package/dist/v3/zodIpc.js.map +1 -1
- package/dist/v3/zodIpc.mjs.map +1 -1
- package/dist/v3/zodMessageHandler.d.mts +16 -3
- package/dist/v3/zodMessageHandler.d.ts +16 -3
- package/dist/v3/zodMessageHandler.js +77 -23
- package/dist/v3/zodMessageHandler.js.map +1 -1
- package/dist/v3/zodMessageHandler.mjs +77 -23
- package/dist/v3/zodMessageHandler.mjs.map +1 -1
- package/dist/v3/zodNamespace.js +59 -28
- package/dist/v3/zodNamespace.js.map +1 -1
- package/dist/v3/zodNamespace.mjs +60 -29
- package/dist/v3/zodNamespace.mjs.map +1 -1
- package/dist/v3/zodSocket.d.mts +8 -3
- package/dist/v3/zodSocket.d.ts +8 -3
- package/dist/v3/zodSocket.js +56 -25
- package/dist/v3/zodSocket.js.map +1 -1
- package/dist/v3/zodSocket.mjs +57 -26
- package/dist/v3/zodSocket.mjs.map +1 -1
- package/dist/v3/zodfetch.d.mts +15 -58
- package/dist/v3/zodfetch.d.ts +15 -58
- package/dist/v3/zodfetch.js +246 -156
- package/dist/v3/zodfetch.js.map +1 -1
- package/dist/v3/zodfetch.mjs +244 -149
- package/dist/v3/zodfetch.mjs.map +1 -1
- package/dist/versions.d.mts +11 -0
- package/dist/versions.d.ts +11 -0
- package/dist/versions.js +31 -0
- package/dist/versions.js.map +1 -0
- package/dist/versions.mjs +27 -0
- package/dist/versions.mjs.map +1 -0
- package/package.json +154 -10
package/dist/v3/zodSocket.js
CHANGED
|
@@ -100,35 +100,51 @@ var messageSchema = zod.z.object({
|
|
|
100
100
|
type: zod.z.string(),
|
|
101
101
|
payload: zod.z.unknown()
|
|
102
102
|
});
|
|
103
|
-
var _schema, _handlers;
|
|
103
|
+
var _schema, _handlers, _logger;
|
|
104
104
|
var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
105
105
|
constructor(options) {
|
|
106
106
|
__privateAdd(this, _schema, void 0);
|
|
107
107
|
__privateAdd(this, _handlers, void 0);
|
|
108
|
+
__privateAdd(this, _logger, void 0);
|
|
108
109
|
__privateSet(this, _schema, options.schema);
|
|
109
110
|
__privateSet(this, _handlers, options.handlers);
|
|
111
|
+
__privateSet(this, _logger, options.logger ?? new SimpleStructuredLogger("socket-message-handler", LogLevel.info));
|
|
110
112
|
}
|
|
111
113
|
async handleMessage(message) {
|
|
112
|
-
const
|
|
114
|
+
const parseResult = this.parseMessage(message);
|
|
115
|
+
if (!parseResult.success) {
|
|
116
|
+
__privateGet(this, _logger).error("Failed to parse message, skipping handler", {
|
|
117
|
+
rawMessage: message,
|
|
118
|
+
error: parseResult.reason
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
113
122
|
if (!__privateGet(this, _handlers)) {
|
|
114
123
|
throw new Error("No handlers provided");
|
|
115
124
|
}
|
|
116
|
-
const
|
|
125
|
+
const { type, payload } = parseResult.data;
|
|
126
|
+
const handler = __privateGet(this, _handlers)[type];
|
|
117
127
|
if (!handler) {
|
|
118
|
-
console.error(`No handler for message type: ${String(
|
|
128
|
+
console.error(`No handler for message type: ${String(type)}`);
|
|
119
129
|
return;
|
|
120
130
|
}
|
|
121
|
-
const ack = await handler(
|
|
131
|
+
const ack = await handler(payload);
|
|
122
132
|
return ack;
|
|
123
133
|
}
|
|
124
134
|
parseMessage(message) {
|
|
125
135
|
const parsedMessage = messageSchema.safeParse(message);
|
|
126
136
|
if (!parsedMessage.success) {
|
|
127
|
-
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
reason: `Failed to parse message: ${zodValidationError.fromZodError(parsedMessage.error).toString()}`
|
|
140
|
+
};
|
|
128
141
|
}
|
|
129
142
|
const schema = __privateGet(this, _schema)[parsedMessage.data.type]["message"];
|
|
130
143
|
if (!schema) {
|
|
131
|
-
|
|
144
|
+
return {
|
|
145
|
+
success: false,
|
|
146
|
+
reason: `Unknown message type: ${parsedMessage.data.type}`
|
|
147
|
+
};
|
|
132
148
|
}
|
|
133
149
|
const messageWithVersion = {
|
|
134
150
|
version: parsedMessage.data.version,
|
|
@@ -140,11 +156,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
140
156
|
message,
|
|
141
157
|
payload: messageWithVersion
|
|
142
158
|
});
|
|
143
|
-
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
reason: zodValidationError.fromZodError(parsedPayload.error).toString()
|
|
162
|
+
};
|
|
144
163
|
}
|
|
145
164
|
return {
|
|
146
|
-
|
|
147
|
-
|
|
165
|
+
success: true,
|
|
166
|
+
data: {
|
|
167
|
+
type: parsedMessage.data.type,
|
|
168
|
+
payload: parsedPayload.data
|
|
169
|
+
}
|
|
148
170
|
};
|
|
149
171
|
}
|
|
150
172
|
registerHandlers(emitter, logger) {
|
|
@@ -192,15 +214,18 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
192
214
|
};
|
|
193
215
|
_schema = new WeakMap();
|
|
194
216
|
_handlers = new WeakMap();
|
|
217
|
+
_logger = new WeakMap();
|
|
195
218
|
__name(_ZodSocketMessageHandler, "ZodSocketMessageHandler");
|
|
196
219
|
var ZodSocketMessageHandler = _ZodSocketMessageHandler;
|
|
197
|
-
var _schema2, _socket;
|
|
220
|
+
var _schema2, _socket, _logger2;
|
|
198
221
|
var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
199
222
|
constructor(options) {
|
|
200
223
|
__privateAdd(this, _schema2, void 0);
|
|
201
224
|
__privateAdd(this, _socket, void 0);
|
|
225
|
+
__privateAdd(this, _logger2, void 0);
|
|
202
226
|
__privateSet(this, _schema2, options.schema);
|
|
203
227
|
__privateSet(this, _socket, options.socket);
|
|
228
|
+
__privateSet(this, _logger2, options.logger ?? new SimpleStructuredLogger("zod-socket-sender", LogLevel.info));
|
|
204
229
|
}
|
|
205
230
|
send(type, payload) {
|
|
206
231
|
const schema = __privateGet(this, _schema2)[type]["message"];
|
|
@@ -209,7 +234,10 @@ var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
|
209
234
|
}
|
|
210
235
|
const parsedPayload = schema.safeParse(payload);
|
|
211
236
|
if (!parsedPayload.success) {
|
|
212
|
-
|
|
237
|
+
__privateGet(this, _logger2).error("Failed to parse message payload, will not send", {
|
|
238
|
+
error: parsedPayload.error
|
|
239
|
+
});
|
|
240
|
+
return;
|
|
213
241
|
}
|
|
214
242
|
__privateGet(this, _socket).emit(type, {
|
|
215
243
|
payload,
|
|
@@ -235,14 +263,15 @@ var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
|
235
263
|
};
|
|
236
264
|
_schema2 = new WeakMap();
|
|
237
265
|
_socket = new WeakMap();
|
|
266
|
+
_logger2 = new WeakMap();
|
|
238
267
|
__name(_ZodSocketMessageSender, "ZodSocketMessageSender");
|
|
239
268
|
var ZodSocketMessageSender = _ZodSocketMessageSender;
|
|
240
|
-
var _sender, _handler,
|
|
269
|
+
var _sender, _handler, _logger3;
|
|
241
270
|
var _ZodSocketConnection = class _ZodSocketConnection {
|
|
242
271
|
constructor(opts) {
|
|
243
272
|
__privateAdd(this, _sender, void 0);
|
|
244
273
|
__privateAdd(this, _handler, void 0);
|
|
245
|
-
__privateAdd(this,
|
|
274
|
+
__privateAdd(this, _logger3, void 0);
|
|
246
275
|
const uri = `${opts.secure ? "wss" : "ws"}://${opts.host}:${opts.port ?? (opts.secure ? "443" : "80")}/${opts.namespace}`;
|
|
247
276
|
const logger = new SimpleStructuredLogger(opts.namespace, LogLevel.info);
|
|
248
277
|
logger.log("new zod socket", {
|
|
@@ -257,39 +286,41 @@ var _ZodSocketConnection = class _ZodSocketConnection {
|
|
|
257
286
|
},
|
|
258
287
|
extraHeaders: opts.extraHeaders,
|
|
259
288
|
reconnectionDelay: 500,
|
|
260
|
-
reconnectionDelayMax: 1e3
|
|
289
|
+
reconnectionDelayMax: 1e3,
|
|
290
|
+
...opts.ioOptions
|
|
261
291
|
});
|
|
262
|
-
__privateSet(this,
|
|
292
|
+
__privateSet(this, _logger3, logger.child({
|
|
263
293
|
socketId: this.socket.id
|
|
264
294
|
}));
|
|
265
295
|
__privateSet(this, _handler, new ZodSocketMessageHandler({
|
|
266
296
|
schema: opts.serverMessages,
|
|
267
297
|
handlers: opts.handlers
|
|
268
298
|
}));
|
|
269
|
-
__privateGet(this, _handler).registerHandlers(this.socket, __privateGet(this,
|
|
299
|
+
__privateGet(this, _handler).registerHandlers(this.socket, __privateGet(this, _logger3));
|
|
270
300
|
__privateSet(this, _sender, new ZodSocketMessageSender({
|
|
271
301
|
schema: opts.clientMessages,
|
|
272
|
-
socket: this.socket
|
|
302
|
+
socket: this.socket,
|
|
303
|
+
logger: __privateGet(this, _logger3)
|
|
273
304
|
}));
|
|
274
305
|
this.socket.on("connect_error", async (error) => {
|
|
275
|
-
__privateGet(this,
|
|
306
|
+
__privateGet(this, _logger3).error(`connect_error: ${error}`);
|
|
276
307
|
if (opts.onError) {
|
|
277
|
-
await opts.onError(this.socket, error, __privateGet(this,
|
|
308
|
+
await opts.onError(this.socket, error, __privateGet(this, _logger3));
|
|
278
309
|
}
|
|
279
310
|
});
|
|
280
311
|
this.socket.on("connect", async () => {
|
|
281
|
-
__privateGet(this,
|
|
312
|
+
__privateGet(this, _logger3).info("connect");
|
|
282
313
|
if (opts.onConnection) {
|
|
283
|
-
await opts.onConnection(this.socket, __privateGet(this, _handler), __privateGet(this, _sender), __privateGet(this,
|
|
314
|
+
await opts.onConnection(this.socket, __privateGet(this, _handler), __privateGet(this, _sender), __privateGet(this, _logger3));
|
|
284
315
|
}
|
|
285
316
|
});
|
|
286
317
|
this.socket.on("disconnect", async (reason, description) => {
|
|
287
|
-
__privateGet(this,
|
|
318
|
+
__privateGet(this, _logger3).info("disconnect", {
|
|
288
319
|
reason,
|
|
289
320
|
description
|
|
290
321
|
});
|
|
291
322
|
if (opts.onDisconnect) {
|
|
292
|
-
await opts.onDisconnect(this.socket, reason, description, __privateGet(this,
|
|
323
|
+
await opts.onDisconnect(this.socket, reason, description, __privateGet(this, _logger3));
|
|
293
324
|
}
|
|
294
325
|
});
|
|
295
326
|
}
|
|
@@ -308,7 +339,7 @@ var _ZodSocketConnection = class _ZodSocketConnection {
|
|
|
308
339
|
};
|
|
309
340
|
_sender = new WeakMap();
|
|
310
341
|
_handler = new WeakMap();
|
|
311
|
-
|
|
342
|
+
_logger3 = new WeakMap();
|
|
312
343
|
__name(_ZodSocketConnection, "ZodSocketConnection");
|
|
313
344
|
var ZodSocketConnection = _ZodSocketConnection;
|
|
314
345
|
|
package/dist/v3/zodSocket.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts"],"names":["io","ZodError","z","LogLevel","SimpleStructuredLogger","constructor","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","message","args","console","error","warn","loggerFunction","structuredLog","length","timestamp","Date","JSON","stringify","fromZodError","messageSchema","object","version","string","type","payload","unknown","ZodSocketMessageHandler","options","schema","handlers","handleMessage","parsedMessage","parseMessage","Error","handler","String","ack","safeParse","success","data","messageWithVersion","parsedPayload","registerHandlers","emitter","logger","eventName","Object","keys","on","callback","hasCallback","stack","_schema","ZodSocketMessageSender","socket","send","emit","sendWithAck","callbackResult","emitWithAck","ZodSocketConnection","opts","uri","secure","host","port","namespace","transports","auth","token","authToken","extraHeaders","reconnectionDelay","reconnectionDelayMax","socketId","id","serverMessages","clientMessages","onError","onConnection","reason","description","onDisconnect","close","connect","bind"],"mappings":"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","sourcesContent":["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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts"],"names":["io","z","LogLevel","SimpleStructuredLogger","constructor","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","message","args","console","error","warn","loggerFunction","structuredLog","length","timestamp","Date","JSON","stringify","fromZodError","messageSchema","object","version","string","type","payload","unknown","ZodSocketMessageHandler","options","schema","handlers","logger","handleMessage","parseResult","parseMessage","success","rawMessage","reason","Error","data","handler","String","ack","parsedMessage","safeParse","toString","messageWithVersion","parsedPayload","registerHandlers","emitter","eventName","Object","keys","on","callback","hasCallback","stack","_schema","_logger","ZodSocketMessageSender","socket","send","emit","sendWithAck","callbackResult","emitWithAck","ZodSocketConnection","opts","uri","secure","host","port","namespace","transports","auth","token","authToken","extraHeaders","reconnectionDelay","reconnectionDelayMax","ioOptions","socketId","id","serverMessages","clientMessages","onError","onConnection","description","onDisconnect","close","connect","bind"],"mappings":"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","sourcesContent":["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"]}
|
package/dist/v3/zodSocket.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { io } from 'socket.io-client';
|
|
2
|
-
import { z
|
|
2
|
+
import { z } from 'zod';
|
|
3
3
|
import { fromZodError } from 'zod-validation-error';
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -98,35 +98,51 @@ var messageSchema = z.object({
|
|
|
98
98
|
type: z.string(),
|
|
99
99
|
payload: z.unknown()
|
|
100
100
|
});
|
|
101
|
-
var _schema, _handlers;
|
|
101
|
+
var _schema, _handlers, _logger;
|
|
102
102
|
var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
103
103
|
constructor(options) {
|
|
104
104
|
__privateAdd(this, _schema, void 0);
|
|
105
105
|
__privateAdd(this, _handlers, void 0);
|
|
106
|
+
__privateAdd(this, _logger, void 0);
|
|
106
107
|
__privateSet(this, _schema, options.schema);
|
|
107
108
|
__privateSet(this, _handlers, options.handlers);
|
|
109
|
+
__privateSet(this, _logger, options.logger ?? new SimpleStructuredLogger("socket-message-handler", LogLevel.info));
|
|
108
110
|
}
|
|
109
111
|
async handleMessage(message) {
|
|
110
|
-
const
|
|
112
|
+
const parseResult = this.parseMessage(message);
|
|
113
|
+
if (!parseResult.success) {
|
|
114
|
+
__privateGet(this, _logger).error("Failed to parse message, skipping handler", {
|
|
115
|
+
rawMessage: message,
|
|
116
|
+
error: parseResult.reason
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
111
120
|
if (!__privateGet(this, _handlers)) {
|
|
112
121
|
throw new Error("No handlers provided");
|
|
113
122
|
}
|
|
114
|
-
const
|
|
123
|
+
const { type, payload } = parseResult.data;
|
|
124
|
+
const handler = __privateGet(this, _handlers)[type];
|
|
115
125
|
if (!handler) {
|
|
116
|
-
console.error(`No handler for message type: ${String(
|
|
126
|
+
console.error(`No handler for message type: ${String(type)}`);
|
|
117
127
|
return;
|
|
118
128
|
}
|
|
119
|
-
const ack = await handler(
|
|
129
|
+
const ack = await handler(payload);
|
|
120
130
|
return ack;
|
|
121
131
|
}
|
|
122
132
|
parseMessage(message) {
|
|
123
133
|
const parsedMessage = messageSchema.safeParse(message);
|
|
124
134
|
if (!parsedMessage.success) {
|
|
125
|
-
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
reason: `Failed to parse message: ${fromZodError(parsedMessage.error).toString()}`
|
|
138
|
+
};
|
|
126
139
|
}
|
|
127
140
|
const schema = __privateGet(this, _schema)[parsedMessage.data.type]["message"];
|
|
128
141
|
if (!schema) {
|
|
129
|
-
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
reason: `Unknown message type: ${parsedMessage.data.type}`
|
|
145
|
+
};
|
|
130
146
|
}
|
|
131
147
|
const messageWithVersion = {
|
|
132
148
|
version: parsedMessage.data.version,
|
|
@@ -138,11 +154,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
138
154
|
message,
|
|
139
155
|
payload: messageWithVersion
|
|
140
156
|
});
|
|
141
|
-
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
reason: fromZodError(parsedPayload.error).toString()
|
|
160
|
+
};
|
|
142
161
|
}
|
|
143
162
|
return {
|
|
144
|
-
|
|
145
|
-
|
|
163
|
+
success: true,
|
|
164
|
+
data: {
|
|
165
|
+
type: parsedMessage.data.type,
|
|
166
|
+
payload: parsedPayload.data
|
|
167
|
+
}
|
|
146
168
|
};
|
|
147
169
|
}
|
|
148
170
|
registerHandlers(emitter, logger) {
|
|
@@ -190,15 +212,18 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
190
212
|
};
|
|
191
213
|
_schema = new WeakMap();
|
|
192
214
|
_handlers = new WeakMap();
|
|
215
|
+
_logger = new WeakMap();
|
|
193
216
|
__name(_ZodSocketMessageHandler, "ZodSocketMessageHandler");
|
|
194
217
|
var ZodSocketMessageHandler = _ZodSocketMessageHandler;
|
|
195
|
-
var _schema2, _socket;
|
|
218
|
+
var _schema2, _socket, _logger2;
|
|
196
219
|
var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
197
220
|
constructor(options) {
|
|
198
221
|
__privateAdd(this, _schema2, void 0);
|
|
199
222
|
__privateAdd(this, _socket, void 0);
|
|
223
|
+
__privateAdd(this, _logger2, void 0);
|
|
200
224
|
__privateSet(this, _schema2, options.schema);
|
|
201
225
|
__privateSet(this, _socket, options.socket);
|
|
226
|
+
__privateSet(this, _logger2, options.logger ?? new SimpleStructuredLogger("zod-socket-sender", LogLevel.info));
|
|
202
227
|
}
|
|
203
228
|
send(type, payload) {
|
|
204
229
|
const schema = __privateGet(this, _schema2)[type]["message"];
|
|
@@ -207,7 +232,10 @@ var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
|
207
232
|
}
|
|
208
233
|
const parsedPayload = schema.safeParse(payload);
|
|
209
234
|
if (!parsedPayload.success) {
|
|
210
|
-
|
|
235
|
+
__privateGet(this, _logger2).error("Failed to parse message payload, will not send", {
|
|
236
|
+
error: parsedPayload.error
|
|
237
|
+
});
|
|
238
|
+
return;
|
|
211
239
|
}
|
|
212
240
|
__privateGet(this, _socket).emit(type, {
|
|
213
241
|
payload,
|
|
@@ -233,14 +261,15 @@ var _ZodSocketMessageSender = class _ZodSocketMessageSender {
|
|
|
233
261
|
};
|
|
234
262
|
_schema2 = new WeakMap();
|
|
235
263
|
_socket = new WeakMap();
|
|
264
|
+
_logger2 = new WeakMap();
|
|
236
265
|
__name(_ZodSocketMessageSender, "ZodSocketMessageSender");
|
|
237
266
|
var ZodSocketMessageSender = _ZodSocketMessageSender;
|
|
238
|
-
var _sender, _handler,
|
|
267
|
+
var _sender, _handler, _logger3;
|
|
239
268
|
var _ZodSocketConnection = class _ZodSocketConnection {
|
|
240
269
|
constructor(opts) {
|
|
241
270
|
__privateAdd(this, _sender, void 0);
|
|
242
271
|
__privateAdd(this, _handler, void 0);
|
|
243
|
-
__privateAdd(this,
|
|
272
|
+
__privateAdd(this, _logger3, void 0);
|
|
244
273
|
const uri = `${opts.secure ? "wss" : "ws"}://${opts.host}:${opts.port ?? (opts.secure ? "443" : "80")}/${opts.namespace}`;
|
|
245
274
|
const logger = new SimpleStructuredLogger(opts.namespace, LogLevel.info);
|
|
246
275
|
logger.log("new zod socket", {
|
|
@@ -255,39 +284,41 @@ var _ZodSocketConnection = class _ZodSocketConnection {
|
|
|
255
284
|
},
|
|
256
285
|
extraHeaders: opts.extraHeaders,
|
|
257
286
|
reconnectionDelay: 500,
|
|
258
|
-
reconnectionDelayMax: 1e3
|
|
287
|
+
reconnectionDelayMax: 1e3,
|
|
288
|
+
...opts.ioOptions
|
|
259
289
|
});
|
|
260
|
-
__privateSet(this,
|
|
290
|
+
__privateSet(this, _logger3, logger.child({
|
|
261
291
|
socketId: this.socket.id
|
|
262
292
|
}));
|
|
263
293
|
__privateSet(this, _handler, new ZodSocketMessageHandler({
|
|
264
294
|
schema: opts.serverMessages,
|
|
265
295
|
handlers: opts.handlers
|
|
266
296
|
}));
|
|
267
|
-
__privateGet(this, _handler).registerHandlers(this.socket, __privateGet(this,
|
|
297
|
+
__privateGet(this, _handler).registerHandlers(this.socket, __privateGet(this, _logger3));
|
|
268
298
|
__privateSet(this, _sender, new ZodSocketMessageSender({
|
|
269
299
|
schema: opts.clientMessages,
|
|
270
|
-
socket: this.socket
|
|
300
|
+
socket: this.socket,
|
|
301
|
+
logger: __privateGet(this, _logger3)
|
|
271
302
|
}));
|
|
272
303
|
this.socket.on("connect_error", async (error) => {
|
|
273
|
-
__privateGet(this,
|
|
304
|
+
__privateGet(this, _logger3).error(`connect_error: ${error}`);
|
|
274
305
|
if (opts.onError) {
|
|
275
|
-
await opts.onError(this.socket, error, __privateGet(this,
|
|
306
|
+
await opts.onError(this.socket, error, __privateGet(this, _logger3));
|
|
276
307
|
}
|
|
277
308
|
});
|
|
278
309
|
this.socket.on("connect", async () => {
|
|
279
|
-
__privateGet(this,
|
|
310
|
+
__privateGet(this, _logger3).info("connect");
|
|
280
311
|
if (opts.onConnection) {
|
|
281
|
-
await opts.onConnection(this.socket, __privateGet(this, _handler), __privateGet(this, _sender), __privateGet(this,
|
|
312
|
+
await opts.onConnection(this.socket, __privateGet(this, _handler), __privateGet(this, _sender), __privateGet(this, _logger3));
|
|
282
313
|
}
|
|
283
314
|
});
|
|
284
315
|
this.socket.on("disconnect", async (reason, description) => {
|
|
285
|
-
__privateGet(this,
|
|
316
|
+
__privateGet(this, _logger3).info("disconnect", {
|
|
286
317
|
reason,
|
|
287
318
|
description
|
|
288
319
|
});
|
|
289
320
|
if (opts.onDisconnect) {
|
|
290
|
-
await opts.onDisconnect(this.socket, reason, description, __privateGet(this,
|
|
321
|
+
await opts.onDisconnect(this.socket, reason, description, __privateGet(this, _logger3));
|
|
291
322
|
}
|
|
292
323
|
});
|
|
293
324
|
}
|
|
@@ -306,7 +337,7 @@ var _ZodSocketConnection = class _ZodSocketConnection {
|
|
|
306
337
|
};
|
|
307
338
|
_sender = new WeakMap();
|
|
308
339
|
_handler = new WeakMap();
|
|
309
|
-
|
|
340
|
+
_logger3 = new WeakMap();
|
|
310
341
|
__name(_ZodSocketConnection, "ZodSocketConnection");
|
|
311
342
|
var ZodSocketConnection = _ZodSocketConnection;
|
|
312
343
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts"],"names":["io","ZodError","z","LogLevel","SimpleStructuredLogger","constructor","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","message","args","console","error","warn","loggerFunction","structuredLog","length","timestamp","Date","JSON","stringify","fromZodError","messageSchema","object","version","string","type","payload","unknown","ZodSocketMessageHandler","options","schema","handlers","handleMessage","parsedMessage","parseMessage","Error","handler","String","ack","safeParse","success","data","messageWithVersion","parsedPayload","registerHandlers","emitter","logger","eventName","Object","keys","on","callback","hasCallback","stack","_schema","ZodSocketMessageSender","socket","send","emit","sendWithAck","callbackResult","emitWithAck","ZodSocketConnection","opts","uri","secure","host","port","namespace","transports","auth","token","authToken","extraHeaders","reconnectionDelay","reconnectionDelayMax","socketId","id","serverMessages","clientMessages","onError","onConnection","reason","description","onDisconnect","close","connect","bind"],"mappings":"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","sourcesContent":["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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/v3/zodSocket.ts","../../src/v3/utils/structuredLogger.ts"],"names":["io","z","LogLevel","SimpleStructuredLogger","constructor","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","message","args","console","error","warn","loggerFunction","structuredLog","length","timestamp","Date","JSON","stringify","fromZodError","messageSchema","object","version","string","type","payload","unknown","ZodSocketMessageHandler","options","schema","handlers","logger","handleMessage","parseResult","parseMessage","success","rawMessage","reason","Error","data","handler","String","ack","parsedMessage","safeParse","toString","messageWithVersion","parsedPayload","registerHandlers","emitter","eventName","Object","keys","on","callback","hasCallback","stack","_schema","_logger","ZodSocketMessageSender","socket","send","emit","sendWithAck","callbackResult","emitWithAck","ZodSocketConnection","opts","uri","secure","host","port","namespace","transports","auth","token","authToken","extraHeaders","reconnectionDelay","reconnectionDelayMax","ioOptions","socketId","id","serverMessages","clientMessages","onError","onConnection","description","onDisconnect","close","connect","bind"],"mappings":"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","sourcesContent":["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"]}
|