@streamotter/client 0.1.0-rc.1

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.
@@ -0,0 +1,424 @@
1
+ import { asStreamOtterError, compareRevisions, EVENTS, streamError, StreamOtterError, UNSUBSCRIBE_TIMEOUT_MS } from "@streamotter/contracts";
2
+ import { WaiterSet } from "./waiters.js";
3
+ /** SDK-detected synchronization failures tolerated per incident before resync-required. */
4
+ const LOCAL_SYNC_ATTEMPTS = 3;
5
+ function isThenable(value) {
6
+ return (typeof value === "object" || typeof value === "function") && value !== null
7
+ && typeof value.then === "function";
8
+ }
9
+ /**
10
+ * Client side of one subscription. Accepts an epoch only after its ordered
11
+ * `synchronizing` frame, validates sequence and revision order, confirms SDK
12
+ * receipt after synchronous listener dispatch, and never reports `live` for a
13
+ * disconnected or superseded view.
14
+ */
15
+ export class ClientSubscription {
16
+ id;
17
+ channel;
18
+ channelVersion;
19
+ params;
20
+ #owner;
21
+ #listeners = {
22
+ data: new Set(),
23
+ state: new Set(),
24
+ error: new Set()
25
+ };
26
+ #waiters = new WaiterSet();
27
+ #state = "idle";
28
+ #reason;
29
+ #terminal = false;
30
+ #attached = null;
31
+ #serverKnows = false;
32
+ #epoch = null;
33
+ /** Set after we ask the gateway to replace `#epoch`; old-epoch progress is ignored. */
34
+ #replacing = null;
35
+ #awaitingEpoch = true;
36
+ #expectedSequence = 1;
37
+ #epochRevision = null;
38
+ #lastRevision = null;
39
+ #localFailures = 0;
40
+ #lastError = null;
41
+ #unsubscribing = null;
42
+ #retryTimer = null;
43
+ constructor(owner, channel, channelVersion, params) {
44
+ this.#owner = owner;
45
+ this.id = owner.randomId();
46
+ this.channel = channel;
47
+ this.channelVersion = channelVersion;
48
+ this.params = params;
49
+ // Start in the next microtask so synchronously attached listeners miss nothing.
50
+ queueMicrotask(() => {
51
+ if (!this.#terminal)
52
+ this.#owner.register(this);
53
+ });
54
+ }
55
+ get state() {
56
+ return this.#state;
57
+ }
58
+ get active() {
59
+ return !this.#terminal;
60
+ }
61
+ on(event, listener) {
62
+ const set = this.#listeners[event];
63
+ if (set === undefined || typeof listener !== "function") {
64
+ throw new StreamOtterError("INVALID_REQUEST", { message: "on() accepts \"data\", \"state\", or \"error\" with a function." });
65
+ }
66
+ set.add(listener);
67
+ return () => { set.delete(listener); };
68
+ }
69
+ ready(options) {
70
+ if (this.#state === "live")
71
+ return Promise.resolve();
72
+ const blocked = this.#blockedError();
73
+ if (blocked !== null)
74
+ return Promise.reject(asStreamOtterError(blocked));
75
+ return this.#waiters.wait(options);
76
+ }
77
+ resync(options) {
78
+ const blocked = this.#blockedError(true);
79
+ if (blocked !== null)
80
+ return Promise.reject(asStreamOtterError(blocked));
81
+ const wait = this.#waiters.wait(options);
82
+ this.#localFailures = 0;
83
+ this.#requestFreshSynchronization();
84
+ return wait;
85
+ }
86
+ unsubscribe() {
87
+ if (this.#unsubscribing !== null)
88
+ return this.#unsubscribing;
89
+ const connection = this.#attached;
90
+ const serverKnows = this.#serverKnows;
91
+ this.#terminate("closed", undefined, new StreamOtterError("CANCELLED", { message: "The subscription was unsubscribed." }));
92
+ this.#unsubscribing = serverKnows && connection !== null && connection.connected
93
+ ? this.#sendUnsubscribe(connection)
94
+ : Promise.resolve();
95
+ return this.#unsubscribing;
96
+ }
97
+ // --- called by the client ----------------------------------------------------------
98
+ /** Subscribes on a freshly authenticated connection. */
99
+ attach(connection) {
100
+ if (this.#terminal)
101
+ return;
102
+ this.#clearRetry();
103
+ this.#attached = connection;
104
+ this.#serverKnows = false;
105
+ this.#epoch = null;
106
+ this.#replacing = null;
107
+ this.#awaitingEpoch = true;
108
+ this.#setState("authorizing");
109
+ void this.#subscribe(connection);
110
+ }
111
+ /** The transport was lost; the view is stale until a new synchronization completes. */
112
+ detach(reason) {
113
+ this.#clearRetry();
114
+ this.#attached = null;
115
+ this.#serverKnows = false;
116
+ this.#awaitingEpoch = true;
117
+ this.#replacing = null;
118
+ if (this.#terminal || this.#state === "resync-required")
119
+ return;
120
+ this.#setState("stale", reason);
121
+ }
122
+ /** Authentication was rejected; waiting for an explicit reconnect(). */
123
+ authRequired(error) {
124
+ this.detach("UNAUTHENTICATED");
125
+ if (!this.#terminal)
126
+ this.#waiters.rejectAll(error);
127
+ }
128
+ /** Terminates without contacting the server (client close or identity change). */
129
+ terminateLocally(state, error, emit) {
130
+ if (this.#terminal)
131
+ return;
132
+ if (emit)
133
+ this.#emitError(error);
134
+ this.#terminate(state, error.code, error);
135
+ }
136
+ handleState(connection, frame) {
137
+ if (this.#terminal || connection !== this.#attached)
138
+ return;
139
+ // A frame proves the gateway holds this subscription, even if its acknowledgement
140
+ // continuation has not run yet (both can arrive in one socket read).
141
+ this.#serverKnows = true;
142
+ if (frame.state === "synchronizing") {
143
+ if (frame.epoch === this.#epoch && !this.#awaitingEpoch)
144
+ return;
145
+ this.#epoch = frame.epoch;
146
+ this.#replacing = null;
147
+ this.#awaitingEpoch = false;
148
+ this.#expectedSequence = 1;
149
+ this.#epochRevision = null;
150
+ this.#setState("synchronizing");
151
+ return;
152
+ }
153
+ if (frame.epoch !== (this.#epoch ?? ""))
154
+ return;
155
+ if (this.#replacing !== null && frame.epoch === this.#replacing
156
+ && (frame.state === "live" || frame.state === "resync-required")) {
157
+ return; // Progress of the epoch we asked the gateway to replace.
158
+ }
159
+ if (frame.state === "live" && this.#awaitingEpoch)
160
+ return;
161
+ switch (frame.state) {
162
+ case "failed":
163
+ this.#serverKnows = false;
164
+ this.#terminate("failed", frame.reason, this.#lastError ?? streamError(frame.reason ?? "INTERNAL"));
165
+ return;
166
+ case "closed":
167
+ this.#serverKnows = false;
168
+ this.#terminate("closed", frame.reason, this.#lastError ?? streamError(frame.reason ?? "CANCELLED"));
169
+ return;
170
+ case "resync-required":
171
+ this.#setState("resync-required", frame.reason ?? "RESYNC_REQUIRED");
172
+ return;
173
+ case "live":
174
+ this.#localFailures = 0;
175
+ this.#setState("live");
176
+ return;
177
+ case "stale":
178
+ case "authorizing":
179
+ this.#setState(frame.state, frame.reason);
180
+ return;
181
+ default:
182
+ return;
183
+ }
184
+ }
185
+ handleData(connection, frame) {
186
+ if (this.#terminal || connection !== this.#attached)
187
+ return;
188
+ this.#serverKnows = true;
189
+ if (this.#awaitingEpoch || frame.epoch !== this.#epoch)
190
+ return;
191
+ if (frame.sequence !== this.#expectedSequence) {
192
+ this.#localSyncFailure("INVALID_REQUEST", `Expected sequence ${this.#expectedSequence} but received ${frame.sequence}.`);
193
+ return;
194
+ }
195
+ const event = frame.event;
196
+ if (event.channel !== this.channel || event.channelVersion !== this.channelVersion) {
197
+ this.#localSyncFailure("INVALID_PAYLOAD", "A frame named a different channel contract.");
198
+ return;
199
+ }
200
+ if (frame.sequence === 1) {
201
+ if (event.kind !== "snapshot") {
202
+ this.#localSyncFailure("INVALID_REQUEST", "The first frame of an epoch must be a snapshot.");
203
+ return;
204
+ }
205
+ if (this.#lastRevision !== null && compareRevisions(event.revision, this.#lastRevision) < 0) {
206
+ this.#localSyncFailure("INVALID_PAYLOAD", "The snapshot is older than state this subscription already delivered.");
207
+ return;
208
+ }
209
+ }
210
+ else if (event.kind !== "update" || (this.#epochRevision !== null && compareRevisions(event.revision, this.#epochRevision) <= 0)) {
211
+ this.#localSyncFailure("INVALID_REQUEST", "Updates must follow the snapshot in increasing revision order.");
212
+ return;
213
+ }
214
+ this.#expectedSequence++;
215
+ this.#epochRevision = event.revision;
216
+ if (this.#lastRevision === null || compareRevisions(event.revision, this.#lastRevision) > 0)
217
+ this.#lastRevision = event.revision;
218
+ for (const listener of [...this.#listeners.data]) {
219
+ if (!this.#invoke(listener, event))
220
+ return;
221
+ }
222
+ connection.receipt({ subscriptionId: this.id, epoch: frame.epoch, sequence: frame.sequence });
223
+ }
224
+ handleError(connection, error) {
225
+ if (this.#terminal || connection !== this.#attached)
226
+ return;
227
+ this.#lastError = error;
228
+ this.#emitError(error);
229
+ }
230
+ // --- internals -----------------------------------------------------------------------
231
+ #blockedError(forResync = false) {
232
+ if (this.#owner.closed && this.#state === "closed")
233
+ return streamError("CLIENT_CLOSED");
234
+ if (this.#terminal) {
235
+ if (this.#state === "failed")
236
+ return this.#lastError ?? streamError("INTERNAL");
237
+ return this.#owner.closed ? streamError("CLIENT_CLOSED") : streamError("CANCELLED", { message: "The subscription was unsubscribed." });
238
+ }
239
+ if (this.#owner.authRequired)
240
+ return streamError("UNAUTHENTICATED", { message: "Authentication is required; call reconnect()." });
241
+ if (!forResync && this.#state === "resync-required")
242
+ return streamError("RESYNC_REQUIRED");
243
+ return null;
244
+ }
245
+ async #subscribe(connection) {
246
+ let result;
247
+ try {
248
+ result = await connection.request(EVENTS.subscribe, {
249
+ requestId: this.#owner.randomId(),
250
+ subscriptionId: this.id,
251
+ channel: this.channel,
252
+ channelVersion: this.channelVersion,
253
+ params: this.params
254
+ });
255
+ }
256
+ catch (error) {
257
+ if (connection !== this.#attached || this.#terminal)
258
+ return;
259
+ if (error.code === "TIMEOUT")
260
+ this.#owner.controlTimedOut(connection);
261
+ return;
262
+ }
263
+ if (connection !== this.#attached || this.#terminal)
264
+ return;
265
+ if (result.ok) {
266
+ this.#serverKnows = true;
267
+ return;
268
+ }
269
+ this.#lastError = result.error;
270
+ this.#emitError(result.error);
271
+ if (result.error.code === "OVERLOADED") {
272
+ // Rate or subscription limit: bounded retry (one- then two-second backoff), then resync-required.
273
+ this.#localFailures++;
274
+ if (this.#localFailures >= LOCAL_SYNC_ATTEMPTS) {
275
+ this.#setState("resync-required", "OVERLOADED");
276
+ return;
277
+ }
278
+ this.#setState("stale", "OVERLOADED");
279
+ this.#retryTimer = setTimeout(() => {
280
+ this.#retryTimer = null;
281
+ if (this.#attached === connection && connection.connected && !this.#terminal)
282
+ this.attach(connection);
283
+ }, 1_000 * 2 ** (this.#localFailures - 1));
284
+ return;
285
+ }
286
+ this.#terminate("failed", result.error.code, result.error);
287
+ }
288
+ #clearRetry() {
289
+ if (this.#retryTimer !== null) {
290
+ clearTimeout(this.#retryTimer);
291
+ this.#retryTimer = null;
292
+ }
293
+ }
294
+ #requestFreshSynchronization() {
295
+ const connection = this.#attached;
296
+ if (connection === null || !connection.connected)
297
+ return; // Reconnection resynchronizes.
298
+ if (!this.#serverKnows) {
299
+ if (this.#state === "authorizing")
300
+ return; // A subscribe is already in flight.
301
+ this.attach(connection);
302
+ return;
303
+ }
304
+ if (this.#state === "authorizing" || this.#state === "synchronizing")
305
+ return; // Joins the running synchronization.
306
+ this.#replacing = this.#epoch;
307
+ this.#awaitingEpoch = true;
308
+ this.#setState("authorizing");
309
+ connection.request(EVENTS.resync, { requestId: this.#owner.randomId(), subscriptionId: this.id }).then(result => {
310
+ if (connection !== this.#attached || this.#terminal || result.ok)
311
+ return;
312
+ this.#lastError = result.error;
313
+ this.#emitError(result.error);
314
+ if (result.error.code === "INVALID_REQUEST")
315
+ this.attach(connection); // The gateway no longer knows it.
316
+ }, (error) => {
317
+ if (connection === this.#attached && !this.#terminal && error.code === "TIMEOUT")
318
+ this.#owner.controlTimedOut(connection);
319
+ });
320
+ }
321
+ /** The SDK rejected a frame. Resynchronize, bounded per incident. */
322
+ #localSyncFailure(code, message) {
323
+ const error = streamError(code, { message, requestId: this.#owner.randomId() });
324
+ this.#lastError = error;
325
+ this.#emitError(error);
326
+ if (this.#terminal)
327
+ return;
328
+ this.#localFailures++;
329
+ if (this.#localFailures >= LOCAL_SYNC_ATTEMPTS) {
330
+ const connection = this.#attached;
331
+ if (this.#serverKnows && connection !== null && connection.connected)
332
+ void this.#sendUnsubscribe(connection);
333
+ this.#serverKnows = false;
334
+ this.#awaitingEpoch = true;
335
+ this.#setState("resync-required", "RESYNC_REQUIRED");
336
+ return;
337
+ }
338
+ this.#setState("stale", code);
339
+ this.#requestFreshSynchronization();
340
+ }
341
+ #sendUnsubscribe(connection) {
342
+ return new Promise(resolve => {
343
+ const timer = setTimeout(resolve, UNSUBSCRIBE_TIMEOUT_MS);
344
+ connection.request(EVENTS.unsubscribe, { requestId: this.#owner.randomId(), subscriptionId: this.id })
345
+ .then(() => undefined, () => undefined)
346
+ .finally(() => { clearTimeout(timer); resolve(); });
347
+ });
348
+ }
349
+ #terminate(state, reason, error) {
350
+ if (this.#terminal)
351
+ return;
352
+ this.#terminal = true;
353
+ this.#clearRetry();
354
+ this.#attached = null;
355
+ this.#owner.unregister(this);
356
+ this.#lastError = error;
357
+ this.#setState(state, reason, true);
358
+ this.#waiters.rejectAll(error);
359
+ this.#listeners.data.clear();
360
+ this.#listeners.state.clear();
361
+ this.#listeners.error.clear();
362
+ }
363
+ #setState(state, reason, force = false) {
364
+ if (this.#terminal && !force)
365
+ return;
366
+ if (this.#state === state && this.#reason === reason)
367
+ return;
368
+ this.#state = state;
369
+ this.#reason = reason;
370
+ const change = reason === undefined ? { state } : { state, reason };
371
+ for (const listener of [...this.#listeners.state]) {
372
+ if (!this.#invoke(listener, change))
373
+ return;
374
+ }
375
+ if (state === "live")
376
+ this.#waiters.resolveAll();
377
+ else if (state === "resync-required")
378
+ this.#waiters.rejectAll(streamError("RESYNC_REQUIRED"));
379
+ }
380
+ /** Runs a data/state listener. Failures become HANDLER_FAILED and fail the subscription. */
381
+ #invoke(listener, value) {
382
+ let returned;
383
+ try {
384
+ returned = listener(value);
385
+ }
386
+ catch (error) {
387
+ this.#listenerFailed(error);
388
+ return false;
389
+ }
390
+ if (isThenable(returned)) {
391
+ Promise.resolve(returned).catch((error) => this.#listenerFailed(error));
392
+ }
393
+ return true;
394
+ }
395
+ #listenerFailed(cause) {
396
+ if (this.#terminal)
397
+ return;
398
+ this.#owner.logListenerFailure(cause);
399
+ const error = streamError("HANDLER_FAILED", {
400
+ message: "A subscription listener threw; the subscription failed.",
401
+ requestId: this.#owner.randomId()
402
+ });
403
+ const connection = this.#attached;
404
+ const serverKnows = this.#serverKnows;
405
+ this.#emitError(error);
406
+ this.#terminate("failed", "HANDLER_FAILED", error);
407
+ if (serverKnows && connection !== null && connection.connected)
408
+ void this.#sendUnsubscribe(connection);
409
+ }
410
+ /** Error-listener failures are logged, never re-emitted. */
411
+ #emitError(error) {
412
+ for (const listener of [...this.#listeners.error]) {
413
+ try {
414
+ const returned = listener(error);
415
+ if (isThenable(returned))
416
+ Promise.resolve(returned).catch((cause) => this.#owner.logListenerFailure(cause));
417
+ }
418
+ catch (cause) {
419
+ this.#owner.logListenerFailure(cause);
420
+ }
421
+ }
422
+ }
423
+ }
424
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,sBAAsB,EAGpG,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AA8BzC,2FAA2F;AAC3F,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,CAAC,IAAI,KAAK,KAAK,IAAI;WAC9E,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IACpB,EAAE,CAAS;IACX,OAAO,CAAS;IAChB,cAAc,CAAS;IACvB,MAAM,CAAS;IACf,MAAM,CAAoB;IAC1B,UAAU,GAAG;QACpB,IAAI,EAAE,IAAI,GAAG,EAAmC;QAChD,KAAK,EAAE,IAAI,GAAG,EAAmD;QACjE,KAAK,EAAE,IAAI,GAAG,EAAgC;KAC/C,CAAC;IACO,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAC;IACpC,MAAM,GAAsB,MAAM,CAAC;IACnC,OAAO,CAAwB;IAC/B,SAAS,GAAG,KAAK,CAAC;IAClB,SAAS,GAAsB,IAAI,CAAC;IACpC,YAAY,GAAG,KAAK,CAAC;IACrB,MAAM,GAAkB,IAAI,CAAC;IAC7B,uFAAuF;IACvF,UAAU,GAAkB,IAAI,CAAC;IACjC,cAAc,GAAG,IAAI,CAAC;IACtB,iBAAiB,GAAG,CAAC,CAAC;IACtB,cAAc,GAAoB,IAAI,CAAC;IACvC,aAAa,GAAoB,IAAI,CAAC;IACtC,cAAc,GAAG,CAAC,CAAC;IACnB,UAAU,GAAuB,IAAI,CAAC;IACtC,cAAc,GAAyB,IAAI,CAAC;IAC5C,WAAW,GAAyC,IAAI,CAAC;IAEzD,YAAY,KAAwB,EAAE,OAAe,EAAE,cAAsB,EAAE,MAAc;QAC3F,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,gFAAgF;QAChF,cAAc,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;IACzB,CAAC;IAKD,EAAE,CAAC,KAAiC,EAAE,QAAkB;QACtD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAA8B,CAAC;QAChE,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACxD,MAAM,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,iEAAiE,EAAE,CAAC,CAAC;QAChI,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,OAAqB;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACrC,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,OAAqB;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,4BAA4B,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,cAAc,CAAC;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,gBAAgB,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC,CAAC;QAC3H,IAAI,CAAC,cAAc,GAAG,WAAW,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,SAAS;YAC9E,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC;YACnC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,sFAAsF;IAEtF,wDAAwD;IACxD,MAAM,CAAC,UAAsB;QAC3B,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC;QAC5B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9B,KAAK,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,uFAAuF;IACvF,MAAM,CAAC,MAAkB;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,iBAAiB;YAAE,OAAO;QAChE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,wEAAwE;IACxE,YAAY,CAAC,KAAkB;QAC7B,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,kFAAkF;IAClF,gBAAgB,CAAC,KAA0B,EAAE,KAAkB,EAAE,IAAa;QAC5E,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,IAAI;YAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,UAAsB,EAAE,KAAwB;QAC1D,IAAI,IAAI,CAAC,SAAS,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5D,kFAAkF;QAClF,qEAAqE;QACrE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,KAAK,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc;gBAAE,OAAO;YAChE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;YAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;YAAE,OAAO;QAChD,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,UAAU;eAC1D,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,iBAAiB,CAAC,EAAE,CAAC;YACnE,OAAO,CAAC,yDAAyD;QACnE,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAC1D,QAAQ,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,KAAK,QAAQ;gBACX,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC1B,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC;gBACpG,OAAO;YACT,KAAK,QAAQ;gBACX,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC1B,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC;gBACrG,OAAO;YACT,KAAK,iBAAiB;gBACpB,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC;gBACrE,OAAO;YACT,KAAK,MAAM;gBACT,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;gBACxB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACvB,OAAO;YACT,KAAK,OAAO,CAAC;YACb,KAAK,aAAa;gBAChB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC1C,OAAO;YACT;gBACE,OAAO;QACX,CAAC;IACH,CAAC;IAED,UAAU,CAAC,UAAsB,EAAE,KAAgB;QACjD,IAAI,IAAI,CAAC,SAAS,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5D,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO;QAC/D,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC9C,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,qBAAqB,IAAI,CAAC,iBAAiB,iBAAiB,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;YACzH,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YACnF,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,6CAA6C,CAAC,CAAC;YACzF,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,iDAAiD,CAAC,CAAC;gBAC7F,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5F,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,uEAAuE,CAAC,CAAC;gBACnH,OAAO;YACT,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACnI,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,gEAAgE,CAAC,CAAC;YAC5G,OAAO;QACT,CAAC;QACD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;QACrC,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC;QACjI,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAuB,CAAC;gBAAE,OAAO;QAC/D,CAAC;QACD,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,WAAW,CAAC,UAAsB,EAAE,KAAkB;QACpD,IAAI,IAAI,CAAC,SAAS,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5D,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,wFAAwF;IAExF,aAAa,CAAC,SAAS,GAAG,KAAK;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,WAAW,CAAC,eAAe,CAAC,CAAC;QACxF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC,UAAU,CAAC,CAAC;YAChF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC;QACzI,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY;YAAE,OAAO,WAAW,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAC,CAAC;QAClI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,iBAAiB;YAAE,OAAO,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAsB;QACrC,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAA6B,MAAM,CAAC,SAAS,EAAE;gBAC9E,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;gBACjC,cAAc,EAAE,IAAI,CAAC,EAAE;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO;YAC5D,IAAK,KAAqB,CAAC,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YACvF,OAAO;QACT,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5D,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACvC,kGAAkG;YAClG,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,cAAc,IAAI,mBAAmB,EAAE,CAAC;gBAC/C,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACtC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;gBACjC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBACxB,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU,IAAI,UAAU,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxG,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC9B,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,4BAA4B;QAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS;YAAE,OAAO,CAAC,+BAA+B;QACzF,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa;gBAAE,OAAO,CAAC,oCAAoC;YAC/E,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,IAAI,IAAI,CAAC,MAAM,KAAK,eAAe;YAAE,OAAO,CAAC,qCAAqC;QACnH,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9B,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YAC9G,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE;gBAAE,OAAO;YACzE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB;gBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,kCAAkC;QAC1G,CAAC,EAAE,CAAC,KAAkB,EAAE,EAAE;YACxB,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC5H,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,iBAAiB,CAAC,IAAe,EAAE,OAAe;QAChD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,cAAc,IAAI,mBAAmB,EAAE,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;YAClC,IAAI,IAAI,CAAC,YAAY,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,SAAS;gBAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAC7G,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,4BAA4B,EAAE,CAAC;IACtC,CAAC;IAED,gBAAgB,CAAC,UAAsB;QACrC,OAAO,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;YACjC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;YAC1D,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;iBACnG,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC;iBACtC,OAAO,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,KAA0B,EAAE,MAA6B,EAAE,KAAkB;QACtF,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,SAAS,CAAC,KAAwB,EAAE,MAAkB,EAAE,KAAK,GAAG,KAAK;QACnE,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK;YAAE,OAAO;QACrC,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,OAAO;QAC7D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,MAAM,MAAM,GAAmC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACpG,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,OAAO;QAC9C,CAAC;QACD,IAAI,KAAK,KAAK,MAAM;YAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;aAC5C,IAAI,KAAK,KAAK,iBAAiB;YAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChG,CAAC;IAED,4FAA4F;IAC5F,OAAO,CAAI,QAA+B,EAAE,KAAQ;QAClD,IAAI,QAAiB,CAAC;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,KAAc;QAC5B,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,WAAW,CAAC,gBAAgB,EAAE;YAC1C,OAAO,EAAE,yDAAyD;YAClE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;SAClC,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC;QACnD,IAAI,WAAW,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,SAAS;YAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACzG,CAAC;IAED,4DAA4D;IAC5D,UAAU,CAAC,KAAkB;QAC3B,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;gBACjC,IAAI,UAAU,CAAC,QAAQ,CAAC;oBAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;YACvH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import { type StreamError, type WaitOptions } from "@streamotter/contracts";
2
+ /**
3
+ * A set of independent waiters. Each waiter has its own timeout and signal;
4
+ * cancelling one never affects the others or the operation they wait for.
5
+ */
6
+ export declare class WaiterSet {
7
+ #private;
8
+ get size(): number;
9
+ wait(options: WaitOptions | undefined): Promise<void>;
10
+ resolveAll(): void;
11
+ rejectAll(error: StreamError): void;
12
+ }
13
+ //# sourceMappingURL=waiters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waiters.d.ts","sourceRoot":"","sources":["../src/waiters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE5I;;;GAGG;AACH,qBAAa,SAAS;;IAGpB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBrD,UAAU,IAAI,IAAI;IAIlB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;CAGpC"}
@@ -0,0 +1,43 @@
1
+ import { asStreamOtterError, DEFAULT_READY_TIMEOUT_MS, StreamOtterError } from "@streamotter/contracts";
2
+ /**
3
+ * A set of independent waiters. Each waiter has its own timeout and signal;
4
+ * cancelling one never affects the others or the operation they wait for.
5
+ */
6
+ export class WaiterSet {
7
+ #waiters = new Set();
8
+ get size() {
9
+ return this.#waiters.size;
10
+ }
11
+ wait(options) {
12
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
13
+ const signal = options?.signal;
14
+ if (signal?.aborted)
15
+ return Promise.reject(new StreamOtterError("CANCELLED"));
16
+ return new Promise((resolve, reject) => {
17
+ const cleanup = () => {
18
+ clearTimeout(timer);
19
+ signal?.removeEventListener("abort", onAbort);
20
+ this.#waiters.delete(waiter);
21
+ };
22
+ const waiter = {
23
+ resolve: () => { cleanup(); resolve(); },
24
+ reject: (error) => { cleanup(); reject(asStreamOtterError(error)); }
25
+ };
26
+ const onAbort = () => waiter.reject(new StreamOtterError("CANCELLED"));
27
+ const timer = setTimeout(() => waiter.reject(new StreamOtterError("TIMEOUT", {
28
+ message: `The subscription did not become live within ${timeoutMs} ms.`
29
+ })), timeoutMs);
30
+ signal?.addEventListener("abort", onAbort, { once: true });
31
+ this.#waiters.add(waiter);
32
+ });
33
+ }
34
+ resolveAll() {
35
+ for (const waiter of [...this.#waiters])
36
+ waiter.resolve();
37
+ }
38
+ rejectAll(error) {
39
+ for (const waiter of [...this.#waiters])
40
+ waiter.reject(error);
41
+ }
42
+ }
43
+ //# sourceMappingURL=waiters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waiters.js","sourceRoot":"","sources":["../src/waiters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,gBAAgB,EAAsC,MAAM,wBAAwB,CAAC;AAE5I;;;GAGG;AACH,MAAM,OAAO,SAAS;IACX,QAAQ,GAAG,IAAI,GAAG,EAAiE,CAAC;IAE7F,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,OAAgC;QACnC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,wBAAwB,CAAC;QACjE,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;QAC/B,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC,CAAC;YACF,MAAM,MAAM,GAAG;gBACb,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACxC,MAAM,EAAE,CAAC,KAAkB,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;aAClF,CAAC;YACF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;YACvE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,SAAS,EAAE;gBAC3E,OAAO,EAAE,+CAA+C,SAAS,MAAM;aACxE,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAChB,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC5D,CAAC;IAED,SAAS,CAAC,KAAkB;QAC1B,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@streamotter/client",
3
+ "version": "0.1.0-rc.1",
4
+ "description": "StreamOtter browser SDK: subscribe to state channels with authoritative snapshots, revision-ordered updates, and explicit live/stale states over Socket.IO.",
5
+ "keywords": [
6
+ "streamotter",
7
+ "kafka",
8
+ "socket.io",
9
+ "websocket",
10
+ "realtime",
11
+ "live-data",
12
+ "state-sync",
13
+ "browser",
14
+ "typescript"
15
+ ],
16
+ "homepage": "https://github.com/jfricano/StreamOtter/tree/main/packages/client#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/jfricano/StreamOtter/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/jfricano/StreamOtter.git",
23
+ "directory": "packages/client"
24
+ },
25
+ "license": "MIT",
26
+ "author": "Orca Solutions",
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src"
38
+ ],
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "dependencies": {
43
+ "socket.io-client": "4.8.3",
44
+ "@streamotter/contracts": "0.1.0-rc.1"
45
+ }
46
+ }