@instantdb/core 0.22.139 → 0.22.140

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 (40) hide show
  1. package/dist/commonjs/Connection.d.ts +2 -1
  2. package/dist/commonjs/Connection.d.ts.map +1 -1
  3. package/dist/commonjs/Connection.js +6 -2
  4. package/dist/commonjs/Connection.js.map +1 -1
  5. package/dist/commonjs/Reactor.d.ts +12 -0
  6. package/dist/commonjs/Reactor.d.ts.map +1 -1
  7. package/dist/commonjs/Reactor.js +63 -18
  8. package/dist/commonjs/Reactor.js.map +1 -1
  9. package/dist/commonjs/Stream.d.ts +112 -0
  10. package/dist/commonjs/Stream.d.ts.map +1 -0
  11. package/dist/commonjs/Stream.js +708 -0
  12. package/dist/commonjs/Stream.js.map +1 -0
  13. package/dist/commonjs/index.d.ts +41 -2
  14. package/dist/commonjs/index.d.ts.map +1 -1
  15. package/dist/commonjs/index.js +41 -1
  16. package/dist/commonjs/index.js.map +1 -1
  17. package/dist/esm/Connection.d.ts +2 -1
  18. package/dist/esm/Connection.d.ts.map +1 -1
  19. package/dist/esm/Connection.js +6 -2
  20. package/dist/esm/Connection.js.map +1 -1
  21. package/dist/esm/Reactor.d.ts +12 -0
  22. package/dist/esm/Reactor.d.ts.map +1 -1
  23. package/dist/esm/Reactor.js +53 -9
  24. package/dist/esm/Reactor.js.map +1 -1
  25. package/dist/esm/Stream.d.ts +112 -0
  26. package/dist/esm/Stream.d.ts.map +1 -0
  27. package/dist/esm/Stream.js +701 -0
  28. package/dist/esm/Stream.js.map +1 -0
  29. package/dist/esm/index.d.ts +41 -2
  30. package/dist/esm/index.d.ts.map +1 -1
  31. package/dist/esm/index.js +42 -1
  32. package/dist/esm/index.js.map +1 -1
  33. package/dist/standalone/index.js +2203 -1604
  34. package/dist/standalone/index.umd.cjs +3 -3
  35. package/package.json +2 -2
  36. package/src/Connection.ts +6 -2
  37. package/src/Reactor.js +56 -10
  38. package/src/Stream.ts +1016 -0
  39. package/src/index.ts +71 -1
  40. package/tsconfig.json +2 -1
