@electric-sql/client 0.5.0 → 0.5.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.
package/dist/index.mjs CHANGED
@@ -1,7 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
2
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
6
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
9
+ };
5
10
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
11
  var __spreadValues = (a, b) => {
7
12
  for (var prop in b || (b = {}))
@@ -14,6 +19,7 @@ var __spreadValues = (a, b) => {
14
19
  }
15
20
  return a;
16
21
  };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
17
23
  var __objRest = (source, exclude) => {
18
24
  var target = {};
19
25
  for (var prop in source)
@@ -26,6 +32,11 @@ var __objRest = (source, exclude) => {
26
32
  }
27
33
  return target;
28
34
  };
35
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
36
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
37
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
38
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
39
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
29
40
  var __async = (__this, __arguments, generator) => {
30
41
  return new Promise((resolve, reject) => {
31
42
  var fulfilled = (value) => {
@@ -166,36 +177,54 @@ function isChangeMessage(message) {
166
177
  function isControlMessage(message) {
167
178
  return !isChangeMessage(message);
168
179
  }
180
+ function isUpToDateMessage(message) {
181
+ return isControlMessage(message) && message.headers.control === `up-to-date`;
182
+ }
169
183
 
170
- // src/client.ts
171
- var BackoffDefaults = {
172
- initialDelay: 100,
173
- maxDelay: 1e4,
174
- multiplier: 1.3
184
+ // src/queue.ts
185
+ function isThenable(value) {
186
+ return !!value && typeof value === `object` && `then` in value && typeof value.then === `function`;
187
+ }
188
+ var _processingChain;
189
+ var AsyncProcessingQueue = class {
190
+ constructor() {
191
+ __privateAdd(this, _processingChain);
192
+ }
193
+ process(callback) {
194
+ __privateSet(this, _processingChain, isThenable(__privateGet(this, _processingChain)) ? __privateGet(this, _processingChain).then(callback) : callback());
195
+ return __privateGet(this, _processingChain);
196
+ }
197
+ waitForProcessing() {
198
+ return __async(this, null, function* () {
199
+ let currentChain;
200
+ do {
201
+ currentChain = __privateGet(this, _processingChain);
202
+ yield currentChain;
203
+ } while (__privateGet(this, _processingChain) !== currentChain);
204
+ });
205
+ }
175
206
  };
207
+ _processingChain = new WeakMap();
208
+ var _queue, _callback;
176
209
  var MessageProcessor = class {
177
210
  constructor(callback) {
178
- this.messageQueue = [];
179
- this.isProcessing = false;
180
- this.callback = callback;
211
+ __privateAdd(this, _queue, new AsyncProcessingQueue());
212
+ __privateAdd(this, _callback);
213
+ __privateSet(this, _callback, callback);
181
214
  }
182
215
  process(messages) {
183
- this.messageQueue.push(messages);
184
- if (!this.isProcessing) {
185
- this.processQueue();
186
- }
216
+ __privateGet(this, _queue).process(() => __privateGet(this, _callback).call(this, messages));
187
217
  }
188
- processQueue() {
218
+ waitForProcessing() {
189
219
  return __async(this, null, function* () {
190
- this.isProcessing = true;
191
- while (this.messageQueue.length > 0) {
192
- const messages = this.messageQueue.shift();
193
- yield this.callback(messages);
194
- }
195
- this.isProcessing = false;
220
+ yield __privateGet(this, _queue).waitForProcessing();
196
221
  });
197
222
  }
198
223
  };
224
+ _queue = new WeakMap();
225
+ _callback = new WeakMap();
226
+
227
+ // src/error.ts
199
228
  var FetchError = class _FetchError extends Error {
200
229
  constructor(status, text, json, headers, url, message) {
201
230
  super(
@@ -224,324 +253,414 @@ var FetchError = class _FetchError extends Error {
224
253
  });
225
254
  }
226
255
  };
256
+ var FetchBackoffAbortError = class extends Error {
257
+ constructor() {
258
+ super(`Fetch with backoff aborted`);
259
+ }
260
+ };
261
+
262
+ // src/fetch.ts
263
+ var BackoffDefaults = {
264
+ initialDelay: 100,
265
+ maxDelay: 1e4,
266
+ multiplier: 1.3
267
+ };
268
+ function createFetchWithBackoff(fetchClient, backoffOptions = BackoffDefaults) {
269
+ const {
270
+ initialDelay,
271
+ maxDelay,
272
+ multiplier,
273
+ debug = false,
274
+ onFailedAttempt
275
+ } = backoffOptions;
276
+ return (...args) => __async(this, null, function* () {
277
+ var _a;
278
+ const url = args[0];
279
+ const options = args[1];
280
+ let delay = initialDelay;
281
+ let attempt = 0;
282
+ while (true) {
283
+ try {
284
+ const result = yield fetchClient(...args);
285
+ if (result.ok) return result;
286
+ else throw yield FetchError.fromResponse(result, url.toString());
287
+ } catch (e) {
288
+ onFailedAttempt == null ? void 0 : onFailedAttempt();
289
+ if ((_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.aborted) {
290
+ throw new FetchBackoffAbortError();
291
+ } else if (e instanceof FetchError && e.status >= 400 && e.status < 500) {
292
+ throw e;
293
+ } else {
294
+ yield new Promise((resolve) => setTimeout(resolve, delay));
295
+ delay = Math.min(delay * multiplier, maxDelay);
296
+ if (debug) {
297
+ attempt++;
298
+ console.log(`Retry attempt #${attempt} after ${delay}ms`);
299
+ }
300
+ }
301
+ }
302
+ }
303
+ });
304
+ }
305
+
306
+ // src/constants.ts
307
+ var SHAPE_ID_HEADER = `x-electric-shape-id`;
308
+ var CHUNK_LAST_OFFSET_HEADER = `x-electric-chunk-last-offset`;
309
+ var SHAPE_SCHEMA_HEADER = `x-electric-schema`;
310
+ var SHAPE_ID_QUERY_PARAM = `shape_id`;
311
+ var OFFSET_QUERY_PARAM = `offset`;
312
+ var WHERE_QUERY_PARAM = `where`;
313
+ var LIVE_QUERY_PARAM = `live`;
314
+
315
+ // src/client.ts
316
+ var _fetchClient, _messageParser, _subscribers, _upToDateSubscribers, _lastOffset, _lastSyncedAt, _isUpToDate, _connected, _shapeId, _schema, _ShapeStream_instances, publish_fn, sendErrorToSubscribers_fn, notifyUpToDateSubscribers_fn, sendErrorToUpToDateSubscribers_fn, reset_fn;
227
317
  var ShapeStream = class {
228
318
  constructor(options) {
229
- this.subscribers = /* @__PURE__ */ new Map();
230
- this.upToDateSubscribers = /* @__PURE__ */ new Map();
319
+ __privateAdd(this, _ShapeStream_instances);
320
+ __privateAdd(this, _fetchClient);
321
+ __privateAdd(this, _messageParser);
322
+ __privateAdd(this, _subscribers, /* @__PURE__ */ new Map());
323
+ __privateAdd(this, _upToDateSubscribers, /* @__PURE__ */ new Map());
324
+ __privateAdd(this, _lastOffset);
325
+ __privateAdd(this, _lastSyncedAt);
231
326
  // unix time
232
- this.isUpToDate = false;
233
- this.connected = false;
327
+ __privateAdd(this, _isUpToDate, false);
328
+ __privateAdd(this, _connected, false);
329
+ __privateAdd(this, _shapeId);
330
+ __privateAdd(this, _schema);
234
331
  var _a, _b, _c;
235
- this.validateOptions(options);
332
+ validateOptions(options);
236
333
  this.options = __spreadValues({ subscribe: true }, options);
237
- this.lastOffset = (_a = this.options.offset) != null ? _a : `-1`;
238
- this.shapeId = this.options.shapeId;
239
- this.messageParser = new MessageParser(options.parser);
240
- this.backoffOptions = (_b = options.backoffOptions) != null ? _b : BackoffDefaults;
241
- this.fetchClient = (_c = options.fetchClient) != null ? _c : (...args) => fetch(...args);
334
+ __privateSet(this, _lastOffset, (_a = this.options.offset) != null ? _a : `-1`);
335
+ __privateSet(this, _shapeId, this.options.shapeId);
336
+ __privateSet(this, _messageParser, new MessageParser(options.parser));
337
+ __privateSet(this, _fetchClient, createFetchWithBackoff(
338
+ (_b = options.fetchClient) != null ? _b : (...args) => fetch(...args),
339
+ __spreadProps(__spreadValues({}, (_c = options.backoffOptions) != null ? _c : BackoffDefaults), {
340
+ onFailedAttempt: () => {
341
+ var _a2, _b2;
342
+ __privateSet(this, _connected, false);
343
+ (_b2 = (_a2 = options.backoffOptions) == null ? void 0 : _a2.onFailedAttempt) == null ? void 0 : _b2.call(_a2);
344
+ }
345
+ })
346
+ ));
242
347
  this.start();
243
348
  }
349
+ get shapeId() {
350
+ return __privateGet(this, _shapeId);
351
+ }
352
+ get isUpToDate() {
353
+ return __privateGet(this, _isUpToDate);
354
+ }
244
355
  start() {
245
356
  return __async(this, null, function* () {
246
357
  var _a;
247
- this.isUpToDate = false;
358
+ __privateSet(this, _isUpToDate, false);
248
359
  const { url, where, signal } = this.options;
249
360
  try {
250
- while (!(signal == null ? void 0 : signal.aborted) && !this.isUpToDate || this.options.subscribe) {
361
+ while (!(signal == null ? void 0 : signal.aborted) && !__privateGet(this, _isUpToDate) || this.options.subscribe) {
251
362
  const fetchUrl = new URL(url);
252
- if (where) fetchUrl.searchParams.set(`where`, where);
253
- fetchUrl.searchParams.set(`offset`, this.lastOffset);
254
- if (this.isUpToDate) {
255
- fetchUrl.searchParams.set(`live`, `true`);
363
+ if (where) fetchUrl.searchParams.set(WHERE_QUERY_PARAM, where);
364
+ fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
365
+ if (__privateGet(this, _isUpToDate)) {
366
+ fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
256
367
  }
257
- if (this.shapeId) {
258
- fetchUrl.searchParams.set(`shape_id`, this.shapeId);
368
+ if (__privateGet(this, _shapeId)) {
369
+ fetchUrl.searchParams.set(SHAPE_ID_QUERY_PARAM, __privateGet(this, _shapeId));
259
370
  }
260
371
  let response;
261
372
  try {
262
- const maybeResponse = yield this.fetchWithBackoff(fetchUrl);
263
- if (maybeResponse) response = maybeResponse;
264
- else break;
373
+ response = yield __privateGet(this, _fetchClient).call(this, fetchUrl.toString(), { signal });
374
+ __privateSet(this, _connected, true);
265
375
  } catch (e) {
376
+ if (e instanceof FetchBackoffAbortError) break;
266
377
  if (!(e instanceof FetchError)) throw e;
267
378
  if (e.status == 400) {
268
- this.reset();
269
- this.publish(e.json);
379
+ __privateMethod(this, _ShapeStream_instances, reset_fn).call(this);
380
+ __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
270
381
  continue;
271
382
  } else if (e.status == 409) {
272
- const newShapeId = e.headers[`x-electric-shape-id`];
273
- this.reset(newShapeId);
274
- this.publish(e.json);
383
+ const newShapeId = e.headers[SHAPE_ID_HEADER];
384
+ __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeId);
385
+ __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
275
386
  continue;
276
387
  } else if (e.status >= 400 && e.status < 500) {
277
- this.sendErrorToUpToDateSubscribers(e);
278
- this.sendErrorToSubscribers(e);
388
+ __privateMethod(this, _ShapeStream_instances, sendErrorToUpToDateSubscribers_fn).call(this, e);
389
+ __privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
279
390
  throw e;
280
391
  }
281
392
  }
282
393
  const { headers, status } = response;
283
- const shapeId = headers.get(`X-Electric-Shape-Id`);
394
+ const shapeId = headers.get(SHAPE_ID_HEADER);
284
395
  if (shapeId) {
285
- this.shapeId = shapeId;
396
+ __privateSet(this, _shapeId, shapeId);
286
397
  }
287
- const lastOffset = headers.get(`X-Electric-Chunk-Last-Offset`);
398
+ const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
288
399
  if (lastOffset) {
289
- this.lastOffset = lastOffset;
400
+ __privateSet(this, _lastOffset, lastOffset);
290
401
  }
291
402
  const getSchema = () => {
292
- const schemaHeader = headers.get(`X-Electric-Schema`);
403
+ const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
293
404
  return schemaHeader ? JSON.parse(schemaHeader) : {};
294
405
  };
295
- this.schema = (_a = this.schema) != null ? _a : getSchema();
406
+ __privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchema());
296
407
  const messages = status === 204 ? `[]` : yield response.text();
297
408
  if (status === 204) {
298
- this.lastSyncedAt = Date.now();
409
+ __privateSet(this, _lastSyncedAt, Date.now());
299
410
  }
300
- const batch = this.messageParser.parse(messages, this.schema);
411
+ const batch = __privateGet(this, _messageParser).parse(messages, __privateGet(this, _schema));
301
412
  if (batch.length > 0) {
302
413
  const lastMessage = batch[batch.length - 1];
303
- if (isControlMessage(lastMessage) && lastMessage.headers.control === `up-to-date`) {
304
- this.lastSyncedAt = Date.now();
305
- if (!this.isUpToDate) {
306
- this.isUpToDate = true;
307
- this.notifyUpToDateSubscribers();
414
+ if (isUpToDateMessage(lastMessage)) {
415
+ __privateSet(this, _lastSyncedAt, Date.now());
416
+ if (!__privateGet(this, _isUpToDate)) {
417
+ __privateSet(this, _isUpToDate, true);
418
+ __privateMethod(this, _ShapeStream_instances, notifyUpToDateSubscribers_fn).call(this);
308
419
  }
309
420
  }
310
- this.publish(batch);
421
+ __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
311
422
  }
312
423
  }
313
424
  } finally {
314
- this.connected = false;
425
+ __privateSet(this, _connected, false);
315
426
  }
316
427
  });
317
428
  }
318
429
  subscribe(callback, onError) {
319
430
  const subscriptionId = Math.random();
320
431
  const subscriber = new MessageProcessor(callback);
321
- this.subscribers.set(subscriptionId, [subscriber, onError]);
432
+ __privateGet(this, _subscribers).set(subscriptionId, [subscriber, onError]);
322
433
  return () => {
323
- this.subscribers.delete(subscriptionId);
434
+ __privateGet(this, _subscribers).delete(subscriptionId);
324
435
  };
325
436
  }
326
437
  unsubscribeAll() {
327
- this.subscribers.clear();
328
- }
329
- publish(messages) {
330
- this.subscribers.forEach(([subscriber, _]) => {
331
- subscriber.process(messages);
332
- });
333
- }
334
- sendErrorToSubscribers(error) {
335
- this.subscribers.forEach(([_, errorFn]) => {
336
- errorFn == null ? void 0 : errorFn(error);
337
- });
438
+ __privateGet(this, _subscribers).clear();
338
439
  }
339
440
  subscribeOnceToUpToDate(callback, error) {
340
441
  const subscriptionId = Math.random();
341
- this.upToDateSubscribers.set(subscriptionId, [callback, error]);
442
+ __privateGet(this, _upToDateSubscribers).set(subscriptionId, [callback, error]);
342
443
  return () => {
343
- this.upToDateSubscribers.delete(subscriptionId);
444
+ __privateGet(this, _upToDateSubscribers).delete(subscriptionId);
344
445
  };
345
446
  }
346
447
  unsubscribeAllUpToDateSubscribers() {
347
- this.upToDateSubscribers.clear();
448
+ __privateGet(this, _upToDateSubscribers).clear();
449
+ }
450
+ /** Unix time at which we last synced. Undefined when `isLoading` is true. */
451
+ lastSyncedAt() {
452
+ return __privateGet(this, _lastSyncedAt);
348
453
  }
349
454
  /** Time elapsed since last sync (in ms). Infinity if we did not yet sync. */
350
455
  lastSynced() {
351
- if (this.lastSyncedAt === void 0) return Infinity;
352
- return Date.now() - this.lastSyncedAt;
456
+ if (__privateGet(this, _lastSyncedAt) === void 0) return Infinity;
457
+ return Date.now() - __privateGet(this, _lastSyncedAt);
353
458
  }
459
+ /** Indicates if we are connected to the Electric sync service. */
354
460
  isConnected() {
355
- return this.connected;
461
+ return __privateGet(this, _connected);
356
462
  }
357
463
  /** True during initial fetch. False afterwise. */
358
464
  isLoading() {
359
465
  return !this.isUpToDate;
360
466
  }
361
- notifyUpToDateSubscribers() {
362
- this.upToDateSubscribers.forEach(([callback]) => {
363
- callback();
364
- });
467
+ };
468
+ _fetchClient = new WeakMap();
469
+ _messageParser = new WeakMap();
470
+ _subscribers = new WeakMap();
471
+ _upToDateSubscribers = new WeakMap();
472
+ _lastOffset = new WeakMap();
473
+ _lastSyncedAt = new WeakMap();
474
+ _isUpToDate = new WeakMap();
475
+ _connected = new WeakMap();
476
+ _shapeId = new WeakMap();
477
+ _schema = new WeakMap();
478
+ _ShapeStream_instances = new WeakSet();
479
+ publish_fn = function(messages) {
480
+ __privateGet(this, _subscribers).forEach(([subscriber, _]) => {
481
+ subscriber.process(messages);
482
+ });
483
+ };
484
+ sendErrorToSubscribers_fn = function(error) {
485
+ __privateGet(this, _subscribers).forEach(([_, errorFn]) => {
486
+ errorFn == null ? void 0 : errorFn(error);
487
+ });
488
+ };
489
+ notifyUpToDateSubscribers_fn = function() {
490
+ __privateGet(this, _upToDateSubscribers).forEach(([callback]) => {
491
+ callback();
492
+ });
493
+ };
494
+ sendErrorToUpToDateSubscribers_fn = function(error) {
495
+ __privateGet(this, _upToDateSubscribers).forEach(
496
+ ([_, errorCallback]) => errorCallback(error)
497
+ );
498
+ };
499
+ /**
500
+ * Resets the state of the stream, optionally with a provided
501
+ * shape ID
502
+ */
503
+ reset_fn = function(shapeId) {
504
+ __privateSet(this, _lastOffset, `-1`);
505
+ __privateSet(this, _shapeId, shapeId);
506
+ __privateSet(this, _isUpToDate, false);
507
+ __privateSet(this, _connected, false);
508
+ __privateSet(this, _schema, void 0);
509
+ };
510
+ function validateOptions(options) {
511
+ if (!options.url) {
512
+ throw new Error(`Invalid shape option. It must provide the url`);
365
513
  }
366
- sendErrorToUpToDateSubscribers(error) {
367
- this.upToDateSubscribers.forEach(
368
- ([_, errorCallback]) => errorCallback(error)
514
+ if (options.signal && !(options.signal instanceof AbortSignal)) {
515
+ throw new Error(
516
+ `Invalid signal option. It must be an instance of AbortSignal.`
369
517
  );
370
518
  }
371
- /**
372
- * Resets the state of the stream, optionally with a provided
373
- * shape ID
374
- */
375
- reset(shapeId) {
376
- this.lastOffset = `-1`;
377
- this.shapeId = shapeId;
378
- this.isUpToDate = false;
379
- this.connected = false;
380
- this.schema = void 0;
381
- }
382
- validateOptions(options) {
383
- if (!options.url) {
384
- throw new Error(`Invalid shape option. It must provide the url`);
385
- }
386
- if (options.signal && !(options.signal instanceof AbortSignal)) {
387
- throw new Error(
388
- `Invalid signal option. It must be an instance of AbortSignal.`
389
- );
390
- }
391
- if (options.offset !== void 0 && options.offset !== `-1` && !options.shapeId) {
392
- throw new Error(
393
- `shapeId is required if this isn't an initial fetch (i.e. offset > -1)`
394
- );
395
- }
396
- }
397
- fetchWithBackoff(url) {
398
- return __async(this, null, function* () {
399
- const { initialDelay, maxDelay, multiplier } = this.backoffOptions;
400
- const signal = this.options.signal;
401
- let delay = initialDelay;
402
- let attempt = 0;
403
- while (true) {
404
- try {
405
- const result = yield this.fetchClient(url.toString(), { signal });
406
- if (result.ok) {
407
- if (this.options.subscribe) {
408
- this.connected = true;
409
- }
410
- return result;
411
- } else throw yield FetchError.fromResponse(result, url.toString());
412
- } catch (e) {
413
- this.connected = false;
414
- if (signal == null ? void 0 : signal.aborted) {
415
- return void 0;
416
- } else if (e instanceof FetchError && e.status >= 400 && e.status < 500) {
417
- throw e;
418
- } else {
419
- yield new Promise((resolve) => setTimeout(resolve, delay));
420
- delay = Math.min(delay * multiplier, maxDelay);
421
- attempt++;
422
- console.log(`Retry attempt #${attempt} after ${delay}ms`);
423
- }
424
- }
425
- }
426
- });
519
+ if (options.offset !== void 0 && options.offset !== `-1` && !options.shapeId) {
520
+ throw new Error(
521
+ `shapeId is required if this isn't an initial fetch (i.e. offset > -1)`
522
+ );
427
523
  }
428
- };
524
+ return;
525
+ }
526
+
527
+ // src/shape.ts
528
+ var _stream, _data, _subscribers2, _hasNotifiedSubscribersUpToDate, _error, _Shape_instances, process_fn, handleError_fn, notify_fn;
429
529
  var Shape = class {
430
530
  constructor(stream) {
431
- this.data = /* @__PURE__ */ new Map();
432
- this.subscribers = /* @__PURE__ */ new Map();
433
- this.error = false;
434
- this.hasNotifiedSubscribersUpToDate = false;
435
- this.stream = stream;
436
- this.stream.subscribe(this.process.bind(this), this.handleError.bind(this));
437
- const unsubscribe = this.stream.subscribeOnceToUpToDate(
531
+ __privateAdd(this, _Shape_instances);
532
+ __privateAdd(this, _stream);
533
+ __privateAdd(this, _data, /* @__PURE__ */ new Map());
534
+ __privateAdd(this, _subscribers2, /* @__PURE__ */ new Map());
535
+ __privateAdd(this, _hasNotifiedSubscribersUpToDate, false);
536
+ __privateAdd(this, _error, false);
537
+ __privateSet(this, _stream, stream);
538
+ __privateGet(this, _stream).subscribe(
539
+ __privateMethod(this, _Shape_instances, process_fn).bind(this),
540
+ __privateMethod(this, _Shape_instances, handleError_fn).bind(this)
541
+ );
542
+ const unsubscribe = __privateGet(this, _stream).subscribeOnceToUpToDate(
438
543
  () => {
439
544
  unsubscribe();
440
545
  },
441
546
  (e) => {
442
- this.handleError(e);
547
+ __privateMethod(this, _Shape_instances, handleError_fn).call(this, e);
443
548
  throw e;
444
549
  }
445
550
  );
446
551
  }
447
- lastSynced() {
448
- return this.stream.lastSynced();
449
- }
450
- isConnected() {
451
- return this.stream.isConnected();
452
- }
453
- /** True during initial fetch. False afterwise. */
454
- isLoading() {
455
- return this.stream.isLoading();
552
+ get isUpToDate() {
553
+ return __privateGet(this, _stream).isUpToDate;
456
554
  }
457
555
  get value() {
458
- return new Promise((resolve) => {
459
- if (this.stream.isUpToDate) {
556
+ return new Promise((resolve, reject) => {
557
+ if (__privateGet(this, _stream).isUpToDate) {
460
558
  resolve(this.valueSync);
461
559
  } else {
462
- const unsubscribe = this.stream.subscribeOnceToUpToDate(
463
- () => {
464
- unsubscribe();
465
- resolve(this.valueSync);
466
- },
467
- (e) => {
468
- throw e;
469
- }
470
- );
560
+ const unsubscribe = this.subscribe((shapeData) => {
561
+ unsubscribe();
562
+ if (__privateGet(this, _error)) reject(__privateGet(this, _error));
563
+ resolve(shapeData);
564
+ });
471
565
  }
472
566
  });
473
567
  }
474
568
  get valueSync() {
475
- return this.data;
569
+ return __privateGet(this, _data);
570
+ }
571
+ get error() {
572
+ return __privateGet(this, _error);
573
+ }
574
+ /** Unix time at which we last synced. Undefined when `isLoading` is true. */
575
+ lastSyncedAt() {
576
+ return __privateGet(this, _stream).lastSyncedAt();
577
+ }
578
+ /** Time elapsed since last sync (in ms). Infinity if we did not yet sync. */
579
+ lastSynced() {
580
+ return __privateGet(this, _stream).lastSynced();
581
+ }
582
+ /** True during initial fetch. False afterwise. */
583
+ isLoading() {
584
+ return __privateGet(this, _stream).isLoading();
585
+ }
586
+ /** Indicates if we are connected to the Electric sync service. */
587
+ isConnected() {
588
+ return __privateGet(this, _stream).isConnected();
476
589
  }
477
590
  subscribe(callback) {
478
591
  const subscriptionId = Math.random();
479
- this.subscribers.set(subscriptionId, callback);
592
+ __privateGet(this, _subscribers2).set(subscriptionId, callback);
480
593
  return () => {
481
- this.subscribers.delete(subscriptionId);
594
+ __privateGet(this, _subscribers2).delete(subscriptionId);
482
595
  };
483
596
  }
484
597
  unsubscribeAll() {
485
- this.subscribers.clear();
598
+ __privateGet(this, _subscribers2).clear();
486
599
  }
487
600
  get numSubscribers() {
488
- return this.subscribers.size;
601
+ return __privateGet(this, _subscribers2).size;
489
602
  }
490
- process(messages) {
491
- let dataMayHaveChanged = false;
492
- let isUpToDate = false;
493
- let newlyUpToDate = false;
494
- messages.forEach((message) => {
495
- if (isChangeMessage(message)) {
496
- dataMayHaveChanged = [`insert`, `update`, `delete`].includes(
497
- message.headers.operation
498
- );
499
- switch (message.headers.operation) {
500
- case `insert`:
501
- this.data.set(message.key, message.value);
502
- break;
503
- case `update`:
504
- this.data.set(message.key, __spreadValues(__spreadValues({}, this.data.get(message.key)), message.value));
505
- break;
506
- case `delete`:
507
- this.data.delete(message.key);
508
- break;
509
- }
510
- }
511
- if (isControlMessage(message)) {
512
- switch (message.headers.control) {
513
- case `up-to-date`:
514
- isUpToDate = true;
515
- if (!this.hasNotifiedSubscribersUpToDate) {
516
- newlyUpToDate = true;
517
- }
518
- break;
519
- case `must-refetch`:
520
- this.data.clear();
521
- this.error = false;
522
- isUpToDate = false;
523
- newlyUpToDate = false;
524
- break;
525
- }
603
+ };
604
+ _stream = new WeakMap();
605
+ _data = new WeakMap();
606
+ _subscribers2 = new WeakMap();
607
+ _hasNotifiedSubscribersUpToDate = new WeakMap();
608
+ _error = new WeakMap();
609
+ _Shape_instances = new WeakSet();
610
+ process_fn = function(messages) {
611
+ let dataMayHaveChanged = false;
612
+ let isUpToDate = false;
613
+ let newlyUpToDate = false;
614
+ messages.forEach((message) => {
615
+ if (isChangeMessage(message)) {
616
+ dataMayHaveChanged = [`insert`, `update`, `delete`].includes(
617
+ message.headers.operation
618
+ );
619
+ switch (message.headers.operation) {
620
+ case `insert`:
621
+ __privateGet(this, _data).set(message.key, message.value);
622
+ break;
623
+ case `update`:
624
+ __privateGet(this, _data).set(message.key, __spreadValues(__spreadValues({}, __privateGet(this, _data).get(message.key)), message.value));
625
+ break;
626
+ case `delete`:
627
+ __privateGet(this, _data).delete(message.key);
628
+ break;
526
629
  }
527
- });
528
- if (newlyUpToDate || isUpToDate && dataMayHaveChanged) {
529
- this.hasNotifiedSubscribersUpToDate = true;
530
- this.notify();
531
630
  }
532
- }
533
- handleError(e) {
534
- if (e instanceof FetchError) {
535
- this.error = e;
536
- this.notify();
631
+ if (isControlMessage(message)) {
632
+ switch (message.headers.control) {
633
+ case `up-to-date`:
634
+ isUpToDate = true;
635
+ if (!__privateGet(this, _hasNotifiedSubscribersUpToDate)) {
636
+ newlyUpToDate = true;
637
+ }
638
+ break;
639
+ case `must-refetch`:
640
+ __privateGet(this, _data).clear();
641
+ __privateSet(this, _error, false);
642
+ isUpToDate = false;
643
+ newlyUpToDate = false;
644
+ break;
645
+ }
537
646
  }
647
+ });
648
+ if (newlyUpToDate || isUpToDate && dataMayHaveChanged) {
649
+ __privateSet(this, _hasNotifiedSubscribersUpToDate, true);
650
+ __privateMethod(this, _Shape_instances, notify_fn).call(this);
538
651
  }
539
- notify() {
540
- this.subscribers.forEach((callback) => {
541
- callback(this.valueSync);
542
- });
652
+ };
653
+ handleError_fn = function(e) {
654
+ if (e instanceof FetchError) {
655
+ __privateSet(this, _error, e);
656
+ __privateMethod(this, _Shape_instances, notify_fn).call(this);
543
657
  }
544
658
  };
659
+ notify_fn = function() {
660
+ __privateGet(this, _subscribers2).forEach((callback) => {
661
+ callback(this.valueSync);
662
+ });
663
+ };
545
664
  export {
546
665
  BackoffDefaults,
547
666
  FetchError,