@electric-sql/client 1.0.11 → 1.0.13
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 +25 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +84 -47
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +84 -47
- package/dist/index.legacy-esm.js +25 -1
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +25 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +50 -3
- package/src/helpers.ts +38 -0
- package/src/index.ts +1 -0
package/src/client.ts
CHANGED
|
@@ -9,7 +9,13 @@ import {
|
|
|
9
9
|
SnapshotMetadata,
|
|
10
10
|
} from './types'
|
|
11
11
|
import { MessageParser, Parser, TransformFunction } from './parser'
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
getOffset,
|
|
14
|
+
isUpToDateMessage,
|
|
15
|
+
isChangeMessage,
|
|
16
|
+
applySubdomainSharding,
|
|
17
|
+
ShardSubdomainOption,
|
|
18
|
+
} from './helpers'
|
|
13
19
|
import {
|
|
14
20
|
FetchError,
|
|
15
21
|
FetchBackoffAbortError,
|
|
@@ -280,7 +286,44 @@ export interface ShapeStreamOptions<T = never> {
|
|
|
280
286
|
/**
|
|
281
287
|
* Initial data loading mode
|
|
282
288
|
*/
|
|
283
|
-
|
|
289
|
+
log?: LogMode
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Enable subdomain sharding to bypass browser HTTP/1.1 connection limits.
|
|
293
|
+
* This is useful in local development and is enabled by default for localhost URLs.
|
|
294
|
+
*
|
|
295
|
+
* See https://electric-sql.com/docs/guides/troubleshooting#slow-shapes-mdash-why-are-my-shapes-slow-in-the-browser-in-local-development
|
|
296
|
+
*
|
|
297
|
+
* When sharded, each shape stream gets a unique subdomain (e.g., `a7f2c.localhost`),
|
|
298
|
+
* which bypasses the browser HTTP/1.1 connection limits. This avoids the need to serve
|
|
299
|
+
* the development server over HTTP/2 (and thus HTTPS) in development.
|
|
300
|
+
*
|
|
301
|
+
* Options:
|
|
302
|
+
* - `'localhost'` - Automatically shard `localhost` and `*.localhost` URLs (the default)
|
|
303
|
+
* - `'always'` - Shard URLs regardless of the hostname
|
|
304
|
+
* - `'never'` - Disable sharding
|
|
305
|
+
* - `true` - Alias for `'always'`
|
|
306
|
+
* - `false` - Alias for `'never'`
|
|
307
|
+
*
|
|
308
|
+
* @default 'localhost'
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* { url: 'http://localhost:3000/v1/shape', shardSubdomain: 'localhost' }
|
|
312
|
+
* // → http://a1c2f.localhost:3000/v1/shape
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* { url: 'https://api.example.com', shardSubdomain: 'localhost' }
|
|
316
|
+
* // → https://api.example.com
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* { url: 'https://localhost:3000', shardSubdomain: 'never' }
|
|
320
|
+
* // → https://localhost:3000
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* { url: 'https://api.example.com', shardSubdomain: 'always' }
|
|
324
|
+
* // → https://b2d3g.api.example.com
|
|
325
|
+
*/
|
|
326
|
+
shardSubdomain?: ShardSubdomainOption
|
|
284
327
|
|
|
285
328
|
signal?: AbortSignal
|
|
286
329
|
fetchClient?: typeof fetch
|
|
@@ -439,6 +482,10 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
439
482
|
constructor(options: ShapeStreamOptions<GetExtensions<T>>) {
|
|
440
483
|
this.options = { subscribe: true, ...options }
|
|
441
484
|
validateOptions(this.options)
|
|
485
|
+
this.options.url = applySubdomainSharding(
|
|
486
|
+
this.options.url,
|
|
487
|
+
this.options.shardSubdomain
|
|
488
|
+
)
|
|
442
489
|
this.#lastOffset = this.options.offset ?? `-1`
|
|
443
490
|
this.#liveCacheBuster = ``
|
|
444
491
|
this.#shapeHandle = this.options.handle
|
|
@@ -447,7 +494,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
447
494
|
options.transformer
|
|
448
495
|
)
|
|
449
496
|
this.#onError = this.options.onError
|
|
450
|
-
this.#mode = this.options.
|
|
497
|
+
this.#mode = this.options.log ?? `full`
|
|
451
498
|
|
|
452
499
|
const baseFetchClient =
|
|
453
500
|
options.fetchClient ??
|
package/src/helpers.ts
CHANGED
|
@@ -97,3 +97,41 @@ export function isVisibleInSnapshot(
|
|
|
97
97
|
|
|
98
98
|
return xid < xmin || (xid < xmax && !xip.includes(xid))
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
export function generateShardId(): string {
|
|
102
|
+
return Math.floor(Math.random() * 0xfffff)
|
|
103
|
+
.toString(16)
|
|
104
|
+
.padStart(5, `0`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function isLocalhostUrl(url: URL): boolean {
|
|
108
|
+
const hostname = url.hostname.toLowerCase()
|
|
109
|
+
return hostname === `localhost` || hostname.endsWith(`.localhost`)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type ShardSubdomainOption = `always` | `localhost` | `never` | boolean
|
|
113
|
+
|
|
114
|
+
export function applySubdomainSharding(
|
|
115
|
+
originalUrl: string,
|
|
116
|
+
option: ShardSubdomainOption = `localhost`
|
|
117
|
+
): string {
|
|
118
|
+
if (option === `never` || option === false) {
|
|
119
|
+
return originalUrl
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const url = new URL(originalUrl)
|
|
123
|
+
|
|
124
|
+
const shouldShard =
|
|
125
|
+
option === `always` ||
|
|
126
|
+
option === true ||
|
|
127
|
+
(option === `localhost` && isLocalhostUrl(url))
|
|
128
|
+
|
|
129
|
+
if (!shouldShard) {
|
|
130
|
+
return originalUrl
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const shardId = generateShardId()
|
|
134
|
+
url.hostname = `${shardId}.${url.hostname}`
|
|
135
|
+
|
|
136
|
+
return url.toString()
|
|
137
|
+
}
|