@@ -0,0 +1,708 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InstantStream = void 0;
7
+ const id_ts_1 = __importDefault(require("./utils/id.js"));
8
+ const Reactor_js_1 = require("./Reactor.js");
9
+ const InstantError_ts_1 = require("./InstantError.js");
10
+ function createWriteStream({ WStream, opts, startStream, appendStream, registerStream, }) {
11
+ const clientId = opts.clientId;
12
+ let streamId_ = null;
13
+ let controller_ = null;
14
+ const reconnectToken = (0, id_ts_1.default)();
15
+ let isDone = false;
16
+ let closed = false;
17
+ const closeCbs = [];
18
+ const streamIdCbs = [];
19
+ let disconnected = false;
20
+ // Chunks that we haven't been notified are flushed to disk
21
+ let bufferOffset = 0;
22
+ let bufferByteSize = 0;
23
+ const buffer = [];
24
+ const encoder = new TextEncoder();
25
+ function markClosed() {
26
+ closed = true;
27
+ for (const cb of closeCbs) {
28
+ cb();
29
+ }
30
+ }
31
+ function addCloseCb(cb) {
32
+ closeCbs.push(cb);
33
+ return () => {
34
+ const i = closeCbs.indexOf(cb);
35
+ if (i !== -1) {
36
+ closeCbs.splice(i, 1);
37
+ }
38
+ };
39
+ }
40
+ function addStreamIdCb(cb) {
41
+ streamIdCbs.push(cb);
42
+ return () => {
43
+ const i = streamIdCbs.indexOf(cb);
44
+ if (i !== -1) {
45
+ streamIdCbs.splice(i, 1);
46
+ }
47
+ };
48
+ }
49
+ function setStreamId(streamId) {
50
+ streamId_ = streamId;
51
+ for (const cb of streamIdCbs) {
52
+ cb(streamId_);
53
+ }
54
+ }
55
+ function onDisconnect() {
56
+ disconnected = true;
57
+ }
58
+ // Clears data from our buffer after it has been flushed to a file
59
+ function discardFlushed(offset) {
60
+ let chunkOffset = bufferOffset;
61
+ let segmentsToDrop = 0;
62
+ let droppedSegmentsByteLen = 0;
63
+ for (const { byteLen } of buffer) {
64
+ const nextChunkOffset = chunkOffset + byteLen;
65
+ if (nextChunkOffset > offset) {
66
+ break;
67
+ }
68
+ chunkOffset = nextChunkOffset;
69
+ segmentsToDrop++;
70
+ droppedSegmentsByteLen += byteLen;
71
+ }
72
+ if (segmentsToDrop > 0) {
73
+ bufferOffset += droppedSegmentsByteLen;
74
+ bufferByteSize -= droppedSegmentsByteLen;
75
+ buffer.splice(0, segmentsToDrop);
76
+ }
77
+ }
78
+ async function onConnectionReconnect() {
79
+ const result = await startStream({
80
+ clientId,
81
+ reconnectToken,
82
+ });
83
+ switch (result.type) {
84
+ case 'ok': {
85
+ const { streamId, offset } = result;
86
+ streamId_ = streamId;
87
+ discardFlushed(offset);
88
+ if (buffer.length) {
89
+ appendStream({
90
+ streamId: streamId,
91
+ chunks: buffer.map((b) => b.chunk),
92
+ offset: bufferOffset,
93
+ });
94
+ }
95
+ disconnected = false;
96
+ break;
97
+ }
98
+ case 'disconnect': {
99
+ onDisconnect();
100
+ break;
101
+ }
102
+ case 'error': {
103
+ if (controller_) {
104
+ controller_.error(result.error);
105
+ markClosed();
106
+ }
107
+ break;
108
+ }
109
+ }
110
+ }
111
+ // When the append fails, we'll just try to reconnect and start again
112
+ function onAppendFailed() {
113
+ onDisconnect();
114
+ onConnectionReconnect();
115
+ }
116
+ function onFlush({ offset, done }) {
117
+ discardFlushed(offset);
118
+ if (done) {
119
+ isDone = true;
120
+ }
121
+ }
122
+ function error(controller, error) {
123
+ markClosed();
124
+ controller.error(error);
125
+ }
126
+ function ensureSetup(controller) {
127
+ if (isDone) {
128
+ error(controller, new InstantError_ts_1.InstantError('Stream has been closed.'));
129
+ }
130
+ if (!streamId_) {
131
+ error(controller, new InstantError_ts_1.InstantError('Stream has not been initialized.'));
132
+ }
133
+ return streamId_;
134
+ }
135
+ async function start(controller) {
136
+ controller_ = controller;
137
+ let tryAgain = true;
138
+ let attempts = 0;
139
+ while (tryAgain) {
140
+ // rate-limit after the first few failed connects
141
+ let nextAttempt = Date.now() + Math.min(15000, 500 * (attempts - 1));
142
+ tryAgain = false;
143
+ const result = await startStream({
144
+ clientId: opts.clientId,
145
+ reconnectToken,
146
+ });
147
+ switch (result.type) {
148
+ case 'ok': {
149
+ const { streamId, offset } = result;
150
+ if (offset !== 0) {
151
+ const e = new InstantError_ts_1.InstantError('Write stream is corrupted');
152
+ error(controller, e);
153
+ return;
154
+ }
155
+ setStreamId(streamId);
156
+ registerStream(streamId, {
157
+ onDisconnect,
158
+ onFlush,
159
+ onConnectionReconnect,
160
+ onAppendFailed,
161
+ });
162
+ disconnected = false;
163
+ return;
164
+ }
165
+ case 'disconnect': {
166
+ tryAgain = true;
167
+ onDisconnect();
168
+ attempts++;
169
+ await new Promise((resolve) => {
170
+ // Try again immediately for the first two attempts, then back off
171
+ setTimeout(resolve, nextAttempt - Date.now());
172
+ });
173
+ break;
174
+ }
175
+ case 'error': {
176
+ error(controller, result.error);
177
+ return;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ class WStreamEnhanced extends WStream {
183
+ constructor(sink, strategy) {
184
+ super(sink, strategy);
185
+ }
186
+ async streamId() {
187
+ if (streamId_) {
188
+ return streamId_;
189
+ }
190
+ return new Promise((resolve, reject) => {
191
+ const cleanupFns = [];
192
+ const cleanup = () => {
193
+ for (const f of cleanupFns) {
194
+ f();
195
+ }
196
+ };
197
+ const resolveCb = (streamId) => {
198
+ resolve(streamId);
199
+ cleanup();
200
+ };
201
+ const rejectCb = () => {
202
+ reject(new InstantError_ts_1.InstantError('Stream is closed.'));
203
+ cleanup();
204
+ };
205
+ cleanupFns.push(addStreamIdCb(resolveCb));
206
+ cleanupFns.push(addCloseCb(rejectCb));
207
+ });
208
+ }
209
+ }
210
+ const stream = new WStreamEnhanced({
211
+ // TODO(dww): accept a storage so that write streams can survive across
212
+ // browser restarts
213
+ async start(controller) {
214
+ try {
215
+ await start(controller);
216
+ }
217
+ catch (e) {
218
+ error(controller, e);
219
+ }
220
+ },
221
+ write(chunk, controller) {
222
+ const streamId = ensureSetup(controller);
223
+ if (streamId) {
224
+ const byteLen = encoder.encode(chunk).length;
225
+ buffer.push({ chunk, byteLen });
226
+ const offset = bufferOffset + bufferByteSize;
227
+ bufferByteSize += byteLen;
228
+ if (!disconnected) {
229
+ appendStream({ streamId, chunks: [chunk], offset });
230
+ }
231
+ }
232
+ },
233
+ close() {
234
+ if (streamId_) {
235
+ appendStream({
236
+ streamId: streamId_,
237
+ chunks: [],
238
+ offset: bufferOffset + bufferByteSize,
239
+ isDone: true,
240
+ });
241
+ }
242
+ markClosed();
243
+ },
244
+ abort(reason) {
245
+ if (streamId_) {
246
+ appendStream({
247
+ streamId: streamId_,
248
+ chunks: [],
249
+ offset: bufferOffset + bufferByteSize,
250
+ isDone: true,
251
+ abortReason: reason,
252
+ });
253
+ }
254
+ markClosed();
255
+ },
256
+ });
257
+ return {
258
+ stream,
259
+ addCloseCb,
260
+ closed() {
261
+ return closed;
262
+ },
263
+ };
264
+ }
265
+ class StreamIterator {
266
+ items = [];
267
+ resolvers = [];
268
+ isClosed = false;
269
+ constructor() { }
270
+ push(item) {
271
+ if (this.isClosed)
272
+ return;
273
+ const resolve = this.resolvers.shift();
274
+ if (resolve) {
275
+ resolve({ value: item, done: false });
276
+ }
277
+ else {
278
+ this.items.push(item);
279
+ }
280
+ }
281
+ close() {
282
+ this.isClosed = true;
283
+ while (this.resolvers.length > 0) {
284
+ const resolve = this.resolvers.shift();
285
+ resolve({ value: undefined, done: true });
286
+ }
287
+ }
288
+ async *[Symbol.asyncIterator]() {
289
+ while (true) {
290
+ if (this.items.length > 0) {
291
+ yield this.items.shift();
292
+ }
293
+ else if (this.isClosed) {
294
+ return;
295
+ }
296
+ else {
297
+ const { value, done } = await new Promise((resolve) => {
298
+ this.resolvers.push(resolve);
299
+ });
300
+ if (done || !value) {
301
+ return;
302
+ }
303
+ yield value;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ function createReadStream({ RStream, opts, startStream, cancelStream, }) {
309
+ let seenOffset = opts.byteOffset || 0;
310
+ let canceled = false;
311
+ const decoder = new TextDecoder('utf-8');
312
+ const encoder = new TextEncoder();
313
+ let eventId;
314
+ let closed = false;
315
+ const closeCbs = [];
316
+ function markClosed() {
317
+ closed = true;
318
+ for (const cb of closeCbs) {
319
+ cb();
320
+ }
321
+ }
322
+ function addCloseCb(cb) {
323
+ closeCbs.push(cb);
324
+ return () => {
325
+ const i = closeCbs.indexOf(cb);
326
+ if (i !== -1) {
327
+ closeCbs.splice(i, 1);
328
+ }
329
+ };
330
+ }
331
+ function error(controller, e) {
332
+ controller.error(e);
333
+ markClosed();
334
+ }
335
+ let fetchFailures = 0;
336
+ async function runStartStream(opts, controller) {
337
+ eventId = (0, id_ts_1.default)();
338
+ const streamOpts = { ...(opts || {}), eventId };
339
+ for await (const item of startStream(streamOpts)) {
340
+ if (canceled) {
341
+ return;
342
+ }
343
+ if (item.type === 'reconnect') {
344
+ return { retry: true };
345
+ }
346
+ if (item.type === 'error') {
347
+ error(controller, item.error);
348
+ return;
349
+ }
350
+ if (item.offset > seenOffset) {
351
+ error(controller, new InstantError_ts_1.InstantError('Stream is corrupted.'));
352
+ canceled = true;
353
+ return;
354
+ }
355
+ let discardLen = seenOffset - item.offset;
356
+ if (item.files && item.files.length) {
357
+ const fetchAbort = new AbortController();
358
+ let nextFetch = fetch(item.files[0].url, {
359
+ signal: fetchAbort.signal,
360
+ });
361
+ for (let i = 0; i < item.files.length; i++) {
362
+ const nextFile = item.files[i + 1];
363
+ const thisFetch = nextFetch;
364
+ const res = await thisFetch;
365
+ if (nextFile) {
366
+ nextFetch = fetch(nextFile.url, { signal: fetchAbort.signal });
367
+ }
368
+ if (!res.ok) {
369
+ fetchFailures++;
370
+ if (fetchFailures > 10) {
371
+ error(controller, new InstantError_ts_1.InstantError('Unable to process stream.'));
372
+ return;
373
+ }
374
+ return { retry: true };
375
+ }
376
+ if (res.body) {
377
+ for await (const bodyChunk of res.body) {
378
+ if (canceled) {
379
+ fetchAbort.abort();
380
+ return;
381
+ }
382
+ let chunk = bodyChunk;
383
+ if (discardLen > 0) {
384
+ chunk = bodyChunk.subarray(discardLen);
385
+ discardLen -= bodyChunk.length - chunk.length;
386
+ }
387
+ if (!chunk.length) {
388
+ continue;
389
+ }
390
+ seenOffset += chunk.length;
391
+ const s = decoder.decode(chunk);
392
+ controller.enqueue(s);
393
+ }
394
+ }
395
+ else {
396
+ // RN doesn't support request.body
397
+ const bodyChunk = await res.arrayBuffer();
398
+ let chunk = bodyChunk;
399
+ if (canceled) {
400
+ fetchAbort.abort();
401
+ return;
402
+ }
403
+ if (discardLen > 0) {
404
+ chunk = new Uint8Array(bodyChunk).subarray(discardLen);
405
+ discardLen -= bodyChunk.byteLength - chunk.length;
406
+ }
407
+ if (!chunk.byteLength) {
408
+ continue;
409
+ }
410
+ seenOffset += chunk.byteLength;
411
+ const s = decoder.decode(chunk);
412
+ controller.enqueue(s);
413
+ }
414
+ }
415
+ }
416
+ fetchFailures = 0;
417
+ if (item.content) {
418
+ let content = item.content;
419
+ let encoded = encoder.encode(item.content);
420
+ if (discardLen > 0) {
421
+ const remaining = encoded.subarray(discardLen);
422
+ discardLen -= encoded.length - remaining.length;
423
+ if (!remaining.length) {
424
+ continue;
425
+ }
426
+ encoded = remaining;
427
+ content = decoder.decode(remaining);
428
+ }
429
+ seenOffset += encoded.length;
430
+ controller.enqueue(content);
431
+ }
432
+ }
433
+ }
434
+ async function start(controller) {
435
+ let retry = true;
436
+ let attempts = 0;
437
+ while (retry) {
438
+ retry = false;
439
+ let nextAttempt = Date.now() + Math.min(15000, 500 * (attempts - 1));
440
+ const res = await runStartStream({ ...opts, offset: seenOffset }, controller);
441
+ if (res?.retry) {
442
+ retry = true;
443
+ attempts++;
444
+ if (nextAttempt < Date.now() - 300000) {
445
+ // reset attempts if we last tried 5 minutes ago
446
+ attempts = 0;
447
+ }
448
+ await new Promise((resolve) => {
449
+ setTimeout(resolve, nextAttempt - Date.now());
450
+ });
451
+ }
452
+ }
453
+ if (!canceled && !closed) {
454
+ controller.close();
455
+ markClosed();
456
+ }
457
+ }
458
+ const stream = new RStream({
459
+ start(controller) {
460
+ start(controller);
461
+ },
462
+ cancel(_reason) {
463
+ canceled = true;
464
+ if (eventId) {
465
+ cancelStream({ eventId });
466
+ }
467
+ markClosed();
468
+ },
469
+ });
470
+ return {
471
+ stream,
472
+ addCloseCb,
473
+ closed() {
474
+ return closed;
475
+ },
476
+ };
477
+ }
478
+ class InstantStream {
479
+ trySend;
480
+ WStream;
481
+ RStream;
482
+ writeStreams = {};
483
+ startWriteStreamCbs = {};
484
+ readStreamIterators = {};
485
+ log;
486
+ activeStreams = new Set();
487
+ constructor({ WStream, RStream, trySend, log, }) {
488
+ this.WStream = WStream;
489
+ this.RStream = RStream;
490
+ this.trySend = trySend;
491
+ this.log = log;
492
+ }
493
+ createWriteStream(opts) {
494
+ const { stream, addCloseCb } = createWriteStream({
495
+ WStream: this.WStream,
496
+ startStream: this.startWriteStream.bind(this),
497
+ appendStream: this.appendStream.bind(this),
498
+ registerStream: this.registerWriteStream.bind(this),
499
+ opts,
500
+ });
501
+ this.activeStreams.add(stream);
502
+ addCloseCb(() => {
503
+ this.activeStreams.delete(stream);
504
+ });
505
+ return stream;
506
+ }
507
+ createReadStream(opts) {
508
+ const { stream, addCloseCb } = createReadStream({
509
+ RStream: this.RStream,
510
+ opts,
511
+ startStream: this.startReadStream.bind(this),
512
+ cancelStream: this.cancelReadStream.bind(this),
513
+ });
514
+ this.activeStreams.add(stream);
515
+ addCloseCb(() => {
516
+ this.activeStreams.delete(stream);
517
+ });
518
+ return stream;
519
+ }
520
+ startWriteStream(opts) {
521
+ const eventId = (0, id_ts_1.default)();
522
+ let resolve = null;
523
+ const promise = new Promise((r) => {
524
+ resolve = r;
525
+ });
526
+ this.startWriteStreamCbs[eventId] = resolve;
527
+ const msg = {
528
+ op: 'start-stream',
529
+ 'client-id': opts.clientId,
530
+ 'reconnect-token': opts.reconnectToken,
531
+ };
532
+ this.trySend(eventId, msg);
533
+ return promise;
534
+ }
535
+ registerWriteStream(streamId, cbs) {
536
+ this.writeStreams[streamId] = cbs;
537
+ }
538
+ appendStream({ streamId, chunks, isDone, offset, abortReason, }) {
539
+ const msg = {
540
+ op: 'append-stream',
541
+ 'stream-id': streamId,
542
+ chunks,
543
+ offset,
544
+ done: !!isDone,
545
+ };
546
+ if (abortReason) {
547
+ msg['abort-reason'] = abortReason;
548
+ }
549
+ this.trySend((0, id_ts_1.default)(), msg);
550
+ }
551
+ onAppendFailed(msg) {
552
+ const cbs = this.writeStreams[msg['stream-id']];
553
+ if (cbs) {
554
+ cbs.onAppendFailed();
555
+ }
556
+ }
557
+ onStartStreamOk(msg) {
558
+ const cb = this.startWriteStreamCbs[msg['client-event-id']];
559
+ if (!cb) {
560
+ this.log.info('No stream for start-stream-ok', msg);
561
+ return;
562
+ }
563
+ cb({ type: 'ok', streamId: msg['stream-id'], offset: msg.offset });
564
+ delete this.startWriteStreamCbs[msg['client-event-id']];
565
+ }
566
+ onStreamFlushed(msg) {
567
+ const streamId = msg['stream-id'];
568
+ const cbs = this.writeStreams[streamId];
569
+ if (!cbs) {
570
+ this.log.info('No stream cbs for stream-flushed', msg);
571
+ return;
572
+ }
573
+ cbs.onFlush({ offset: msg.offset, done: msg.done });
574
+ if (msg.done) {
575
+ delete this.writeStreams[streamId];
576
+ }
577
+ }
578
+ startReadStream({ eventId, clientId, streamId, offset, }) {
579
+ const msg = { op: 'subscribe-stream' };
580
+ if (!streamId && !clientId) {
581
+ throw new Error('Must provide one of streamId or clientId to subscribe to the stream.');
582
+ }
583
+ if (streamId) {
584
+ msg['stream-id'] = streamId;
585
+ }
586
+ if (clientId) {
587
+ msg['client-id'] = clientId;
588
+ }
589
+ if (offset) {
590
+ msg['offset'] = offset;
591
+ }
592
+ const iterator = new StreamIterator();
593
+ this.readStreamIterators[eventId] = iterator;
594
+ this.trySend(eventId, msg);
595
+ return iterator;
596
+ }
597
+ cancelReadStream({ eventId }) {
598
+ const msg = {
599
+ op: 'unsubscribe-stream',
600
+ 'subscribe-event-id': eventId,
601
+ };
602
+ this.trySend((0, id_ts_1.default)(), msg);
603
+ delete this.readStreamIterators[eventId];
604
+ }
605
+ onStreamAppend(msg) {
606
+ const eventId = msg['client-event-id'];
607
+ const iterator = this.readStreamIterators[eventId];
608
+ if (!iterator) {
609
+ this.log.info('No iterator for read stream', msg);
610
+ return;
611
+ }
612
+ if (msg.error) {
613
+ if (msg.retry) {
614
+ iterator.push({ type: 'reconnect' });
615
+ }
616
+ else {
617
+ iterator.push({
618
+ type: 'error',
619
+ error: new InstantError_ts_1.InstantError(msg.error),
620
+ });
621
+ }
622
+ iterator.close();
623
+ delete this.readStreamIterators[eventId];
624
+ return;
625
+ }
626
+ if (msg.files?.length || msg.content) {
627
+ iterator.push({
628
+ type: 'append',
629
+ offset: msg.offset,
630
+ files: msg.files,
631
+ content: msg.content,
632
+ });
633
+ }
634
+ if (msg.done) {
635
+ iterator.close();
636
+ delete this.readStreamIterators[eventId];
637
+ }
638
+ }
639
+ onConnectionStatusChange(status) {
640
+ // Tell the writers to retry:
641
+ for (const cb of Object.values(this.startWriteStreamCbs)) {
642
+ cb({ type: 'disconnect' });
643
+ }
644
+ this.startWriteStreamCbs = {};
645
+ if (status !== Reactor_js_1.STATUS.AUTHENTICATED) {
646
+ // Notify the writers that they've been disconnected
647
+ for (const { onDisconnect } of Object.values(this.writeStreams)) {
648
+ onDisconnect();
649
+ }
650
+ }
651
+ else {
652
+ // Notify the writers that they need to reconnect
653
+ for (const { onConnectionReconnect } of Object.values(this.writeStreams)) {
654
+ onConnectionReconnect();
655
+ }
656
+ // Notify the readers that they need to reconnect
657
+ for (const iterator of Object.values(this.readStreamIterators)) {
658
+ iterator.push({ type: 'reconnect' });
659
+ iterator.close();
660
+ }
661
+ this.readStreamIterators = {};
662
+ }
663
+ }
664
+ onRecieveError(msg) {
665
+ const ev = msg['original-event'];
666
+ switch (ev.op) {
667
+ case 'append-stream': {
668
+ const streamId = ev['stream-id'];
669
+ const cbs = this.writeStreams[streamId];
670
+ cbs?.onAppendFailed();
671
+ break;
672
+ }
673
+ case 'start-stream': {
674
+ const eventId = msg['client-event-id'];
675
+ const cb = this.startWriteStreamCbs[eventId];
676
+ if (cb) {
677
+ cb({
678
+ type: 'error',
679
+ error: new InstantError_ts_1.InstantError(msg.message || 'Unknown error', msg.hint),
680
+ });
681
+ delete this.startWriteStreamCbs[eventId];
682
+ }
683
+ break;
684
+ }
685
+ case 'subscribe-stream': {
686
+ const eventId = msg['client-event-id'];
687
+ const iterator = this.readStreamIterators[eventId];
688
+ if (iterator) {
689
+ iterator.push({
690
+ type: 'error',
691
+ error: new InstantError_ts_1.InstantError(msg.message || 'Unknown error', msg.hint),
692
+ });
693
+ iterator.close();
694
+ delete this.readStreamIterators[eventId];
695
+ }
696
+ break;
697
+ }
698
+ case 'unsubscribe-stream': {
699
+ break;
700
+ }
701
+ }
702
+ }
703
+ hasActiveStreams() {
704
+ return this.activeStreams.size > 0;
705
+ }
706
+ }
707
+ exports.InstantStream = InstantStream;
708
+ //# sourceMappingURL=Stream.js.map