@electric-sql/client 1.0.13 → 1.1.0
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/cjs/index.cjs +10 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +52 -85
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +52 -85
- package/dist/index.legacy-esm.js +10 -26
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +10 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +18 -51
- package/src/constants.ts +4 -0
- package/src/fetch.ts +4 -6
- package/src/helpers.ts +0 -38
- package/src/index.ts +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -118,52 +118,6 @@ type Parser<Extensions = never> = {
|
|
|
118
118
|
};
|
|
119
119
|
type TransformFunction<Extensions = never> = (message: Row<Extensions>) => Row<Extensions>;
|
|
120
120
|
|
|
121
|
-
/**
|
|
122
|
-
* Type guard for checking {@link Message} is {@link ChangeMessage}.
|
|
123
|
-
*
|
|
124
|
-
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)
|
|
125
|
-
* for information on how to use type guards.
|
|
126
|
-
*
|
|
127
|
-
* @param message - the message to check
|
|
128
|
-
* @returns true if the message is a {@link ChangeMessage}
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* ```ts
|
|
132
|
-
* if (isChangeMessage(message)) {
|
|
133
|
-
* const msgChng: ChangeMessage = message // Ok
|
|
134
|
-
* const msgCtrl: ControlMessage = message // Err, type mismatch
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
declare function isChangeMessage<T extends Row<unknown> = Row>(message: Message<T>): message is ChangeMessage<T>;
|
|
139
|
-
/**
|
|
140
|
-
* Type guard for checking {@link Message} is {@link ControlMessage}.
|
|
141
|
-
*
|
|
142
|
-
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)
|
|
143
|
-
* for information on how to use type guards.
|
|
144
|
-
*
|
|
145
|
-
* @param message - the message to check
|
|
146
|
-
* @returns true if the message is a {@link ControlMessage}
|
|
147
|
-
*
|
|
148
|
-
* * @example
|
|
149
|
-
* ```ts
|
|
150
|
-
* if (isControlMessage(message)) {
|
|
151
|
-
* const msgChng: ChangeMessage = message // Err, type mismatch
|
|
152
|
-
* const msgCtrl: ControlMessage = message // Ok
|
|
153
|
-
* }
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
declare function isControlMessage<T extends Row<unknown> = Row>(message: Message<T>): message is ControlMessage;
|
|
157
|
-
/**
|
|
158
|
-
* Checks if a transaction is visible in a snapshot.
|
|
159
|
-
*
|
|
160
|
-
* @param txid - the transaction id to check
|
|
161
|
-
* @param snapshot - the information about the snapshot
|
|
162
|
-
* @returns true if the transaction is visible in the snapshot
|
|
163
|
-
*/
|
|
164
|
-
declare function isVisibleInSnapshot(txid: number | bigint | `${bigint}`, snapshot: PostgresSnapshot | NormalizedPgSnapshot): boolean;
|
|
165
|
-
type ShardSubdomainOption = `always` | `localhost` | `never` | boolean;
|
|
166
|
-
|
|
167
121
|
declare class FetchError extends Error {
|
|
168
122
|
url: string;
|
|
169
123
|
status: number;
|
|
@@ -324,49 +278,17 @@ interface ShapeStreamOptions<T = never> {
|
|
|
324
278
|
*/
|
|
325
279
|
subscribe?: boolean;
|
|
326
280
|
/**
|
|
327
|
-
*
|
|
281
|
+
* @deprecated No longer experimental, use {@link liveSse} instead.
|
|
328
282
|
*/
|
|
329
283
|
experimentalLiveSse?: boolean;
|
|
330
284
|
/**
|
|
331
|
-
*
|
|
285
|
+
* Use Server-Sent Events (SSE) for live updates.
|
|
332
286
|
*/
|
|
333
|
-
|
|
287
|
+
liveSse?: boolean;
|
|
334
288
|
/**
|
|
335
|
-
*
|
|
336
|
-
* This is useful in local development and is enabled by default for localhost URLs.
|
|
337
|
-
*
|
|
338
|
-
* See https://electric-sql.com/docs/guides/troubleshooting#slow-shapes-mdash-why-are-my-shapes-slow-in-the-browser-in-local-development
|
|
339
|
-
*
|
|
340
|
-
* When sharded, each shape stream gets a unique subdomain (e.g., `a7f2c.localhost`),
|
|
341
|
-
* which bypasses the browser HTTP/1.1 connection limits. This avoids the need to serve
|
|
342
|
-
* the development server over HTTP/2 (and thus HTTPS) in development.
|
|
343
|
-
*
|
|
344
|
-
* Options:
|
|
345
|
-
* - `'localhost'` - Automatically shard `localhost` and `*.localhost` URLs (the default)
|
|
346
|
-
* - `'always'` - Shard URLs regardless of the hostname
|
|
347
|
-
* - `'never'` - Disable sharding
|
|
348
|
-
* - `true` - Alias for `'always'`
|
|
349
|
-
* - `false` - Alias for `'never'`
|
|
350
|
-
*
|
|
351
|
-
* @default 'localhost'
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* { url: 'http://localhost:3000/v1/shape', shardSubdomain: 'localhost' }
|
|
355
|
-
* // → http://a1c2f.localhost:3000/v1/shape
|
|
356
|
-
*
|
|
357
|
-
* @example
|
|
358
|
-
* { url: 'https://api.example.com', shardSubdomain: 'localhost' }
|
|
359
|
-
* // → https://api.example.com
|
|
360
|
-
*
|
|
361
|
-
* @example
|
|
362
|
-
* { url: 'https://localhost:3000', shardSubdomain: 'never' }
|
|
363
|
-
* // → https://localhost:3000
|
|
364
|
-
*
|
|
365
|
-
* @example
|
|
366
|
-
* { url: 'https://api.example.com', shardSubdomain: 'always' }
|
|
367
|
-
* // → https://b2d3g.api.example.com
|
|
289
|
+
* Initial data loading mode
|
|
368
290
|
*/
|
|
369
|
-
|
|
291
|
+
log?: LogMode;
|
|
370
292
|
signal?: AbortSignal;
|
|
371
293
|
fetchClient?: typeof fetch;
|
|
372
294
|
backoffOptions?: BackoffOptions;
|
|
@@ -430,7 +352,7 @@ interface ShapeStreamInterface<T extends Row<unknown> = Row> {
|
|
|
430
352
|
* ```
|
|
431
353
|
* const stream = new ShapeStream({
|
|
432
354
|
* url: `http://localhost:3000/v1/shape`,
|
|
433
|
-
*
|
|
355
|
+
* liveSse: true
|
|
434
356
|
* })
|
|
435
357
|
* ```
|
|
436
358
|
*
|
|
@@ -572,4 +494,49 @@ declare class Shape<T extends Row<unknown> = Row> {
|
|
|
572
494
|
get numSubscribers(): number;
|
|
573
495
|
}
|
|
574
496
|
|
|
575
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Type guard for checking {@link Message} is {@link ChangeMessage}.
|
|
499
|
+
*
|
|
500
|
+
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)
|
|
501
|
+
* for information on how to use type guards.
|
|
502
|
+
*
|
|
503
|
+
* @param message - the message to check
|
|
504
|
+
* @returns true if the message is a {@link ChangeMessage}
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* ```ts
|
|
508
|
+
* if (isChangeMessage(message)) {
|
|
509
|
+
* const msgChng: ChangeMessage = message // Ok
|
|
510
|
+
* const msgCtrl: ControlMessage = message // Err, type mismatch
|
|
511
|
+
* }
|
|
512
|
+
* ```
|
|
513
|
+
*/
|
|
514
|
+
declare function isChangeMessage<T extends Row<unknown> = Row>(message: Message<T>): message is ChangeMessage<T>;
|
|
515
|
+
/**
|
|
516
|
+
* Type guard for checking {@link Message} is {@link ControlMessage}.
|
|
517
|
+
*
|
|
518
|
+
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)
|
|
519
|
+
* for information on how to use type guards.
|
|
520
|
+
*
|
|
521
|
+
* @param message - the message to check
|
|
522
|
+
* @returns true if the message is a {@link ControlMessage}
|
|
523
|
+
*
|
|
524
|
+
* * @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* if (isControlMessage(message)) {
|
|
527
|
+
* const msgChng: ChangeMessage = message // Err, type mismatch
|
|
528
|
+
* const msgCtrl: ControlMessage = message // Ok
|
|
529
|
+
* }
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
declare function isControlMessage<T extends Row<unknown> = Row>(message: Message<T>): message is ControlMessage;
|
|
533
|
+
/**
|
|
534
|
+
* Checks if a transaction is visible in a snapshot.
|
|
535
|
+
*
|
|
536
|
+
* @param txid - the transaction id to check
|
|
537
|
+
* @param snapshot - the information about the snapshot
|
|
538
|
+
* @returns true if the transaction is visible in the snapshot
|
|
539
|
+
*/
|
|
540
|
+
declare function isVisibleInSnapshot(txid: number | bigint | `${bigint}`, snapshot: PostgresSnapshot | NormalizedPgSnapshot): boolean;
|
|
541
|
+
|
|
542
|
+
export { BackoffDefaults, type BackoffOptions, type BitColumn, type BpcharColumn, type ChangeMessage, type ColumnInfo, type CommonColumnProps, type ControlMessage, ELECTRIC_PROTOCOL_QUERY_PARAMS, type ExternalHeadersRecord, type ExternalParamsRecord, FetchError, type GetExtensions, type IntervalColumn, type IntervalColumnWithPrecision, type LogMode, type MaybePromise, type Message, type NormalizedPgSnapshot, type NumericColumn, type Offset, type Operation, type PostgresParams, type PostgresSnapshot, type RegularColumn, type Row, type Schema, Shape, type ShapeChangedCallback, type ShapeData, ShapeStream, type ShapeStreamInterface, type ShapeStreamOptions, type SnapshotMetadata, type SubsetParams, type TimeColumn, type TypedMessages, type Value, type VarcharColumn, isChangeMessage, isControlMessage, isVisibleInSnapshot, resolveValue };
|
package/dist/index.legacy-esm.js
CHANGED
|
@@ -271,26 +271,6 @@ function isVisibleInSnapshot(txid, snapshot) {
|
|
|
271
271
|
const xip = snapshot.xip_list.map(BigInt);
|
|
272
272
|
return xid < xmin || xid < xmax && !xip.includes(xid);
|
|
273
273
|
}
|
|
274
|
-
function generateShardId() {
|
|
275
|
-
return Math.floor(Math.random() * 1048575).toString(16).padStart(5, `0`);
|
|
276
|
-
}
|
|
277
|
-
function isLocalhostUrl(url) {
|
|
278
|
-
const hostname = url.hostname.toLowerCase();
|
|
279
|
-
return hostname === `localhost` || hostname.endsWith(`.localhost`);
|
|
280
|
-
}
|
|
281
|
-
function applySubdomainSharding(originalUrl, option = `localhost`) {
|
|
282
|
-
if (option === `never` || option === false) {
|
|
283
|
-
return originalUrl;
|
|
284
|
-
}
|
|
285
|
-
const url = new URL(originalUrl);
|
|
286
|
-
const shouldShard = option === `always` || option === true || option === `localhost` && isLocalhostUrl(url);
|
|
287
|
-
if (!shouldShard) {
|
|
288
|
-
return originalUrl;
|
|
289
|
-
}
|
|
290
|
-
const shardId = generateShardId();
|
|
291
|
-
url.hostname = `${shardId}.${url.hostname}`;
|
|
292
|
-
return url.toString();
|
|
293
|
-
}
|
|
294
274
|
|
|
295
275
|
// src/constants.ts
|
|
296
276
|
var LIVE_CACHE_BUSTER_HEADER = `electric-cursor`;
|
|
@@ -309,6 +289,7 @@ var WHERE_QUERY_PARAM = `where`;
|
|
|
309
289
|
var REPLICA_PARAM = `replica`;
|
|
310
290
|
var WHERE_PARAMS_PARAM = `params`;
|
|
311
291
|
var EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`;
|
|
292
|
+
var LIVE_SSE_QUERY_PARAM = `live_sse`;
|
|
312
293
|
var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
|
|
313
294
|
var PAUSE_STREAM = `pause-stream`;
|
|
314
295
|
var LOG_MODE_QUERY_PARAM = `log`;
|
|
@@ -379,6 +360,7 @@ function createFetchWithBackoff(fetchClient, backoffOptions = BackoffDefaults) {
|
|
|
379
360
|
var NO_BODY_STATUS_CODES = [201, 204, 205];
|
|
380
361
|
function createFetchWithConsumedMessages(fetchClient) {
|
|
381
362
|
return async (...args) => {
|
|
363
|
+
var _a, _b;
|
|
382
364
|
const url = args[0];
|
|
383
365
|
const res = await fetchClient(...args);
|
|
384
366
|
try {
|
|
@@ -388,6 +370,9 @@ function createFetchWithConsumedMessages(fetchClient) {
|
|
|
388
370
|
const text = await res.text();
|
|
389
371
|
return new Response(text, res);
|
|
390
372
|
} catch (err) {
|
|
373
|
+
if ((_b = (_a = args[1]) == null ? void 0 : _a.signal) == null ? void 0 : _b.aborted) {
|
|
374
|
+
throw new FetchBackoffAbortError();
|
|
375
|
+
}
|
|
391
376
|
throw new FetchError(
|
|
392
377
|
res.status,
|
|
393
378
|
void 0,
|
|
@@ -769,10 +754,6 @@ var ShapeStream = class {
|
|
|
769
754
|
var _a, _b, _c, _d;
|
|
770
755
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
771
756
|
validateOptions(this.options);
|
|
772
|
-
this.options.url = applySubdomainSharding(
|
|
773
|
-
this.options.url,
|
|
774
|
-
this.options.shardSubdomain
|
|
775
|
-
);
|
|
776
757
|
__privateSet(this, _lastOffset, (_a = this.options.offset) != null ? _a : `-1`);
|
|
777
758
|
__privateSet(this, _liveCacheBuster, ``);
|
|
778
759
|
__privateSet(this, _shapeHandle, this.options.handle);
|
|
@@ -1010,7 +991,7 @@ requestShape_fn = async function() {
|
|
|
1010
991
|
}
|
|
1011
992
|
const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER] || `${__privateGet(this, _shapeHandle)}-next`;
|
|
1012
993
|
__privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
|
|
1013
|
-
await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
|
|
994
|
+
await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, Array.isArray(e.json) ? e.json : [e.json]);
|
|
1014
995
|
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
1015
996
|
} else {
|
|
1016
997
|
__privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
|
|
@@ -1153,8 +1134,11 @@ onMessages_fn = async function(batch, isSseMessage = false) {
|
|
|
1153
1134
|
}
|
|
1154
1135
|
};
|
|
1155
1136
|
fetchShape_fn = async function(opts) {
|
|
1156
|
-
|
|
1137
|
+
var _a;
|
|
1138
|
+
const useSse = (_a = this.options.liveSse) != null ? _a : this.options.experimentalLiveSse;
|
|
1139
|
+
if (__privateGet(this, _isUpToDate) && useSse && !__privateGet(this, _isRefreshing) && !opts.resumingFromPause) {
|
|
1157
1140
|
opts.fetchUrl.searchParams.set(EXPERIMENTAL_LIVE_SSE_QUERY_PARAM, `true`);
|
|
1141
|
+
opts.fetchUrl.searchParams.set(LIVE_SSE_QUERY_PARAM, `true`);
|
|
1158
1142
|
return __privateMethod(this, _ShapeStream_instances, requestShapeSSE_fn).call(this, opts);
|
|
1159
1143
|
}
|
|
1160
1144
|
return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
|