@zyraxon-ai/http-recorder 19.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/cassette.d.ts +36 -0
  4. package/dist/cassette.d.ts.map +1 -0
  5. package/dist/cassette.js +105 -0
  6. package/dist/cassette.js.map +1 -0
  7. package/dist/effect.d.ts +11 -0
  8. package/dist/effect.d.ts.map +1 -0
  9. package/dist/effect.js +18 -0
  10. package/dist/effect.js.map +1 -0
  11. package/dist/index.d.ts +18 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +5 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/internal-effect.d.ts +19 -0
  16. package/dist/internal-effect.d.ts.map +1 -0
  17. package/dist/internal-effect.js +105 -0
  18. package/dist/internal-effect.js.map +1 -0
  19. package/dist/internal.d.ts +9 -0
  20. package/dist/internal.d.ts.map +1 -0
  21. package/dist/internal.js +9 -0
  22. package/dist/internal.js.map +1 -0
  23. package/dist/matching.d.ts +14 -0
  24. package/dist/matching.d.ts.map +1 -0
  25. package/dist/matching.js +92 -0
  26. package/dist/matching.js.map +1 -0
  27. package/dist/recorder.d.ts +13 -0
  28. package/dist/recorder.d.ts.map +1 -0
  29. package/dist/recorder.js +33 -0
  30. package/dist/recorder.js.map +1 -0
  31. package/dist/redaction.d.ts +14 -0
  32. package/dist/redaction.d.ts.map +1 -0
  33. package/dist/redaction.js +100 -0
  34. package/dist/redaction.js.map +1 -0
  35. package/dist/redactor.d.ts +30 -0
  36. package/dist/redactor.d.ts.map +1 -0
  37. package/dist/redactor.js +87 -0
  38. package/dist/redactor.js.map +1 -0
  39. package/dist/schema.d.ts +330 -0
  40. package/dist/schema.d.ts.map +1 -0
  41. package/dist/schema.js +53 -0
  42. package/dist/schema.js.map +1 -0
  43. package/dist/socket.d.ts +16 -0
  44. package/dist/socket.d.ts.map +1 -0
  45. package/dist/socket.js +194 -0
  46. package/dist/socket.js.map +1 -0
  47. package/dist/types.d.ts +101 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/websocket.d.ts +29 -0
  52. package/dist/websocket.d.ts.map +1 -0
  53. package/dist/websocket.js +101 -0
  54. package/dist/websocket.js.map +1 -0
  55. package/package.json +47 -0
