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