@electric-sql/client 0.6.1 → 0.6.3
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 +22 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.browser.mjs +1 -1
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.legacy-esm.js +22 -3
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +22 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +26 -2
- package/src/constants.ts +3 -0
- package/src/fetch.ts +5 -0
package/src/client.ts
CHANGED
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
} from './fetch'
|
|
18
18
|
import {
|
|
19
19
|
CHUNK_LAST_OFFSET_HEADER,
|
|
20
|
+
LIVE_CACHE_BUSTER_HEADER,
|
|
21
|
+
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
22
|
+
COLUMNS_QUERY_PARAM,
|
|
20
23
|
LIVE_QUERY_PARAM,
|
|
21
24
|
OFFSET_QUERY_PARAM,
|
|
22
25
|
SHAPE_ID_HEADER,
|
|
@@ -35,9 +38,16 @@ export interface ShapeStreamOptions<T = never> {
|
|
|
35
38
|
*/
|
|
36
39
|
url: string
|
|
37
40
|
/**
|
|
38
|
-
* where clauses for the shape.
|
|
41
|
+
* The where clauses for the shape.
|
|
39
42
|
*/
|
|
40
43
|
where?: string
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The columns to include in the shape.
|
|
47
|
+
* Must include primary keys, and can only inlude valid columns.
|
|
48
|
+
*/
|
|
49
|
+
columns?: string[]
|
|
50
|
+
|
|
41
51
|
/**
|
|
42
52
|
* The "offset" on the shape log. This is typically not set as the ShapeStream
|
|
43
53
|
* will handle this automatically. A common scenario where you might pass an offset
|
|
@@ -143,6 +153,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
143
153
|
>()
|
|
144
154
|
|
|
145
155
|
#lastOffset: Offset
|
|
156
|
+
#liveCacheBuster: string // Seconds since our Electric Epoch 😎
|
|
146
157
|
#lastSyncedAt?: number // unix time
|
|
147
158
|
#isUpToDate: boolean = false
|
|
148
159
|
#connected: boolean = false
|
|
@@ -153,6 +164,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
153
164
|
validateOptions(options)
|
|
154
165
|
this.options = { subscribe: true, ...options }
|
|
155
166
|
this.#lastOffset = this.options.offset ?? `-1`
|
|
167
|
+
this.#liveCacheBuster = ``
|
|
156
168
|
this.#shapeId = this.options.shapeId
|
|
157
169
|
this.#messageParser = new MessageParser<T>(options.parser)
|
|
158
170
|
|
|
@@ -184,7 +196,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
184
196
|
async start() {
|
|
185
197
|
this.#isUpToDate = false
|
|
186
198
|
|
|
187
|
-
const { url, where, signal } = this.options
|
|
199
|
+
const { url, where, columns, signal } = this.options
|
|
188
200
|
|
|
189
201
|
try {
|
|
190
202
|
while (
|
|
@@ -193,10 +205,16 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
193
205
|
) {
|
|
194
206
|
const fetchUrl = new URL(url)
|
|
195
207
|
if (where) fetchUrl.searchParams.set(WHERE_QUERY_PARAM, where)
|
|
208
|
+
if (columns && columns.length > 0)
|
|
209
|
+
fetchUrl.searchParams.set(COLUMNS_QUERY_PARAM, columns.join(`,`))
|
|
196
210
|
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, this.#lastOffset)
|
|
197
211
|
|
|
198
212
|
if (this.#isUpToDate) {
|
|
199
213
|
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`)
|
|
214
|
+
fetchUrl.searchParams.set(
|
|
215
|
+
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
216
|
+
this.#liveCacheBuster
|
|
217
|
+
)
|
|
200
218
|
}
|
|
201
219
|
|
|
202
220
|
if (this.#shapeId) {
|
|
@@ -248,6 +266,11 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
248
266
|
this.#lastOffset = lastOffset as Offset
|
|
249
267
|
}
|
|
250
268
|
|
|
269
|
+
const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER)
|
|
270
|
+
if (liveCacheBuster) {
|
|
271
|
+
this.#liveCacheBuster = liveCacheBuster
|
|
272
|
+
}
|
|
273
|
+
|
|
251
274
|
const getSchema = (): Schema => {
|
|
252
275
|
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER)
|
|
253
276
|
return schemaHeader ? JSON.parse(schemaHeader) : {}
|
|
@@ -376,6 +399,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
|
|
|
376
399
|
*/
|
|
377
400
|
#reset(shapeId?: string) {
|
|
378
401
|
this.#lastOffset = `-1`
|
|
402
|
+
this.#liveCacheBuster = ``
|
|
379
403
|
this.#shapeId = shapeId
|
|
380
404
|
this.#isUpToDate = false
|
|
381
405
|
this.#connected = false
|
package/src/constants.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export const SHAPE_ID_HEADER = `electric-shape-id`
|
|
2
|
+
export const LIVE_CACHE_BUSTER_HEADER = `electric-next-cursor`
|
|
3
|
+
export const LIVE_CACHE_BUSTER_QUERY_PARAM = `cursor`
|
|
2
4
|
export const CHUNK_LAST_OFFSET_HEADER = `electric-chunk-last-offset`
|
|
3
5
|
export const CHUNK_UP_TO_DATE_HEADER = `electric-chunk-up-to-date`
|
|
4
6
|
export const SHAPE_SCHEMA_HEADER = `electric-schema`
|
|
5
7
|
export const SHAPE_ID_QUERY_PARAM = `shape_id`
|
|
6
8
|
export const OFFSET_QUERY_PARAM = `offset`
|
|
7
9
|
export const WHERE_QUERY_PARAM = `where`
|
|
10
|
+
export const COLUMNS_QUERY_PARAM = `columns`
|
|
8
11
|
export const LIVE_QUERY_PARAM = `live`
|
package/src/fetch.ts
CHANGED
|
@@ -8,6 +8,10 @@ import {
|
|
|
8
8
|
} from './constants'
|
|
9
9
|
import { FetchError, FetchBackoffAbortError } from './error'
|
|
10
10
|
|
|
11
|
+
// Some specific 4xx and 5xx HTTP status codes that we definitely
|
|
12
|
+
// want to retry
|
|
13
|
+
const HTTP_RETRY_STATUS_CODES = [429]
|
|
14
|
+
|
|
11
15
|
export interface BackoffOptions {
|
|
12
16
|
/**
|
|
13
17
|
* Initial delay before retrying in milliseconds
|
|
@@ -63,6 +67,7 @@ export function createFetchWithBackoff(
|
|
|
63
67
|
throw new FetchBackoffAbortError()
|
|
64
68
|
} else if (
|
|
65
69
|
e instanceof FetchError &&
|
|
70
|
+
!HTTP_RETRY_STATUS_CODES.includes(e.status) &&
|
|
66
71
|
e.status >= 400 &&
|
|
67
72
|
e.status < 500
|
|
68
73
|
) {
|