@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
|
@@ -34,43 +34,81 @@ var ZodMessageSchema = z.object({
|
|
|
34
34
|
type: z.string(),
|
|
35
35
|
payload: z.unknown()
|
|
36
36
|
});
|
|
37
|
-
var _schema, _handlers;
|
|
37
|
+
var _schema, _handlers, _logger;
|
|
38
38
|
var _ZodMessageHandler = class _ZodMessageHandler {
|
|
39
39
|
constructor(options) {
|
|
40
40
|
__privateAdd(this, _schema, void 0);
|
|
41
41
|
__privateAdd(this, _handlers, void 0);
|
|
42
|
+
__privateAdd(this, _logger, void 0);
|
|
42
43
|
__privateSet(this, _schema, options.schema);
|
|
43
44
|
__privateSet(this, _handlers, options.messages);
|
|
45
|
+
__privateSet(this, _logger, options.logger ?? console);
|
|
44
46
|
}
|
|
45
47
|
async handleMessage(message) {
|
|
46
48
|
const parsedMessage = this.parseMessage(message);
|
|
49
|
+
if (!parsedMessage.success) {
|
|
50
|
+
__privateGet(this, _logger).error(parsedMessage.error, {
|
|
51
|
+
message
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
error: parsedMessage.error
|
|
56
|
+
};
|
|
57
|
+
}
|
|
47
58
|
if (!__privateGet(this, _handlers)) {
|
|
48
|
-
|
|
59
|
+
__privateGet(this, _logger).error("No handlers provided", {
|
|
60
|
+
message
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
error: "No handlers provided"
|
|
65
|
+
};
|
|
49
66
|
}
|
|
50
|
-
const handler = __privateGet(this, _handlers)[parsedMessage.type];
|
|
67
|
+
const handler = __privateGet(this, _handlers)[parsedMessage.data.type];
|
|
51
68
|
if (!handler) {
|
|
52
|
-
|
|
53
|
-
|
|
69
|
+
const error = `No handler for message type: ${String(parsedMessage.data.type)}`;
|
|
70
|
+
__privateGet(this, _logger).error(error, {
|
|
71
|
+
message
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
error
|
|
76
|
+
};
|
|
54
77
|
}
|
|
55
|
-
const ack = await handler(parsedMessage.payload);
|
|
56
|
-
return
|
|
78
|
+
const ack = await handler(parsedMessage.data.payload);
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
data: ack
|
|
82
|
+
};
|
|
57
83
|
}
|
|
58
84
|
parseMessage(message) {
|
|
59
85
|
const parsedMessage = ZodMessageSchema.safeParse(message);
|
|
60
86
|
if (!parsedMessage.success) {
|
|
61
|
-
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`
|
|
90
|
+
};
|
|
62
91
|
}
|
|
63
92
|
const schema = __privateGet(this, _schema)[parsedMessage.data.type];
|
|
64
93
|
if (!schema) {
|
|
65
|
-
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
error: `Unknown message type: ${parsedMessage.data.type}`
|
|
97
|
+
};
|
|
66
98
|
}
|
|
67
99
|
const parsedPayload = schema.safeParse(parsedMessage.data.payload);
|
|
68
100
|
if (!parsedPayload.success) {
|
|
69
|
-
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`
|
|
104
|
+
};
|
|
70
105
|
}
|
|
71
106
|
return {
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
success: true,
|
|
108
|
+
data: {
|
|
109
|
+
type: parsedMessage.data.type,
|
|
110
|
+
payload: parsedPayload.data
|
|
111
|
+
}
|
|
74
112
|
};
|
|
75
113
|
}
|
|
76
114
|
registerHandlers(emitter, logger) {
|
|
@@ -100,7 +138,14 @@ var _ZodMessageHandler = class _ZodMessageHandler {
|
|
|
100
138
|
});
|
|
101
139
|
}
|
|
102
140
|
if (callback && typeof callback === "function") {
|
|
103
|
-
|
|
141
|
+
if (!ack.success) {
|
|
142
|
+
log.error("Failed to handle message, skipping callback", {
|
|
143
|
+
message,
|
|
144
|
+
error: ack.error
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
callback(ack.data);
|
|
104
149
|
}
|
|
105
150
|
});
|
|
106
151
|
}
|
|
@@ -108,6 +153,7 @@ var _ZodMessageHandler = class _ZodMessageHandler {
|
|
|
108
153
|
};
|
|
109
154
|
_schema = new WeakMap();
|
|
110
155
|
_handlers = new WeakMap();
|
|
156
|
+
_logger = new WeakMap();
|
|
111
157
|
__name(_ZodMessageHandler, "ZodMessageHandler");
|
|
112
158
|
var ZodMessageHandler = _ZodMessageHandler;
|
|
113
159
|
var _schema2, _sender;
|
|
@@ -127,11 +173,15 @@ var _ZodMessageSender = class _ZodMessageSender {
|
|
|
127
173
|
if (!parsedPayload.success) {
|
|
128
174
|
throw new ZodSchemaParsedError(parsedPayload.error, payload);
|
|
129
175
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
176
|
+
try {
|
|
177
|
+
await __privateGet(this, _sender).call(this, {
|
|
178
|
+
type,
|
|
179
|
+
payload,
|
|
180
|
+
version: "v1"
|
|
181
|
+
});
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error("[ZodMessageSender] Failed to send message", error);
|
|
184
|
+
}
|
|
135
185
|
}
|
|
136
186
|
async forwardMessage(message) {
|
|
137
187
|
const parsedMessage = ZodMessageSchema.safeParse(message);
|
|
@@ -146,11 +196,15 @@ var _ZodMessageSender = class _ZodMessageSender {
|
|
|
146
196
|
if (!parsedPayload.success) {
|
|
147
197
|
throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);
|
|
148
198
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
199
|
+
try {
|
|
200
|
+
await __privateGet(this, _sender).call(this, {
|
|
201
|
+
type: parsedMessage.data.type,
|
|
202
|
+
payload: parsedPayload.data,
|
|
203
|
+
version: "v1"
|
|
204
|
+
});
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error("[ZodMessageSender] Failed to forward message", error);
|
|
207
|
+
}
|
|
154
208
|
}
|
|
155
209
|
};
|
|
156
210
|
_schema2 = new WeakMap();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/v3/zodMessageHandler.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageHandler","options","schema","messages","handleMessage","parsedMessage","parseMessage","handler","console","String","ack","safeParse","success","JSON","stringify","data","parsedPayload","registerHandlers","emitter","logger","log","info","eventName","Object","keys","on","callback","hasCallback","_schema","ZodMessageSender","sender","send","forwardMessage"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,SAAS;AAGX,IAAMC,wBAAN,MAAMA,8BAA6BC,MAAAA;EACxCC,YACSC,OACAC,SACP;AACA,UAAMD,MAAME,OAAO;iBAHZF;mBACAC;EAGT;AACF;AAP0CH;AAAnC,IAAMD,uBAAN;AAsCA,IAAMM,mBAAmBP,EAAEQ,OAAO;EACvCC,SAAST,EAAEU,QAAQ,IAAA,EAAMC,QAAQ,IAAA;EACjCC,MAAMZ,EAAEa,OAAM;EACdR,SAASL,EAAEc,QAAO;AACpB,CAAA;AA7CA;AAmDO,IAAMC,qBAAN,MAAMA,mBAAAA;EAIXZ,YAAYa,SAAoD;AAHhE;AACA;AAGE,uBAAK,SAAUA,QAAQC;AACvB,uBAAK,WAAYD,QAAQE;EAC3B;EAEA,MAAaC,cAAcb,SAAkB;AAC3C,UAAMc,gBAAgB,KAAKC,aAAaf,OAAAA;AAExC,QAAI,CAAC,mBAAK,YAAW;AACnB,YAAM,IAAIJ,MAAM,sBAAA;IAClB;AAEA,UAAMoB,UAAU,mBAAK,WAAUF,cAAcR,IAAI;AAEjD,QAAI,CAACU,SAAS;AACZC,cAAQnB,MAAM,gCAAgCoB,OAAOJ,cAAcR,IAAI,CAAA,EAAG;AAC1E;IACF;AAEA,UAAMa,MAAM,MAAMH,QAAQF,cAAcf,OAAO;AAE/C,WAAOoB;EACT;EAEOJ,aAAaf,SAAuD;AACzE,UAAMc,gBAAgBb,iBAAiBmB,UAAUpB,OAAAA;AAEjD,QAAI,CAACc,cAAcO,SAAS;AAC1B,YAAM,IAAIzB,MAAM,4BAA4B0B,KAAKC,UAAUT,cAAchB,KAAK,CAAA,EAAG;IACnF;AAEA,UAAMa,SAAS,mBAAK,SAAQG,cAAcU,KAAKlB,IAAI;AAEnD,QAAI,CAACK,QAAQ;AACX,YAAM,IAAIf,MAAM,yBAAyBkB,cAAcU,KAAKlB,IAAI,EAAE;IACpE;AAEA,UAAMmB,gBAAgBd,OAAOS,UAAUN,cAAcU,KAAKzB,OAAO;AAEjE,QAAI,CAAC0B,cAAcJ,SAAS;AAC1B,YAAM,IAAIzB,MAAM,oCAAoC0B,KAAKC,UAAUE,cAAc3B,KAAK,CAAA,EAAG;IAC3F;AAEA,WAAO;MACLQ,MAAMQ,cAAcU,KAAKlB;MACzBP,SAAS0B,cAAcD;IACzB;EACF;EAEOE,iBAAiBC,SAA2BC,QAA2B;AAC5E,UAAMC,MAAMD,UAAUX;AAEtB,QAAI,CAAC,mBAAK,YAAW;AACnBY,UAAIC,KAAK,sBAAA;AACT;IACF;AAEA,eAAWC,aAAaC,OAAOC,KAAK,mBAAK,QAAO,GAAG;AACjDN,cAAQO,GAAGH,WAAW,OAAO/B,SAAcmC,aAAkC;AAC3EN,YAAIC,KAAK,YAAYC,SAAAA,IAAa;UAChChC,SAASC;UACToC,aAAa,CAAC,CAACD;QACjB,CAAA;AAEA,YAAIhB;AAGJ,YAAI,aAAanB,SAAS;AACxBmB,gBAAM,MAAM,KAAKN,cAAc;YAAEP,MAAMyB;YAAW,GAAG/B;UAAQ,CAAA;QAC/D,OAAO;AAEL,gBAAM,EAAEG,SAAS,GAAGJ,QAAAA,IAAYC;AAChCmB,gBAAM,MAAM,KAAKN,cAAc;YAAEP,MAAMyB;YAAW5B;YAASJ;UAAQ,CAAA;QACrE;AAEA,YAAIoC,YAAY,OAAOA,aAAa,YAAY;AAC9CA,mBAAShB,GAAAA;QACX;MACF,CAAA;IACF;EACF;AACF;AApFE;AACA;AAFWV;AAAN,IAAMA,oBAAN;AAnDP,IAAA4B,UAAA;AAqJO,IAAMC,oBAAN,MAAMA,kBAAAA;EAIXzC,YAAYa,SAAmD;AAH/D,uBAAA2B,UAAA;AACA;AAGE,uBAAKA,UAAU3B,QAAQC;AACvB,uBAAK,SAAUD,QAAQ6B;EACzB;EAEA,MAAaC,KACXlC,MACAP,SACA;AACA,UAAMY,SAAS,mBAAK0B,UAAQ/B,IAAAA;AAE5B,QAAI,CAACK,QAAQ;AACX,YAAM,IAAIf,MAAM,yBAAyBU,IAAAA,EAAgB;IAC3D;AAEA,UAAMmB,gBAAgBd,OAAOS,UAAUrB,OAAAA;AAEvC,QAAI,CAAC0B,cAAcJ,SAAS;AAC1B,YAAM,IAAI1B,qBAAqB8B,cAAc3B,OAAOC,OAAAA;IACtD;AAEA,UAAM,mBAAK,SAAL,WAAa;MAAEO;MAAMP;MAASI,SAAS;IAAK;EACpD;EAEA,MAAasC,eAAezC,SAAkB;AAC5C,UAAMc,gBAAgBb,iBAAiBmB,UAAUpB,OAAAA;AAEjD,QAAI,CAACc,cAAcO,SAAS;AAC1B,YAAM,IAAIzB,MAAM,4BAA4B0B,KAAKC,UAAUT,cAAchB,KAAK,CAAA,EAAG;IACnF;AAEA,UAAMa,SAAS,mBAAK0B,UAAQvB,cAAcU,KAAKlB,IAAI;AAEnD,QAAI,CAACK,QAAQ;AACX,YAAM,IAAIf,MAAM,yBAAyBkB,cAAcU,KAAKlB,IAAI,EAAE;IACpE;AAEA,UAAMmB,gBAAgBd,OAAOS,UAAUN,cAAcU,KAAKzB,OAAO;AAEjE,QAAI,CAAC0B,cAAcJ,SAAS;AAC1B,YAAM,IAAIzB,MAAM,oCAAoC0B,KAAKC,UAAUE,cAAc3B,KAAK,CAAA,EAAG;IAC3F;AAEA,UAAM,mBAAK,SAAL,WAAa;MACjBQ,MAAMQ,cAAcU,KAAKlB;MACzBP,SAAS0B,cAAcD;MACvBrB,SAAS;IACX;EACF;AACF;AApDEkC,WAAA;AACA;AAFWC;AAAN,IAAMA,mBAAN","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 await this.#sender({ type, payload, version: \"v1\" });\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/v3/zodMessageHandler.ts"],"names":["z","ZodSchemaParsedError","Error","constructor","error","payload","message","ZodMessageSchema","object","version","literal","default","type","string","unknown","ZodMessageHandler","options","schema","messages","logger","console","handleMessage","parsedMessage","parseMessage","success","handler","data","String","ack","safeParse","JSON","stringify","parsedPayload","registerHandlers","emitter","log","info","eventName","Object","keys","on","callback","hasCallback","_schema","ZodMessageSender","sender","send","forwardMessage"],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n #logger: StructuredLogger | Console;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n this.#logger = options.logger ?? console;\n }\n\n public async handleMessage(message: unknown): Promise<\n | {\n success: true;\n data: unknown;\n }\n | {\n success: false;\n error: string;\n }\n > {\n const parsedMessage = this.parseMessage(message);\n\n if (!parsedMessage.success) {\n this.#logger.error(parsedMessage.error, { message });\n\n return {\n success: false,\n error: parsedMessage.error,\n };\n }\n\n if (!this.#handlers) {\n this.#logger.error(\"No handlers provided\", { message });\n\n return {\n success: false,\n error: \"No handlers provided\",\n };\n }\n\n const handler = this.#handlers[parsedMessage.data.type];\n\n if (!handler) {\n const error = `No handler for message type: ${String(parsedMessage.data.type)}`;\n\n this.#logger.error(error, { message });\n\n return {\n success: false,\n error,\n };\n }\n\n const ack = await handler(parsedMessage.data.payload);\n\n return {\n success: true,\n data: ack,\n };\n }\n\n public parseMessage(message: unknown):\n | {\n success: true;\n data: MessageFromCatalog<TMessageCatalog>;\n }\n | {\n success: false;\n error: string;\n } {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n return {\n success: false,\n error: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n return {\n success: false,\n error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`,\n };\n }\n\n return {\n success: true,\n data: {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n },\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack: Awaited<ReturnType<ZodMessageHandler<TMessageCatalog>[\"handleMessage\"]>>;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n if (!ack.success) {\n // We don't know the callback type, so we can't do anything else - not all callbacks may accept a success prop\n log.error(\"Failed to handle message, skipping callback\", { message, error: ack.error });\n return;\n }\n\n callback(ack.data);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n"]}
|
package/dist/v3/zodNamespace.js
CHANGED
|
@@ -59,11 +59,15 @@ var _ZodMessageSender = class _ZodMessageSender {
|
|
|
59
59
|
if (!parsedPayload.success) {
|
|
60
60
|
throw new ZodSchemaParsedError(parsedPayload.error, payload);
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
try {
|
|
63
|
+
await __privateGet(this, _sender).call(this, {
|
|
64
|
+
type,
|
|
65
|
+
payload,
|
|
66
|
+
version: "v1"
|
|
67
|
+
});
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error("[ZodMessageSender] Failed to send message", error);
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
async forwardMessage(message) {
|
|
69
73
|
const parsedMessage = ZodMessageSchema.safeParse(message);
|
|
@@ -78,11 +82,15 @@ var _ZodMessageSender = class _ZodMessageSender {
|
|
|
78
82
|
if (!parsedPayload.success) {
|
|
79
83
|
throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);
|
|
80
84
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
try {
|
|
86
|
+
await __privateGet(this, _sender).call(this, {
|
|
87
|
+
type: parsedMessage.data.type,
|
|
88
|
+
payload: parsedPayload.data,
|
|
89
|
+
version: "v1"
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error("[ZodMessageSender] Failed to forward message", error);
|
|
93
|
+
}
|
|
86
94
|
}
|
|
87
95
|
};
|
|
88
96
|
_schema = new WeakMap();
|
|
@@ -161,35 +169,51 @@ var messageSchema = zod.z.object({
|
|
|
161
169
|
type: zod.z.string(),
|
|
162
170
|
payload: zod.z.unknown()
|
|
163
171
|
});
|
|
164
|
-
var _schema2, _handlers;
|
|
172
|
+
var _schema2, _handlers, _logger;
|
|
165
173
|
var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
166
174
|
constructor(options) {
|
|
167
175
|
__privateAdd(this, _schema2, void 0);
|
|
168
176
|
__privateAdd(this, _handlers, void 0);
|
|
177
|
+
__privateAdd(this, _logger, void 0);
|
|
169
178
|
__privateSet(this, _schema2, options.schema);
|
|
170
179
|
__privateSet(this, _handlers, options.handlers);
|
|
180
|
+
__privateSet(this, _logger, options.logger ?? new SimpleStructuredLogger("socket-message-handler", LogLevel.info));
|
|
171
181
|
}
|
|
172
182
|
async handleMessage(message) {
|
|
173
|
-
const
|
|
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
|
+
}
|
|
174
191
|
if (!__privateGet(this, _handlers)) {
|
|
175
192
|
throw new Error("No handlers provided");
|
|
176
193
|
}
|
|
177
|
-
const
|
|
194
|
+
const { type, payload } = parseResult.data;
|
|
195
|
+
const handler = __privateGet(this, _handlers)[type];
|
|
178
196
|
if (!handler) {
|
|
179
|
-
console.error(`No handler for message type: ${String(
|
|
197
|
+
console.error(`No handler for message type: ${String(type)}`);
|
|
180
198
|
return;
|
|
181
199
|
}
|
|
182
|
-
const ack = await handler(
|
|
200
|
+
const ack = await handler(payload);
|
|
183
201
|
return ack;
|
|
184
202
|
}
|
|
185
203
|
parseMessage(message) {
|
|
186
204
|
const parsedMessage = messageSchema.safeParse(message);
|
|
187
205
|
if (!parsedMessage.success) {
|
|
188
|
-
|
|
206
|
+
return {
|
|
207
|
+
success: false,
|
|
208
|
+
reason: `Failed to parse message: ${zodValidationError.fromZodError(parsedMessage.error).toString()}`
|
|
209
|
+
};
|
|
189
210
|
}
|
|
190
211
|
const schema = __privateGet(this, _schema2)[parsedMessage.data.type]["message"];
|
|
191
212
|
if (!schema) {
|
|
192
|
-
|
|
213
|
+
return {
|
|
214
|
+
success: false,
|
|
215
|
+
reason: `Unknown message type: ${parsedMessage.data.type}`
|
|
216
|
+
};
|
|
193
217
|
}
|
|
194
218
|
const messageWithVersion = {
|
|
195
219
|
version: parsedMessage.data.version,
|
|
@@ -201,11 +225,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
201
225
|
message,
|
|
202
226
|
payload: messageWithVersion
|
|
203
227
|
});
|
|
204
|
-
|
|
228
|
+
return {
|
|
229
|
+
success: false,
|
|
230
|
+
reason: zodValidationError.fromZodError(parsedPayload.error).toString()
|
|
231
|
+
};
|
|
205
232
|
}
|
|
206
233
|
return {
|
|
207
|
-
|
|
208
|
-
|
|
234
|
+
success: true,
|
|
235
|
+
data: {
|
|
236
|
+
type: parsedMessage.data.type,
|
|
237
|
+
payload: parsedPayload.data
|
|
238
|
+
}
|
|
209
239
|
};
|
|
210
240
|
}
|
|
211
241
|
registerHandlers(emitter, logger) {
|
|
@@ -253,16 +283,17 @@ var _ZodSocketMessageHandler = class _ZodSocketMessageHandler {
|
|
|
253
283
|
};
|
|
254
284
|
_schema2 = new WeakMap();
|
|
255
285
|
_handlers = new WeakMap();
|
|
286
|
+
_logger = new WeakMap();
|
|
256
287
|
__name(_ZodSocketMessageHandler, "ZodSocketMessageHandler");
|
|
257
288
|
var ZodSocketMessageHandler = _ZodSocketMessageHandler;
|
|
258
289
|
|
|
259
290
|
// src/v3/zodNamespace.ts
|
|
260
|
-
var
|
|
291
|
+
var _logger2, _handler;
|
|
261
292
|
var _ZodNamespace = class _ZodNamespace {
|
|
262
293
|
constructor(opts) {
|
|
263
|
-
__privateAdd(this,
|
|
294
|
+
__privateAdd(this, _logger2, void 0);
|
|
264
295
|
__privateAdd(this, _handler, void 0);
|
|
265
|
-
__privateSet(this,
|
|
296
|
+
__privateSet(this, _logger2, opts.logger ?? new SimpleStructuredLogger(opts.name));
|
|
266
297
|
__privateSet(this, _handler, new ZodSocketMessageHandler({
|
|
267
298
|
schema: opts.clientMessages,
|
|
268
299
|
handlers: opts.handlers
|
|
@@ -284,7 +315,7 @@ var _ZodNamespace = class _ZodNamespace {
|
|
|
284
315
|
});
|
|
285
316
|
if (opts.preAuth) {
|
|
286
317
|
this.namespace.use(async (socket, next) => {
|
|
287
|
-
const logger = __privateGet(this,
|
|
318
|
+
const logger = __privateGet(this, _logger2).child({
|
|
288
319
|
socketId: socket.id,
|
|
289
320
|
socketStage: "preAuth"
|
|
290
321
|
});
|
|
@@ -295,7 +326,7 @@ var _ZodNamespace = class _ZodNamespace {
|
|
|
295
326
|
}
|
|
296
327
|
if (opts.authToken) {
|
|
297
328
|
this.namespace.use((socket, next) => {
|
|
298
|
-
const logger = __privateGet(this,
|
|
329
|
+
const logger = __privateGet(this, _logger2).child({
|
|
299
330
|
socketId: socket.id,
|
|
300
331
|
socketStage: "auth"
|
|
301
332
|
});
|
|
@@ -314,7 +345,7 @@ var _ZodNamespace = class _ZodNamespace {
|
|
|
314
345
|
}
|
|
315
346
|
if (opts.postAuth) {
|
|
316
347
|
this.namespace.use(async (socket, next) => {
|
|
317
|
-
const logger = __privateGet(this,
|
|
348
|
+
const logger = __privateGet(this, _logger2).child({
|
|
318
349
|
socketId: socket.id,
|
|
319
350
|
socketStage: "auth"
|
|
320
351
|
});
|
|
@@ -324,7 +355,7 @@ var _ZodNamespace = class _ZodNamespace {
|
|
|
324
355
|
});
|
|
325
356
|
}
|
|
326
357
|
this.namespace.on("connection", async (socket) => {
|
|
327
|
-
const logger = __privateGet(this,
|
|
358
|
+
const logger = __privateGet(this, _logger2).child({
|
|
328
359
|
socketId: socket.id,
|
|
329
360
|
socketStage: "connection"
|
|
330
361
|
});
|
|
@@ -356,7 +387,7 @@ var _ZodNamespace = class _ZodNamespace {
|
|
|
356
387
|
return this.namespace.fetchSockets();
|
|
357
388
|
}
|
|
358
389
|
};
|
|
359
|
-
|
|
390
|
+
_logger2 = new WeakMap();
|
|
360
391
|
_handler = new WeakMap();
|
|
361
392
|
__name(_ZodNamespace, "ZodNamespace");
|
|
362
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","forwardMessage","parsedMessage","JSON","stringify","data","io","ZodError","LogLevel","SimpleStructuredLogger","name","level","includes","process","env","DEBUG","debug","info","fields","child","log","args","console","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 await this.#sender({ type, payload, version: \"v1\" });\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n","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":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,SAAS;AAGX,IAAMC,wBAAN,MAAMA,8BAA6BC,MAAAA;EACxCC,YACSC,OACAC,SACP;AACA,UAAMD,MAAME,OAAO;iBAHZF;mBACAC;EAGT;AACF;AAP0CH;AAAnC,IAAMD,uBAAN;AAuCA,IAAMM,mBAAmBP,EAAEQ,OAAO;EACvCC,SAAST,EAAEU,QAAQ,IAAA,EAAMC,QAAQ,IAAA;EACjCC,MAAMZ,EAAEa,OAAM;EACdR,SAASL,EAAEc,QAAO;AACpB,CAAA;AA9CA;AAkNO,IAAMC,oBAAN,MAAMA,kBAAAA;EAIXZ,YAAYa,SAAmD;AAH/D;AACA;AAGE,uBAAK,SAAUA,QAAQC;AACvB,uBAAK,SAAUD,QAAQE;EACzB;EAEA,MAAaC,KACXP,MACAP,SACA;AACA,UAAMY,SAAS,mBAAK,SAAQL,IAAAA;AAE5B,QAAI,CAACK,QAAQ;AACX,YAAM,IAAIf,MAAM,yBAAyBU,IAAAA,EAAgB;IAC3D;AAEA,UAAMQ,gBAAgBH,OAAOI,UAAUhB,OAAAA;AAEvC,QAAI,CAACe,cAAcE,SAAS;AAC1B,YAAM,IAAIrB,qBAAqBmB,cAAchB,OAAOC,OAAAA;IACtD;AAEA,QAAI;AACF,YAAM,mBAAK,SAAL,WAAa;QAAEO;QAAMP;QAASI,SAAS;MAAK;IACpD,SAASL,OAAO;AACdmB,cAAQnB,MAAM,6CAA6CA,KAAAA;IAC7D;EACF;EAEA,MAAaoB,eAAelB,SAAkB;AAC5C,UAAMmB,gBAAgBlB,iBAAiBc,UAAUf,OAAAA;AAEjD,QAAI,CAACmB,cAAcH,SAAS;AAC1B,YAAM,IAAIpB,MAAM,4BAA4BwB,KAAKC,UAAUF,cAAcrB,KAAK,CAAA,EAAG;IACnF;AAEA,UAAMa,SAAS,mBAAK,SAAQQ,cAAcG,KAAKhB,IAAI;AAEnD,QAAI,CAACK,QAAQ;AACX,YAAM,IAAIf,MAAM,yBAAyBuB,cAAcG,KAAKhB,IAAI,EAAE;IACpE;AAEA,UAAMQ,gBAAgBH,OAAOI,UAAUI,cAAcG,KAAKvB,OAAO;AAEjE,QAAI,CAACe,cAAcE,SAAS;AAC1B,YAAM,IAAIpB,MAAM,oCAAoCwB,KAAKC,UAAUP,cAAchB,KAAK,CAAA,EAAG;IAC3F;AAEA,QAAI;AACF,YAAM,mBAAK,SAAL,WAAa;QACjBQ,MAAMa,cAAcG,KAAKhB;QACzBP,SAASe,cAAcQ;QACvBnB,SAAS;MACX;IACF,SAASL,OAAO;AACdmB,cAAQnB,MAAM,gDAAgDA,KAAAA;IAChE;EACF;AACF;AA5DE;AACA;AAFWW;AAAN,IAAMA,mBAAN;;;ACjNP,SAASc,UAAU;AACnB,SAAmB7B,KAAAA,UAAS;;;ICSrB;UAAK8B,WAAQ;AAARA,EAAAA,UAAAA,UACV,KAAA,IAAA,CAAA,IAAA;AADUA,EAAAA,UAAAA,UAEV,OAAA,IAAA,CAAA,IAAA;AAFUA,EAAAA,UAAAA,UAGV,MAAA,IAAA,CAAA,IAAA;AAHUA,EAAAA,UAAAA,UAIV,MAAA,IAAA,CAAA,IAAA;AAJUA,EAAAA,UAAAA,UAKV,OAAA,IAAA,CAAA,IAAA;GALUA,aAAAA,WAAAA,CAAAA,EAAAA;;AAQL,IAAMC,0BAAN,MAAMA,wBAAAA;EACX5B,YACU6B,MACAC,QAAkB;IAAC;IAAK;IAAQC,SAASC,QAAQC,IAAIC,SAAS,EAAA,IAClEP,SAASQ,QACTR,SAASS,MACLC,QACR;AAoCF;gBAzCUR;iBACAC;kBAGAO;EACP;EAEHC,MAAMD,QAAiCP,OAAkB;AACvD,WAAO,IAAIF,wBAAuB,KAAKC,MAAMC,OAAO;MAAE,GAAG,KAAKO;MAAQ,GAAGA;IAAO,CAAA;EAClF;EAEAE,IAAIpC,YAAoBqC,MAAsB;AAC5C,QAAI,KAAKV,QAAQH,SAASY;AAAK;AAE/B,0BAAK,kCAAL,WAAoBnB,QAAQmB,KAAKpC,SAAS,OAAA,GAAUqC;EACtD;EAEAvC,MAAME,YAAoBqC,MAAsB;AAC9C,QAAI,KAAKV,QAAQH,SAAS1B;AAAO;AAEjC,0BAAK,kCAAL,WAAoBmB,QAAQnB,OAAOE,SAAS,SAAA,GAAYqC;EAC1D;EAEAC,KAAKtC,YAAoBqC,MAAsB;AAC7C,QAAI,KAAKV,QAAQH,SAASc;AAAM;AAEhC,0BAAK,kCAAL,WAAoBrB,QAAQqB,MAAMtC,SAAS,QAAA,GAAWqC;EACxD;EAEAJ,KAAKjC,YAAoBqC,MAAsB;AAC7C,QAAI,KAAKV,QAAQH,SAASS;AAAM;AAEhC,0BAAK,kCAAL,WAAoBhB,QAAQgB,MAAMjC,SAAS,QAAA,GAAWqC;EACxD;EAEAL,MAAMhC,YAAoBqC,MAAsB;AAC9C,QAAI,KAAKV,QAAQH,SAASQ;AAAO;AAEjC,0BAAK,kCAAL,WAAoBf,QAAQe,OAAOhC,SAAS,SAAA,GAAYqC;EAC1D;AAmBF;AAjBE;mBAAc,gCACZE,gBACAvC,SACA2B,UACGU,MACH;AACA,QAAMG,gBAAgB;IACpB,GAAIH,KAAKI,WAAW,IAAIJ,KAAK,CAAA,IAAKA;IAClC,GAAG,KAAKH;IACRQ,WAAW,oBAAIC,KAAAA;IACfjB,MAAM,KAAKA;IACX1B;IACA2B;EACF;AAEAY,iBAAenB,KAAKC,UAAUmB,aAAAA,CAAAA;AAChC,GAhBc;AA3CHf;AAAN,IAAMA,yBAAN;;;ADdP,SAASmB,oBAAoB;AA+E7B,IAAMC,gBAAgBnD,GAAEQ,OAAO;EAC7BC,SAAST,GAAEa,OAAM;EACjBD,MAAMZ,GAAEa,OAAM;EACdR,SAASL,GAAEc,QAAO;AACpB,CAAA;AAvFA,IAAAsC,UAAA;AAyFO,IAAMC,2BAAN,MAAMA,yBAAAA;EAKXlD,YAAYa,SAAsD;AAJlE,uBAAAoC,UAAA;AACA;AACA;AAGE,uBAAKA,UAAUpC,QAAQC;AACvB,uBAAK,WAAYD,QAAQsC;AACzB,uBAAK,SACHtC,QAAQuC,UAAU,IAAIxB,uBAAuB,0BAA0BD,SAASS,IAAI;EACxF;EAEA,MAAaiB,cAAclD,SAAkB;AAC3C,UAAMmD,cAAc,KAAKC,aAAapD,OAAAA;AAEtC,QAAI,CAACmD,YAAYnC,SAAS;AACxB,yBAAK,SAAQlB,MAAM,6CAA6C;QAC9DuD,YAAYrD;QACZF,OAAOqD,YAAYG;MACrB,CAAA;AACA;IACF;AAEA,QAAI,CAAC,mBAAK,YAAW;AACnB,YAAM,IAAI1D,MAAM,sBAAA;IAClB;AAEA,UAAM,EAAEU,MAAMP,QAAO,IAAKoD,YAAY7B;AAEtC,UAAMiC,UAAU,mBAAK,WAAUjD,IAAAA;AAE/B,QAAI,CAACiD,SAAS;AACZtC,cAAQnB,MAAM,gCAAgC0D,OAAOlD,IAAAA,CAAAA,EAAO;AAC5D;IACF;AAEA,UAAMmD,MAAM,MAAMF,QAAQxD,OAAAA;AAE1B,WAAO0D;EACT;EAEQL,aAAapD,SAQf;AACJ,UAAMmB,gBAAgB0B,cAAc9B,UAAUf,OAAAA;AAE9C,QAAI,CAACmB,cAAcH,SAAS;AAC1B,aAAO;QACLA,SAAS;QACTsC,QAAQ,4BAA4BV,aAAazB,cAAcrB,KAAK,EAAE4D,SAAQ,CAAA;MAChF;IACF;AAEA,UAAM/C,SAAS,mBAAKmC,UAAQ3B,cAAcG,KAAKhB,IAAI,EAAE,SAAA;AAErD,QAAI,CAACK,QAAQ;AACX,aAAO;QACLK,SAAS;QACTsC,QAAQ,yBAAyBnC,cAAcG,KAAKhB,IAAI;MAC1D;IACF;AAEA,UAAMqD,qBAAqB;MACzBxD,SAASgB,cAAcG,KAAKnB;MAC5B,GAAI,OAAOgB,cAAcG,KAAKvB,YAAY,WAAWoB,cAAcG,KAAKvB,UAAU,CAAC;IACrF;AAEA,UAAMe,gBAAgBH,OAAOI,UAAU4C,kBAAAA;AAEvC,QAAI,CAAC7C,cAAcE,SAAS;AAC1BC,cAAQnB,MAAM,mCAAmC;QAC/CE;QACAD,SAAS4D;MACX,CAAA;AAEA,aAAO;QACL3C,SAAS;QACTsC,QAAQV,aAAa9B,cAAchB,KAAK,EAAE4D,SAAQ;MACpD;IACF;AAEA,WAAO;MACL1C,SAAS;MACTM,MAAM;QACJhB,MAAMa,cAAcG,KAAKhB;QACzBP,SAASe,cAAcQ;MACzB;IACF;EACF;EAEOsC,iBAAiBC,SAA2BZ,QAA2B;AAC5E,UAAMb,MAAMa,UAAUhC;AAEtB,QAAI,CAAC,mBAAK,YAAW;AACnBmB,UAAIH,KAAK,sBAAA;AACT;IACF;AAEA,eAAW6B,aAAaC,OAAOC,KAAK,mBAAK,UAAS,GAAG;AACnDH,cAAQI,GAAGH,WAAW,OAAO9D,SAAckE,aAAkC;AAC3E9B,YAAIH,KAAK,YAAY6B,SAAAA,IAAa;UAChC/D,SAASC;UACTmE,aAAa,CAAC,CAACD;QACjB,CAAA;AAEA,YAAIT;AAEJ,YAAI;AAEF,cAAI,aAAazD,SAAS;AACxByD,kBAAM,MAAM,KAAKP,cAAc;cAAE5C,MAAMwD;cAAW,GAAG9D;YAAQ,CAAA;UAC/D,OAAO;AAEL,kBAAM,EAAEG,SAAS,GAAGJ,QAAAA,IAAYC;AAChCyD,kBAAM,MAAM,KAAKP,cAAc;cAAE5C,MAAMwD;cAAW3D;cAASJ;YAAQ,CAAA;UACrE;QACF,SAASD,OAAO;AACdsC,cAAItC,MAAM,gCAAgC;YACxCA,OACEA,iBAAiBF,QACb;cACEI,SAASF,MAAME;cACfoE,OAAOtE,MAAMsE;YACf,IACAtE;UACR,CAAA;AACA;QACF;AAEA,YAAIoE,YAAY,OAAOA,aAAa,YAAY;AAC9CA,mBAAST,GAAAA;QACX;MACF,CAAA;IACF;EACF;AACF;AA5IEX,WAAA;AACA;AACA;AAHWC;AAAN,IAAMA,0BAAN;;;AEzFP,IAAAsB,UAAA;AAsEO,IAAMC,gBAAN,MAAMA,cAAAA;EAkBXzE,YACE0E,MACA;AAdF,uBAAAF,UAAA;AACA;AAcE,uBAAKA,UAAUE,KAAKtB,UAAU,IAAIxB,uBAAuB8C,KAAK7C,IAAI;AAElE,uBAAK,UAAW,IAAIqB,wBAAwB;MAC1CpC,QAAQ4D,KAAKC;MACbxB,UAAUuB,KAAKvB;IACjB,CAAA;AAEA,SAAKzB,KAAKgD,KAAKhD;AAEf,SAAKkD,YAAY,KAAKlD,GAAGmD,GAAGH,KAAK7C,IAAI;AAGrC,SAAKd,SAAS,IAAIH,iBAAiB;MACjCE,QAAQ4D,KAAKI;MACb/D,QAAQ,OAAOZ,YAAY;AACzB,eAAO,IAAI4E,QAAQ,CAACC,SAASC,WAAW;AACtC,cAAI;AAEF,iBAAKL,UAAUM,KAAK/E,QAAQM,MAAMN,QAAQD,OAAO;AACjD8E,oBAAAA;UACF,SAASG,KAAK;AACZF,mBAAOE,GAAAA;UACT;QACF,CAAA;MACF;IACF,CAAA;AAEA,QAAIT,KAAKU,SAAS;AAChB,WAAKR,UAAUS,IAAI,OAAOC,QAAQC,SAAS;AACzC,cAAMnC,SAAS,mBAAKoB,UAAQlC,MAAM;UAAEkD,UAAUF,OAAOG;UAAIC,aAAa;QAAU,CAAA;AAEhF,YAAI,OAAOhB,KAAKU,YAAY,YAAY;AACtC,gBAAMV,KAAKU,QAAQE,QAAQC,MAAMnC,MAAAA;QACnC;MACF,CAAA;IACF;AAEA,QAAIsB,KAAKiB,WAAW;AAClB,WAAKf,UAAUS,IAAI,CAACC,QAAQC,SAAS;AACnC,cAAMnC,SAAS,mBAAKoB,UAAQlC,MAAM;UAAEkD,UAAUF,OAAOG;UAAIC,aAAa;QAAO,CAAA;AAE7E,cAAM,EAAEE,KAAI,IAAKN,OAAOO;AAExB,YAAI,EAAE,WAAWD,OAAO;AACtBxC,iBAAOnD,MAAM,UAAA;AACb,iBAAOqF,OAAOQ,WAAW,IAAI;QAC/B;AAEA,YAAIF,KAAKG,UAAUrB,KAAKiB,WAAW;AACjCvC,iBAAOnD,MAAM,eAAA;AACb,iBAAOqF,OAAOQ,WAAW,IAAI;QAC/B;AAEA1C,eAAOhB,KAAK,SAAA;AAEZmD,aAAAA;MACF,CAAA;IACF;AAEA,QAAIb,KAAKsB,UAAU;AACjB,WAAKpB,UAAUS,IAAI,OAAOC,QAAQC,SAAS;AACzC,cAAMnC,SAAS,mBAAKoB,UAAQlC,MAAM;UAAEkD,UAAUF,OAAOG;UAAIC,aAAa;QAAO,CAAA;AAE7E,YAAI,OAAOhB,KAAKsB,aAAa,YAAY;AACvC,gBAAMtB,KAAKsB,SAASV,QAAQC,MAAMnC,MAAAA;QACpC;MACF,CAAA;IACF;AAEA,SAAKwB,UAAUR,GAAG,cAAc,OAAOkB,WAAW;AAChD,YAAMlC,SAAS,mBAAKoB,UAAQlC,MAAM;QAAEkD,UAAUF,OAAOG;QAAIC,aAAa;MAAa,CAAA;AACnFtC,aAAOhB,KAAK,WAAA;AAEZ,yBAAK,UAAS2B,iBAAiBuB,QAAQlC,MAAAA;AAEvCkC,aAAOlB,GAAG,cAAc,OAAOX,QAAQwC,gBAAgB;AACrD7C,eAAOhB,KAAK,cAAc;UAAEqB;UAAQwC;QAAY,CAAA;AAEhD,YAAIvB,KAAKwB,cAAc;AACrB,gBAAMxB,KAAKwB,aAAaZ,QAAQ7B,QAAQwC,aAAa7C,MAAAA;QACvD;MACF,CAAA;AAEAkC,aAAOlB,GAAG,SAAS,OAAOnE,UAAU;AAClCmD,eAAOnD,MAAM,SAAS;UAAEA;QAAM,CAAA;AAE9B,YAAIyE,KAAKyB,SAAS;AAChB,gBAAMzB,KAAKyB,QAAQb,QAAQrF,OAAOmD,MAAAA;QACpC;MACF,CAAA;AAEA,UAAIsB,KAAK0B,cAAc;AACrB,cAAM1B,KAAK0B,aAAad,QAAQ,mBAAK,WAAU,KAAKvE,QAAQqC,MAAAA;MAC9D;IACF,CAAA;EACF;EAEAiD,eAAe;AACb,WAAO,KAAKzB,UAAUyB,aAAY;EACpC;AACF;AAnHE7B,WAAA;AACA;AAPWC;AAAN,IAAMA,eAAN","sourcesContent":["import { z } from \"zod\";\nimport { StructuredLogger } from \"./utils/structuredLogger\";\n\nexport class ZodSchemaParsedError extends Error {\n constructor(\n public error: z.ZodError,\n public payload: unknown\n ) {\n super(error.message);\n }\n}\n\nexport type ZodMessageValueSchema<TDiscriminatedUnion extends z.ZodDiscriminatedUnion<any, any>> =\n | z.ZodFirstPartySchemaTypes\n | TDiscriminatedUnion;\n\nexport interface ZodMessageCatalogSchema {\n [key: string]: ZodMessageValueSchema<any>;\n}\n\nexport type ZodMessageHandlers<TCatalogSchema extends ZodMessageCatalogSchema> = Partial<{\n [K in keyof TCatalogSchema]: (payload: z.infer<TCatalogSchema[K]>) => Promise<any>;\n}>;\n\nexport type ZodMessageHandlerOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n messages?: ZodMessageHandlers<TMessageCatalog>;\n logger?: StructuredLogger;\n};\n\nexport type MessageFromSchema<\n K extends keyof TMessageCatalog,\n TMessageCatalog extends ZodMessageCatalogSchema,\n> = {\n type: K;\n payload: z.input<TMessageCatalog[K]>;\n};\n\nexport type MessageFromCatalog<TMessageCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TMessageCatalog]: MessageFromSchema<K, TMessageCatalog>;\n}[keyof TMessageCatalog];\n\nexport const ZodMessageSchema = z.object({\n version: z.literal(\"v1\").default(\"v1\"),\n type: z.string(),\n payload: z.unknown(),\n});\n\nexport interface EventEmitterLike {\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport class ZodMessageHandler<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #handlers: ZodMessageHandlers<TMessageCatalog> | undefined;\n #logger: StructuredLogger | Console;\n\n constructor(options: ZodMessageHandlerOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#handlers = options.messages;\n this.#logger = options.logger ?? console;\n }\n\n public async handleMessage(message: unknown): Promise<\n | {\n success: true;\n data: unknown;\n }\n | {\n success: false;\n error: string;\n }\n > {\n const parsedMessage = this.parseMessage(message);\n\n if (!parsedMessage.success) {\n this.#logger.error(parsedMessage.error, { message });\n\n return {\n success: false,\n error: parsedMessage.error,\n };\n }\n\n if (!this.#handlers) {\n this.#logger.error(\"No handlers provided\", { message });\n\n return {\n success: false,\n error: \"No handlers provided\",\n };\n }\n\n const handler = this.#handlers[parsedMessage.data.type];\n\n if (!handler) {\n const error = `No handler for message type: ${String(parsedMessage.data.type)}`;\n\n this.#logger.error(error, { message });\n\n return {\n success: false,\n error,\n };\n }\n\n const ack = await handler(parsedMessage.data.payload);\n\n return {\n success: true,\n data: ack,\n };\n }\n\n public parseMessage(message: unknown):\n | {\n success: true;\n data: MessageFromCatalog<TMessageCatalog>;\n }\n | {\n success: false;\n error: string;\n } {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n return {\n success: false,\n error: `Failed to parse message: ${JSON.stringify(parsedMessage.error)}`,\n };\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n return {\n success: false,\n error: `Unknown message type: ${parsedMessage.data.type}`,\n };\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n return {\n success: false,\n error: `Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`,\n };\n }\n\n return {\n success: true,\n data: {\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n },\n };\n }\n\n public registerHandlers(emitter: EventEmitterLike, logger?: StructuredLogger) {\n const log = logger ?? console;\n\n if (!this.#handlers) {\n log.info(\"No handlers provided\");\n return;\n }\n\n for (const eventName of Object.keys(this.#schema)) {\n emitter.on(eventName, async (message: any, callback?: any): Promise<void> => {\n log.info(`handling ${eventName}`, {\n payload: message,\n hasCallback: !!callback,\n });\n\n let ack: Awaited<ReturnType<ZodMessageHandler<TMessageCatalog>[\"handleMessage\"]>>;\n\n // FIXME: this only works if the message doesn't have genuine payload prop\n if (\"payload\" in message) {\n ack = await this.handleMessage({ type: eventName, ...message });\n } else {\n // Handle messages not sent by ZodMessageSender\n const { version, ...payload } = message;\n ack = await this.handleMessage({ type: eventName, version, payload });\n }\n\n if (callback && typeof callback === \"function\") {\n if (!ack.success) {\n // We don't know the callback type, so we can't do anything else - not all callbacks may accept a success prop\n log.error(\"Failed to handle message, skipping callback\", { message, error: ack.error });\n return;\n }\n\n callback(ack.data);\n }\n });\n }\n }\n}\n\ntype ZodMessageSenderCallback<TMessageCatalog extends ZodMessageCatalogSchema> = (message: {\n type: keyof TMessageCatalog;\n payload: z.infer<TMessageCatalog[keyof TMessageCatalog]>;\n version: \"v1\";\n}) => Promise<void>;\n\nexport type ZodMessageSenderOptions<TMessageCatalog extends ZodMessageCatalogSchema> = {\n schema: TMessageCatalog;\n sender: ZodMessageSenderCallback<TMessageCatalog>;\n};\n\nexport class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {\n #schema: TMessageCatalog;\n #sender: ZodMessageSenderCallback<TMessageCatalog>;\n\n constructor(options: ZodMessageSenderOptions<TMessageCatalog>) {\n this.#schema = options.schema;\n this.#sender = options.sender;\n }\n\n public async send<K extends keyof TMessageCatalog>(\n type: K,\n payload: z.input<TMessageCatalog[K]>\n ) {\n const schema = this.#schema[type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${type as string}`);\n }\n\n const parsedPayload = schema.safeParse(payload);\n\n if (!parsedPayload.success) {\n throw new ZodSchemaParsedError(parsedPayload.error, payload);\n }\n\n try {\n await this.#sender({ type, payload, version: \"v1\" });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to send message\", error);\n }\n }\n\n public async forwardMessage(message: unknown) {\n const parsedMessage = ZodMessageSchema.safeParse(message);\n\n if (!parsedMessage.success) {\n throw new Error(`Failed to parse message: ${JSON.stringify(parsedMessage.error)}`);\n }\n\n const schema = this.#schema[parsedMessage.data.type];\n\n if (!schema) {\n throw new Error(`Unknown message type: ${parsedMessage.data.type}`);\n }\n\n const parsedPayload = schema.safeParse(parsedMessage.data.payload);\n\n if (!parsedPayload.success) {\n throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);\n }\n\n try {\n await this.#sender({\n type: parsedMessage.data.type,\n payload: parsedPayload.data,\n version: \"v1\",\n });\n } catch (error) {\n console.error(\"[ZodMessageSender] Failed to forward message\", error);\n }\n }\n}\n\nexport type MessageCatalogToSocketIoEvents<TCatalog extends ZodMessageCatalogSchema> = {\n [K in keyof TCatalog]: (message: z.infer<TCatalog[K]>) => void;\n};\n","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"]}
|