@@ -0,0 +1,330 @@
1
+ import { Schema } from "effect";
2
+ export type { CassetteMetadata, HttpInteraction, RequestSnapshot, ResponseSnapshot, WebSocketEvent, WebSocketInteraction, } from "./types.js";
3
+ export declare const RequestSnapshotSchema: Schema.Struct<{
4
+ readonly method: Schema.String;
5
+ readonly url: Schema.String;
6
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
7
+ readonly body: Schema.String;
8
+ }>;
9
+ export declare const ResponseSnapshotSchema: Schema.Struct<{
10
+ readonly status: Schema.Number;
11
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
12
+ readonly body: Schema.String;
13
+ readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["text", "base64"]>>;
14
+ }>;
15
+ export declare const CassetteMetadataSchema: Schema.$Record<Schema.String, Schema.Unknown>;
16
+ export declare const HttpInteractionSchema: Schema.Struct<{
17
+ readonly transport: Schema.tag<"http">;
18
+ readonly request: Schema.Struct<{
19
+ readonly method: Schema.String;
20
+ readonly url: Schema.String;
21
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
22
+ readonly body: Schema.String;
23
+ }>;
24
+ readonly response: Schema.Struct<{
25
+ readonly status: Schema.Number;
26
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
27
+ readonly body: Schema.String;
28
+ readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["text", "base64"]>>;
29
+ }>;
30
+ }>;
31
+ export declare const WebSocketEventSchema: Schema.Union<readonly [Schema.Struct<{
32
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
33
+ readonly kind: Schema.tag<"text">;
34
+ readonly body: Schema.String;
35
+ }>, Schema.Struct<{
36
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
37
+ readonly kind: Schema.tag<"binary">;
38
+ readonly body: Schema.String;
39
+ readonly bodyEncoding: Schema.Literal<"base64">;
40
+ }>]>;
41
+ export declare const WebSocketInteractionSchema: Schema.Struct<{
42
+ readonly transport: Schema.tag<"websocket">;
43
+ readonly open: Schema.Struct<{
44
+ readonly url: Schema.String;
45
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
46
+ }>;
47
+ readonly events: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
48
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
49
+ readonly kind: Schema.tag<"text">;
50
+ readonly body: Schema.String;
51
+ }>, Schema.Struct<{
52
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
53
+ readonly kind: Schema.tag<"binary">;
54
+ readonly body: Schema.String;
55
+ readonly bodyEncoding: Schema.Literal<"base64">;
56
+ }>]>>;
57
+ }>;
58
+ export declare const InteractionSchema: Schema.toTaggedUnion<"transport", readonly [Schema.Struct<{
59
+ readonly transport: Schema.tag<"http">;
60
+ readonly request: Schema.Struct<{
61
+ readonly method: Schema.String;
62
+ readonly url: Schema.String;
63
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
64
+ readonly body: Schema.String;
65
+ }>;
66
+ readonly response: Schema.Struct<{
67
+ readonly status: Schema.Number;
68
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
69
+ readonly body: Schema.String;
70
+ readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["text", "base64"]>>;
71
+ }>;
72
+ }>, Schema.Struct<{
73
+ readonly transport: Schema.tag<"websocket">;
74
+ readonly open: Schema.Struct<{
75
+ readonly url: Schema.String;
76
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
77
+ }>;
78
+ readonly events: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
79
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
80
+ readonly kind: Schema.tag<"text">;
81
+ readonly body: Schema.String;
82
+ }>, Schema.Struct<{
83
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
84
+ readonly kind: Schema.tag<"binary">;
85
+ readonly body: Schema.String;
86
+ readonly bodyEncoding: Schema.Literal<"base64">;
87
+ }>]>>;
88
+ }>]>;
89
+ export type Interaction = Schema.Schema.Type<typeof InteractionSchema>;
90
+ export declare const isHttpInteraction: (u: unknown) => u is {
91
+ readonly transport: "http";
92
+ readonly request: {
93
+ readonly method: string;
94
+ readonly url: string;
95
+ readonly headers: {
96
+ readonly [x: string]: string;
97
+ };
98
+ readonly body: string;
99
+ };
100
+ readonly response: {
101
+ readonly status: number;
102
+ readonly headers: {
103
+ readonly [x: string]: string;
104
+ };
105
+ readonly body: string;
106
+ readonly bodyEncoding?: "text" | "base64";
107
+ };
108
+ };
109
+ export declare const isWebSocketInteraction: (u: unknown) => u is {
110
+ readonly transport: "websocket";
111
+ readonly open: {
112
+ readonly url: string;
113
+ readonly headers: {
114
+ readonly [x: string]: string;
115
+ };
116
+ };
117
+ readonly events: readonly ({
118
+ readonly direction: "client" | "server";
119
+ readonly kind: "text";
120
+ readonly body: string;
121
+ } | {
122
+ readonly direction: "client" | "server";
123
+ readonly kind: "binary";
124
+ readonly body: string;
125
+ readonly bodyEncoding: "base64";
126
+ })[];
127
+ };
128
+ export declare const httpInteractions: (interactions: ReadonlyArray<Interaction>) => {
129
+ readonly transport: "http";
130
+ readonly request: {
131
+ readonly method: string;
132
+ readonly url: string;
133
+ readonly headers: {
134
+ readonly [x: string]: string;
135
+ };
136
+ readonly body: string;
137
+ };
138
+ readonly response: {
139
+ readonly status: number;
140
+ readonly headers: {
141
+ readonly [x: string]: string;
142
+ };
143
+ readonly body: string;
144
+ readonly bodyEncoding?: "text" | "base64";
145
+ };
146
+ }[];
147
+ export declare const webSocketInteractions: (interactions: ReadonlyArray<Interaction>) => {
148
+ readonly transport: "websocket";
149
+ readonly open: {
150
+ readonly url: string;
151
+ readonly headers: {
152
+ readonly [x: string]: string;
153
+ };
154
+ };
155
+ readonly events: readonly ({
156
+ readonly direction: "client" | "server";
157
+ readonly kind: "text";
158
+ readonly body: string;
159
+ } | {
160
+ readonly direction: "client" | "server";
161
+ readonly kind: "binary";
162
+ readonly body: string;
163
+ readonly bodyEncoding: "base64";
164
+ })[];
165
+ }[];
166
+ export declare const CassetteSchema: Schema.Struct<{
167
+ readonly version: Schema.Literal<1>;
168
+ readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
169
+ readonly interactions: Schema.$Array<Schema.toTaggedUnion<"transport", readonly [Schema.Struct<{
170
+ readonly transport: Schema.tag<"http">;
171
+ readonly request: Schema.Struct<{
172
+ readonly method: Schema.String;
173
+ readonly url: Schema.String;
174
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
175
+ readonly body: Schema.String;
176
+ }>;
177
+ readonly response: Schema.Struct<{
178
+ readonly status: Schema.Number;
179
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
180
+ readonly body: Schema.String;
181
+ readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["text", "base64"]>>;
182
+ }>;
183
+ }>, Schema.Struct<{
184
+ readonly transport: Schema.tag<"websocket">;
185
+ readonly open: Schema.Struct<{
186
+ readonly url: Schema.String;
187
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
188
+ }>;
189
+ readonly events: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
190
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
191
+ readonly kind: Schema.tag<"text">;
192
+ readonly body: Schema.String;
193
+ }>, Schema.Struct<{
194
+ readonly direction: Schema.Literals<readonly ["client", "server"]>;
195
+ readonly kind: Schema.tag<"binary">;
196
+ readonly body: Schema.String;
197
+ readonly bodyEncoding: Schema.Literal<"base64">;
198
+ }>]>>;
199
+ }>]>>;
200
+ }>;
201
+ export type Cassette = Schema.Schema.Type<typeof CassetteSchema>;
202
+ export declare const decodeCassette: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => {
203
+ readonly version: 1;
204
+ readonly interactions: readonly ({
205
+ readonly transport: "http";
206
+ readonly request: {
207
+ readonly method: string;
208
+ readonly url: string;
209
+ readonly headers: {
210
+ readonly [x: string]: string;
211
+ };
212
+ readonly body: string;
213
+ };
214
+ readonly response: {
215
+ readonly status: number;
216
+ readonly headers: {
217
+ readonly [x: string]: string;
218
+ };
219
+ readonly body: string;
220
+ readonly bodyEncoding?: "text" | "base64";
221
+ };
222
+ } | {
223
+ readonly transport: "websocket";
224
+ readonly open: {
225
+ readonly url: string;
226
+ readonly headers: {
227
+ readonly [x: string]: string;
228
+ };
229
+ };
230
+ readonly events: readonly ({
231
+ readonly direction: "client" | "server";
232
+ readonly kind: "text";
233
+ readonly body: string;
234
+ } | {
235
+ readonly direction: "client" | "server";
236
+ readonly kind: "binary";
237
+ readonly body: string;
238
+ readonly bodyEncoding: "base64";
239
+ })[];
240
+ })[];
241
+ readonly metadata?: {
242
+ readonly [x: string]: unknown;
243
+ };
244
+ };
245
+ export declare const encodeCassette: (input: {
246
+ readonly version: 1;
247
+ readonly interactions: readonly ({
248
+ readonly transport: "http";
249
+ readonly request: {
250
+ readonly method: string;
251
+ readonly url: string;
252
+ readonly headers: {
253
+ readonly [x: string]: string;
254
+ };
255
+ readonly body: string;
256
+ };
257
+ readonly response: {
258
+ readonly status: number;
259
+ readonly headers: {
260
+ readonly [x: string]: string;
261
+ };
262
+ readonly body: string;
263
+ readonly bodyEncoding?: "text" | "base64";
264
+ };
265
+ } | {
266
+ readonly transport: "websocket";
267
+ readonly open: {
268
+ readonly url: string;
269
+ readonly headers: {
270
+ readonly [x: string]: string;
271
+ };
272
+ };
273
+ readonly events: readonly ({
274
+ readonly direction: "client" | "server";
275
+ readonly kind: "text";
276
+ readonly body: string;
277
+ } | {
278
+ readonly direction: "client" | "server";
279
+ readonly kind: "binary";
280
+ readonly body: string;
281
+ readonly bodyEncoding: "base64";
282
+ })[];
283
+ })[];
284
+ readonly metadata?: {
285
+ readonly [x: string]: unknown;
286
+ };
287
+ }, options?: import("effect/SchemaAST").ParseOptions) => {
288
+ readonly version: 1;
289
+ readonly interactions: readonly ({
290
+ readonly transport: "http";
291
+ readonly request: {
292
+ readonly method: string;
293
+ readonly url: string;
294
+ readonly headers: {
295
+ readonly [x: string]: string;
296
+ };
297
+ readonly body: string;
298
+ };
299
+ readonly response: {
300
+ readonly status: number;
301
+ readonly headers: {
302
+ readonly [x: string]: string;
303
+ };
304
+ readonly body: string;
305
+ readonly bodyEncoding?: "text" | "base64";
306
+ };
307
+ } | {
308
+ readonly transport: "websocket";
309
+ readonly open: {
310
+ readonly url: string;
311
+ readonly headers: {
312
+ readonly [x: string]: string;
313
+ };
314
+ };
315
+ readonly events: readonly ({
316
+ readonly direction: "client" | "server";
317
+ readonly kind: "text";
318
+ readonly body: string;
319
+ } | {
320
+ readonly direction: "client" | "server";
321
+ readonly kind: "binary";
322
+ readonly body: string;
323
+ readonly bodyEncoding: "base64";
324
+ })[];
325
+ })[];
326
+ readonly metadata?: {
327
+ readonly [x: string]: unknown;
328
+ };
329
+ };
330
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAU/B,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAA;AAEnB,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;EAKjC,CAAA;AAEF,eAAO,MAAM,sBAAsB,+CAA+C,CAAA;AAElF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;EAIhC,CAAA;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;IAY/B,CAAA;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;EAOrC,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE7B,CAAA;AACD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAEtE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAAgC,CAAA;AAE9D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;CAAqC,CAAA;AAExE,eAAO,MAAM,gBAAgB,GAAI,cAAc,aAAa,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;GAA2C,CAAA;AAEpH,eAAO,MAAM,qBAAqB,GAAI,cAAc,aAAa,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;GACjC,CAAA;AAE7C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAIzB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,cAAc,CAAC,CAAA;AAEhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAA2C,CAAA;AACtE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAoC,CAAA"}
package/dist/schema.js ADDED
@@ -0,0 +1,53 @@
1
+ import { Schema } from "effect";
2
+ export const RequestSnapshotSchema = Schema.Struct({
3
+ method: Schema.String,
4
+ url: Schema.String,
5
+ headers: Schema.Record(Schema.String, Schema.String),
6
+ body: Schema.String,
7
+ });
8
+ export const ResponseSnapshotSchema = Schema.Struct({
9
+ status: Schema.Number,
10
+ headers: Schema.Record(Schema.String, Schema.String),
11
+ body: Schema.String,
12
+ bodyEncoding: Schema.optional(Schema.Literals(["text", "base64"])),
13
+ });
14
+ export const CassetteMetadataSchema = Schema.Record(Schema.String, Schema.Unknown);
15
+ export const HttpInteractionSchema = Schema.Struct({
16
+ transport: Schema.tag("http"),
17
+ request: RequestSnapshotSchema,
18
+ response: ResponseSnapshotSchema,
19
+ });
20
+ export const WebSocketEventSchema = Schema.Union([
21
+ Schema.Struct({
22
+ direction: Schema.Literals(["client", "server"]),
23
+ kind: Schema.tag("text"),
24
+ body: Schema.String,
25
+ }),
26
+ Schema.Struct({
27
+ direction: Schema.Literals(["client", "server"]),
28
+ kind: Schema.tag("binary"),
29
+ body: Schema.String,
30
+ bodyEncoding: Schema.Literal("base64"),
31
+ }),
32
+ ]);
33
+ export const WebSocketInteractionSchema = Schema.Struct({
34
+ transport: Schema.tag("websocket"),
35
+ open: Schema.Struct({
36
+ url: Schema.String,
37
+ headers: Schema.Record(Schema.String, Schema.String),
38
+ }),
39
+ events: Schema.Array(WebSocketEventSchema),
40
+ });
41
+ export const InteractionSchema = Schema.Union([HttpInteractionSchema, WebSocketInteractionSchema]).pipe(Schema.toTaggedUnion("transport"));
42
+ export const isHttpInteraction = InteractionSchema.guards.http;
43
+ export const isWebSocketInteraction = InteractionSchema.guards.websocket;
44
+ export const httpInteractions = (interactions) => interactions.filter(isHttpInteraction);
45
+ export const webSocketInteractions = (interactions) => interactions.filter(isWebSocketInteraction);
46
+ export const CassetteSchema = Schema.Struct({
47
+ version: Schema.Literal(1),
48
+ metadata: Schema.optional(CassetteMetadataSchema),
49
+ interactions: Schema.Array(InteractionSchema),
50
+ });
51
+ export const decodeCassette = Schema.decodeUnknownSync(CassetteSchema);
52
+ export const encodeCassette = Schema.encodeSync(CassetteSchema);
53
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Layer } from "effect";
2
+ import { Socket } from "effect/unstable/socket";
3
+ import type { RecorderOptions, WebSocketRecorderOptions, WebSocketRequest } from "./types.js";
4
+ /**
5
+ * Wraps a provided `Socket.Socket` with cassette recording and replay.
6
+ *
7
+ * Supply the ordinary URL-bound Effect socket layer beneath this decorator.
8
+ * The cassette name identifies the connection; recorder configuration does not
9
+ * duplicate the transport URL.
10
+ */
11
+ export declare const socket: (name: string, options?: RecorderOptions) => Layer.Layer<Socket.Socket, never, Socket.Socket>;
12
+ /** @internal */
13
+ export declare const socketLayer: (name: string, request: WebSocketRequest, options: WebSocketRecorderOptions & {
14
+ readonly mode: "record" | "replay";
15
+ }) => Layer.Layer<Socket.Socket, never, Socket.Socket>;
16
+ //# sourceMappingURL=socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,EAAyB,MAAM,QAAQ,CAAA;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAM/C,OAAO,KAAK,EACV,eAAe,EAGf,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,YAAY,CAAA;AA8RnB;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,EAAE,UAAS,eAAoB,KAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CACJ,CAAA;AAEhH,gBAAgB;AAChB,eAAO,MAAM,WAAW,GACtB,MAAM,MAAM,EACZ,SAAS,gBAAgB,EACzB,SAAS,wBAAwB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,KACzE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAC8B,CAAA"}
package/dist/socket.js ADDED
@@ -0,0 +1,194 @@
1
+ import { NodeFileSystem } from "@effect/platform-node";
2
+ import { Deferred, Effect, Exit, FiberSet, Layer, Ref, Semaphore } from "effect";
3
+ import { Socket } from "effect/unstable/socket";
4
+ import * as CassetteService from "./cassette.js";
5
+ import { canonicalizeJson, decodeJson, safeText } from "./matching.js";
6
+ import { makeReplayState, resolveAutoMode } from "./recorder.js";
7
+ import { make } from "./redactor.js";
8
+ import { webSocketInteractions } from "./schema.js";
9
+ const encodeEvent = (direction, message) => typeof message === "string"
10
+ ? { direction, kind: "text", body: message }
11
+ : { direction, kind: "binary", body: Buffer.from(message).toString("base64"), bodyEncoding: "base64" };
12
+ const decodeEvent = (event) => event.kind === "text" ? event.body : new Uint8Array(Buffer.from(event.body, "base64"));
13
+ const redactEvent = (event, redactor) => {
14
+ if (event.kind === "binary")
15
+ return event;
16
+ const body = event.direction === "client"
17
+ ? redactor.request({ method: "WEBSOCKET", url: "", headers: {}, body: event.body }).body
18
+ : redactor.response({ status: 101, headers: {}, body: event.body }).body;
19
+ return { ...event, body };
20
+ };
21
+ const comparable = (event, asJson) => {
22
+ if (!asJson || event.kind === "binary")
23
+ return JSON.stringify(canonicalizeJson(event));
24
+ const decoded = decodeJson(event.body);
25
+ return JSON.stringify(canonicalizeJson({
26
+ ...event,
27
+ body: decoded._tag === "None" ? event.body : canonicalizeJson(decoded.value),
28
+ }));
29
+ };
30
+ const assertEvent = (actual, expected, index, asJson) => Effect.sync(() => {
31
+ if (expected && comparable(actual, asJson) === comparable(expected, asJson))
32
+ return;
33
+ throw new Error(`WebSocket event ${index + 1}: expected ${safeText(expected)}, received ${safeText(actual)}`);
34
+ });
35
+ const runHandler = (handler, value) => Effect.suspend(() => {
36
+ const result = handler(value);
37
+ return Effect.isEffect(result) ? Effect.asVoid(result) : Effect.void;
38
+ });
39
+ const runReplay = (state, handler, decode, onOpen) => Effect.scoped(Effect.gen(function* () {
40
+ const handlers = yield* FiberSet.make();
41
+ const run = yield* FiberSet.runtime(handlers)();
42
+ if (onOpen)
43
+ yield* onOpen;
44
+ const drive = Effect.gen(function* () {
45
+ while (true) {
46
+ const current = yield* Ref.get(state.progress);
47
+ const event = state.interaction.events[current.position];
48
+ if (!event)
49
+ return;
50
+ if (yield* Ref.get(state.closed))
51
+ return yield* Effect.die(new Error(`WebSocket closed with unconsumed events: used ${current.position} of ${state.interaction.events.length}`));
52
+ if (event.direction === "server") {
53
+ yield* Ref.set(state.progress, {
54
+ position: current.position + 1,
55
+ changed: yield* Deferred.make(),
56
+ });
57
+ run(runHandler(handler, decode(event)));
58
+ continue;
59
+ }
60
+ yield* Deferred.await(current.changed);
61
+ }
62
+ });
63
+ yield* drive.pipe(Effect.raceFirst(FiberSet.join(handlers)));
64
+ yield* FiberSet.awaitEmpty(handlers).pipe(Effect.raceFirst(FiberSet.join(handlers)));
65
+ }));
66
+ const openSnapshot = (request, redactor) => {
67
+ const snapshot = redactor.request({ method: "GET", url: request.url, headers: request.headers ?? {}, body: "" });
68
+ return { url: snapshot.url, headers: snapshot.headers };
69
+ };
70
+ const makeRecordingSocket = (upstream, cassette, name, request, options, redactor) => Effect.gen(function* () {
71
+ const active = yield* Ref.make(undefined);
72
+ const writeLock = yield* Semaphore.make(1);
73
+ return Socket.make({
74
+ runRaw: (handler, runOptions) => Effect.gen(function* () {
75
+ const state = {
76
+ events: [],
77
+ eventLock: yield* Semaphore.make(1),
78
+ accepting: yield* Ref.make(true),
79
+ opened: false,
80
+ valid: true,
81
+ };
82
+ const occupied = yield* Ref.modify(active, (current) => [current !== undefined, current ?? state]);
83
+ if (occupied)
84
+ return yield* Effect.die("Concurrent runs of a recorded WebSocket are not supported");
85
+ yield* upstream
86
+ .runRaw((message) => {
87
+ if (!Ref.getUnsafe(state.accepting))
88
+ throw new Error("WebSocket received a frame after closing");
89
+ state.events.push(redactEvent(encodeEvent("server", message), redactor));
90
+ return handler(message);
91
+ }, {
92
+ ...runOptions,
93
+ onOpen: Effect.gen(function* () {
94
+ state.opened = true;
95
+ if (runOptions?.onOpen)
96
+ yield* runOptions.onOpen;
97
+ }),
98
+ })
99
+ .pipe(Effect.onExit((exit) => writeLock.withPermit(state.eventLock.withPermit(Effect.gen(function* () {
100
+ yield* Ref.set(state.accepting, false);
101
+ yield* Ref.set(active, undefined);
102
+ if (!Exit.isSuccess(exit) || !state.opened || !state.valid)
103
+ return;
104
+ yield* cassette
105
+ .append(name, {
106
+ transport: "websocket",
107
+ open: openSnapshot(request, redactor),
108
+ events: [...state.events],
109
+ }, options.metadata)
110
+ .pipe(Effect.orDie);
111
+ })))));
112
+ }),
113
+ writer: upstream.writer.pipe(Effect.map((write) => (message) => writeLock.withPermit(Effect.gen(function* () {
114
+ if (Socket.isCloseEvent(message))
115
+ return yield* write(message);
116
+ const state = yield* Ref.get(active);
117
+ if (!state || !(yield* Ref.get(state.accepting)))
118
+ return yield* Effect.die("WebSocket writer used without an active socket run");
119
+ const event = redactEvent(encodeEvent("client", message), redactor);
120
+ yield* state.eventLock.withPermit(Effect.sync(() => state.events.push(event)));
121
+ return yield* write(message).pipe(Effect.onError(() => Effect.sync(() => (state.valid = false))));
122
+ })))),
123
+ });
124
+ });
125
+ const makeReplaySocket = (cassette, name, request, options, redactor) => Effect.gen(function* () {
126
+ const replay = yield* makeReplayState(cassette, name, webSocketInteractions);
127
+ const active = yield* Ref.make(undefined);
128
+ return Socket.make({
129
+ runRaw: (handler, runOptions) => Effect.gen(function* () {
130
+ const claimed = yield* replay
131
+ .claim((interaction, index) => Effect.sync(() => {
132
+ const incoming = openSnapshot(request, redactor);
133
+ if (interaction &&
134
+ JSON.stringify(canonicalizeJson(incoming)) === JSON.stringify(canonicalizeJson(interaction.open)))
135
+ return;
136
+ throw new Error(`WebSocket open ${index + 1}: expected ${safeText(interaction?.open)}, received ${safeText(incoming)}`);
137
+ }))
138
+ .pipe(Effect.orDie);
139
+ const progress = yield* Ref.make({ position: 0, changed: yield* Deferred.make() });
140
+ const writeLock = yield* Semaphore.make(1);
141
+ const state = {
142
+ interaction: claimed.interaction,
143
+ progress,
144
+ writeLock,
145
+ closed: yield* Ref.make(false),
146
+ };
147
+ const occupied = yield* Ref.modify(active, (current) => [current !== undefined, current ?? state]);
148
+ if (occupied)
149
+ return yield* Effect.die("Concurrent runs of a replayed WebSocket are not supported");
150
+ yield* runReplay(state, handler, decodeEvent, runOptions?.onOpen).pipe(Effect.ensuring(Ref.set(active, undefined)));
151
+ }),
152
+ writer: Effect.succeed((message) => {
153
+ return Ref.get(active).pipe(Effect.flatMap((state) => state
154
+ ? state.writeLock.withPermit(Effect.gen(function* () {
155
+ const current = yield* Ref.get(state.progress);
156
+ if (Socket.isCloseEvent(message)) {
157
+ yield* Ref.set(state.closed, true);
158
+ yield* Deferred.succeed(current.changed, undefined);
159
+ if (current.position === state.interaction.events.length)
160
+ return;
161
+ return yield* Effect.die(new Error(`WebSocket closed with unconsumed events: used ${current.position} of ${state.interaction.events.length}`));
162
+ }
163
+ const actual = redactEvent(encodeEvent("client", message), redactor);
164
+ yield* assertEvent(actual, state.interaction.events[current.position], current.position, options.compareClientMessagesAsJson === true);
165
+ yield* Ref.set(state.progress, {
166
+ position: current.position + 1,
167
+ changed: yield* Deferred.make(),
168
+ });
169
+ yield* Deferred.succeed(current.changed, undefined);
170
+ }))
171
+ : Effect.die("WebSocket writer used without an active socket run")));
172
+ }),
173
+ });
174
+ });
175
+ const recordingLayer = (name, request, options, forcedMode) => Layer.effect(Socket.Socket, Effect.gen(function* () {
176
+ const upstream = yield* Socket.Socket;
177
+ const cassette = yield* CassetteService.Service;
178
+ const redactor = make(options.redact);
179
+ if ((forcedMode ?? (yield* resolveAutoMode(cassette, name))) === "record")
180
+ return yield* makeRecordingSocket(upstream, cassette, name, request, options, redactor);
181
+ return yield* makeReplaySocket(cassette, name, request, options, redactor);
182
+ }));
183
+ /**
184
+ * Wraps a provided `Socket.Socket` with cassette recording and replay.
185
+ *
186
+ * Supply the ordinary URL-bound Effect socket layer beneath this decorator.
187
+ * The cassette name identifies the connection; recorder configuration does not
188
+ * duplicate the transport URL.
189
+ */
190
+ export const socket = (name, options = {}) => provideCassette(recordingLayer(name, { url: "" }, { ...options, compareClientMessagesAsJson: true }), options);
191
+ /** @internal */
192
+ export const socketLayer = (name, request, options) => provideCassette(recordingLayer(name, request, options, options.mode), options);
193
+ const provideCassette = (layer, options) => layer.pipe(Layer.provide(CassetteService.fileSystem({ directory: options.directory })), Layer.provide(NodeFileSystem.layer));
194
+ //# sourceMappingURL=socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAS,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,KAAK,eAAe,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAAE,IAAI,EAAiB,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA0BnD,MAAM,WAAW,GAAG,CAAC,SAA8B,EAAE,OAAc,EAAkB,EAAE,CACrF,OAAO,OAAO,KAAK,QAAQ;IACzB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;IAC5C,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA;AAE1G,MAAM,WAAW,GAAG,CAAC,KAAqB,EAAS,EAAE,CACnD,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;AAExF,MAAM,WAAW,GAAG,CAAC,KAAqB,EAAE,QAAkB,EAAkB,EAAE;IAChF,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACzC,MAAM,IAAI,GACR,KAAK,CAAC,SAAS,KAAK,QAAQ;QAC1B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACxF,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAA;IAC5E,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,KAAqB,EAAE,MAAe,EAAE,EAAE;IAC5D,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAA;IACtF,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACtC,OAAO,IAAI,CAAC,SAAS,CACnB,gBAAgB,CAAC;QACf,GAAG,KAAK;QACR,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC;KAC7E,CAAC,CACH,CAAA;AACH,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,MAAsB,EAAE,QAAoC,EAAE,KAAa,EAAE,MAAe,EAAE,EAAE,CACnH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;IACf,IAAI,QAAQ,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAE,OAAM;IACnF,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,GAAG,CAAC,cAAc,QAAQ,CAAC,QAAQ,CAAC,cAAc,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAC/G,CAAC,CAAC,CAAA;AAEJ,MAAM,UAAU,GAAG,CAAU,OAA0D,EAAE,KAAQ,EAAE,EAAE,CACnG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;IAClB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;AACtE,CAAC,CAAC,CAAA;AAEJ,MAAM,SAAS,GAAG,CAChB,KAAmB,EACnB,OAA0D,EAC1D,MAAoC,EACpC,MAAuC,EACvC,EAAE,CACF,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAc,CAAA;IACnD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAK,CAAA;IAClD,IAAI,MAAM;QAAE,KAAK,CAAC,CAAC,MAAM,CAAA;IAEzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAChC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YACxD,IAAI,CAAC,KAAK;gBAAE,OAAM;YAClB,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;gBAC9B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CACtB,IAAI,KAAK,CACP,iDAAiD,OAAO,CAAC,QAAQ,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAC1G,CACF,CAAA;YACH,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBACjC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;oBAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,CAAC;oBAC9B,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ;iBACtC,CAAC,CAAA;gBACF,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBACvC,SAAQ;YACV,CAAC;YACD,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACxC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC5D,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC,CAAC,CACH,CAAA;AAEH,MAAM,YAAY,GAAG,CAAC,OAAyB,EAAE,QAAkB,EAAE,EAAE;IACrE,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;IAChH,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAA;AACzD,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG,CAC1B,QAAuB,EACvB,QAAmC,EACnC,IAAY,EACZ,OAAyB,EACzB,OAAiC,EACjC,QAAkB,EAClB,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAA8B,SAAS,CAAC,CAAA;IACtE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAE1C,OAAO,MAAM,CAAC,IAAI,CAAC;QACjB,MAAM,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,CAC9B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,KAAK,GAAoB;gBAC7B,MAAM,EAAE,EAAE;gBACV,SAAS,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;gBACnC,SAAS,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAChC,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,IAAI;aACZ,CAAA;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAA;YAClG,IAAI,QAAQ;gBAAE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAA;YACnG,KAAK,CAAC,CAAC,QAAQ;iBACZ,MAAM,CACL,CAAC,OAAO,EAAE,EAAE;gBACV,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;gBAChG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;gBACxE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAA;YACzB,CAAC,EACD;gBACE,GAAG,UAAU;gBACb,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAC1B,KAAK,CAAC,MAAM,GAAG,IAAI,CAAA;oBACnB,IAAI,UAAU,EAAE,MAAM;wBAAE,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAA;gBAClD,CAAC,CAAC;aACH,CACF;iBACA,IAAI,CACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,SAAS,CAAC,UAAU,CAClB,KAAK,CAAC,SAAS,CAAC,UAAU,CACxB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;gBACtC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;gBACjC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK;oBAAE,OAAM;gBAClE,KAAK,CAAC,CAAC,QAAQ;qBACZ,MAAM,CACL,IAAI,EACJ;oBACE,SAAS,EAAE,WAAW;oBACtB,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC;oBACrC,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;iBAC1B,EACD,OAAO,CAAC,QAAQ,CACjB;qBACA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACvB,CAAC,CAAC,CACH,CACF,CACF,CACF,CAAA;QACL,CAAC,CAAC;QACJ,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAC1B,MAAM,CAAC,GAAG,CACR,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CACrB,SAAS,CAAC,UAAU,CAClB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC;gBAAE,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAC9C,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAA;YAChF,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAA;YACnE,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YAC9E,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACnG,CAAC,CAAC,CACH,CACJ,CACF;KACF,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEJ,MAAM,gBAAgB,GAAG,CACvB,QAAmC,EACnC,IAAY,EACZ,OAAyB,EACzB,OAAiC,EACjC,QAAkB,EACgC,EAAE,CACpD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,EAAE,qBAAqB,CAAC,CAAA;IAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAA2B,SAAS,CAAC,CAAA;IAEnE,OAAO,MAAM,CAAC,IAAI,CAAC;QACjB,MAAM,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,CAC9B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM;iBAC1B,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;gBACf,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;gBAChD,IACE,WAAW;oBACX,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;oBAEjG,OAAM;gBACR,MAAM,IAAI,KAAK,CACb,kBAAkB,KAAK,GAAG,CAAC,cAAc,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,QAAQ,CAAC,QAAQ,CAAC,EAAE,CACvG,CAAA;YACH,CAAC,CAAC,CACH;iBACA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,EAAE,CAAC,CAAA;YACxF,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC1C,MAAM,KAAK,GAAG;gBACZ,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ;gBACR,SAAS;gBACT,MAAM,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;aAC/B,CAAA;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAA;YAClG,IAAI,QAAQ;gBAAE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAA;YACnG,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,IAAI,CACpE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAC5C,CAAA;QACH,CAAC,CAAC;QACJ,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjC,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CACzB,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,KAAK;gBACH,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CACxB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;oBAC9C,IAAI,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;wBACjC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;wBAClC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;wBACnD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM;4BAAE,OAAM;wBAChE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CACtB,IAAI,KAAK,CACP,iDAAiD,OAAO,CAAC,QAAQ,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAC1G,CACF,CAAA;oBACH,CAAC;oBACD,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAA;oBACpE,KAAK,CAAC,CAAC,WAAW,CAChB,MAAM,EACN,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC1C,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,2BAA2B,KAAK,IAAI,CAC7C,CAAA;oBACD,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;wBAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,CAAC;wBAC9B,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ;qBACtC,CAAC,CAAA;oBACF,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;gBACrD,CAAC,CAAC,CACH;gBACH,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,oDAAoD,CAAC,CACrE,CACF,CAAA;QACH,CAAC,CAAC;KACH,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CACrB,IAAY,EACZ,OAAyB,EACzB,OAAiC,EACjC,UAAgC,EAC4C,EAAE,CAC9E,KAAK,CAAC,MAAM,CACV,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,OAAO,CAAA;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACrC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;QACvE,OAAO,KAAK,CAAC,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IACzF,OAAO,KAAK,CAAC,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;AAC5E,CAAC,CAAC,CACH,CAAA;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,UAA2B,EAAE,EAAoD,EAAE,CACtH,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,2BAA2B,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;AAEhH,gBAAgB;AAChB,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,IAAY,EACZ,OAAyB,EACzB,OAA0E,EACxB,EAAE,CACpD,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;AAEhF,MAAM,eAAe,GAAG,CACtB,KAAiF,EACjF,OAAiC,EACjC,EAAE,CACF,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAC3E,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CACpC,CAAA"}