on-zero 0.6.7 → 0.6.8

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.
Files changed (48) hide show
  1. package/dist/cjs/helpers/createMutators.cjs +7 -2
  2. package/dist/cjs/helpers/createMutators.native.js +7 -2
  3. package/dist/cjs/helpers/createMutators.native.js.map +1 -1
  4. package/dist/cjs/helpers/createMutators.test.cjs +43 -0
  5. package/dist/cjs/helpers/createMutators.test.native.js +46 -0
  6. package/dist/cjs/helpers/createMutators.test.native.js.map +1 -0
  7. package/dist/cjs/httpPull/completeAck.test.cjs +69 -0
  8. package/dist/cjs/httpPull/completeAck.test.native.js +76 -0
  9. package/dist/cjs/httpPull/completeAck.test.native.js.map +1 -0
  10. package/dist/cjs/httpPull/transport.test.cjs +177 -1
  11. package/dist/cjs/httpPull/transport.test.native.js +192 -0
  12. package/dist/cjs/httpPull/transport.test.native.js.map +1 -1
  13. package/dist/cjs/httpPullTransport.cjs +138 -12
  14. package/dist/cjs/httpPullTransport.native.js +173 -13
  15. package/dist/cjs/httpPullTransport.native.js.map +1 -1
  16. package/dist/esm/helpers/createMutators.mjs +7 -2
  17. package/dist/esm/helpers/createMutators.mjs.map +1 -1
  18. package/dist/esm/helpers/createMutators.native.js +7 -2
  19. package/dist/esm/helpers/createMutators.native.js.map +1 -1
  20. package/dist/esm/helpers/createMutators.test.mjs +44 -0
  21. package/dist/esm/helpers/createMutators.test.mjs.map +1 -0
  22. package/dist/esm/helpers/createMutators.test.native.js +44 -0
  23. package/dist/esm/helpers/createMutators.test.native.js.map +1 -0
  24. package/dist/esm/httpPull/completeAck.test.mjs +70 -0
  25. package/dist/esm/httpPull/completeAck.test.mjs.map +1 -0
  26. package/dist/esm/httpPull/completeAck.test.native.js +74 -0
  27. package/dist/esm/httpPull/completeAck.test.native.js.map +1 -0
  28. package/dist/esm/httpPull/transport.test.mjs +176 -0
  29. package/dist/esm/httpPull/transport.test.mjs.map +1 -1
  30. package/dist/esm/httpPull/transport.test.native.js +192 -0
  31. package/dist/esm/httpPull/transport.test.native.js.map +1 -1
  32. package/dist/esm/httpPullTransport.mjs +138 -12
  33. package/dist/esm/httpPullTransport.mjs.map +1 -1
  34. package/dist/esm/httpPullTransport.native.js +173 -13
  35. package/dist/esm/httpPullTransport.native.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/helpers/createMutators.test.ts +51 -0
  38. package/src/helpers/createMutators.ts +7 -2
  39. package/src/httpPull/completeAck.test.ts +80 -0
  40. package/src/httpPull/transport.test.ts +134 -0
  41. package/src/httpPullTransport.ts +198 -13
  42. package/types/helpers/createMutators.d.ts.map +1 -1
  43. package/types/helpers/createMutators.test.d.ts +2 -0
  44. package/types/helpers/createMutators.test.d.ts.map +1 -0
  45. package/types/httpPull/completeAck.test.d.ts +2 -0
  46. package/types/httpPull/completeAck.test.d.ts.map +1 -0
  47. package/types/httpPullTransport.d.ts +4 -0
  48. package/types/httpPullTransport.d.ts.map +1 -1
@@ -25,16 +25,36 @@ type DesiredQueryPatchOp =
25
25
 
26
26
  type GotQueryPatchOp = { op: 'clear' } | { op: 'put' | 'del'; hash: string }
27
27
 
28
+ // a shipped desired-query put carries an AST (client-resolved by a
29
+ // queryTransform, or an ad-hoc query's inline ast) OR name+args for the server
30
+ // to resolve. name+args is the auth-sensitive path: the permission transform
31
+ // stays server-side, so a client cannot forge the AST.
32
+ type QueryPatchOp =
33
+ | { op: 'put'; hash: string; ast: unknown }
34
+ | { op: 'put'; hash: string; name: string; args: readonly unknown[] }
35
+ | { op: 'del'; hash: string }
36
+ | { op: 'clear' }
37
+
38
+ // transforms a named query's (name, args) into its Zero v51 AST. providing one
39
+ // turns the query-aware extension on and resolves desired queries CLIENT-side
40
+ // (ship the AST). use for a native host with no query registry, or a trusted
41
+ // harness. omit it (with queryForward) to ship name+args and resolve SERVER-side.
42
+ export type QueryTransform = (name: string, args: readonly unknown[]) => unknown
43
+
44
+ type ServerGotQueries = { version: number; patch: GotQueryPatchOp[] }
45
+
28
46
  type PullResponse =
29
47
  | {
30
48
  cookie: number
31
49
  lastMutationIDChanges: Record<string, number>
32
50
  rowsPatch: unknown[]
33
51
  unchanged?: false
52
+ gotQueries?: ServerGotQueries
34
53
  }
35
54
  | {
36
55
  cookie: number | null
37
56
  unchanged: true
57
+ gotQueries?: ServerGotQueries
38
58
  }
39
59
 
40
60
  type TransportState = {
@@ -44,6 +64,10 @@ type TransportState = {
44
64
  readonly nativeWebSocket: WebSocketConstructor | undefined
45
65
  readonly sockets: Set<ZeroHttpSocket>
46
66
  readonly pullIntervalMs: number | undefined
67
+ readonly wakeEnabled: boolean
68
+ readonly queryTransform: QueryTransform | undefined
69
+ readonly queryForward: boolean
70
+ readonly queryAware: boolean
47
71
  nextPokeID: number
48
72
  transientFailureCount: number
49
73
  }
@@ -64,6 +88,20 @@ export type HttpPullTransportOptions = {
64
88
  // when set, every open connection also pulls on this interval so
65
89
  // server-initiated changes arrive without a client-side trigger
66
90
  pullIntervalMs?: number
91
+ // when true, each connection also opens a notification-only wake socket to
92
+ // <origin>/wake and pulls immediately on any wake, demoting the interval
93
+ // poll to a safety net. the wake channel carries no data ("pull now" only)
94
+ // and zero correctness weight: a lost or duplicated wake can never cause
95
+ // missed or wrong data because convergence comes from the pull protocol.
96
+ wake?: boolean
97
+ // when provided, the query-aware extension is on and desired queries are
98
+ // resolved client-side to an AST before shipping (native host / trusted
99
+ // harness). omit for the baseline dialect (client-local got-query synthesis).
100
+ queryTransform?: QueryTransform
101
+ // turns the query-aware extension on WITHOUT a client-side transform: desired
102
+ // queries ship as name+args for the SERVER (consumer worker) to resolve with
103
+ // auth. the production path for permission-transformed queries.
104
+ queryForward?: boolean
67
105
  }
68
106
 
69
107
  export function installHttpPullTransport(
@@ -85,6 +123,10 @@ export function installHttpPullTransport(
85
123
  nativeWebSocket: previousWebSocket,
86
124
  sockets: new Set(),
87
125
  pullIntervalMs: opts.pullIntervalMs,
126
+ wakeEnabled: opts.wake ?? false,
127
+ queryTransform: opts.queryTransform,
128
+ queryForward: opts.queryForward === true,
129
+ queryAware: opts.queryTransform !== undefined || opts.queryForward === true,
88
130
  nextPokeID: 0,
89
131
  transientFailureCount: 0,
90
132
  }
@@ -161,12 +203,22 @@ class ZeroHttpSocket {
161
203
  private readonly wsid: string
162
204
  private cookie: string | null
163
205
  private pendingGotQueriesPatch: GotQueryPatchOp[] = []
206
+ // query-aware extension state: the accumulated un-acked desired-query delta
207
+ // to ship, a client-side query-state version that bumps on each change, and
208
+ // the version/length of the delta the in-flight pull sent (to clear the
209
+ // acked prefix on the server's ack).
210
+ private desiredQueryPatch: QueryPatchOp[] = []
211
+ private queryVersion = 0
212
+ private sentQueryVersion: number | undefined
213
+ private sentQueryPatchLen = 0
164
214
  private pullInFlight: Promise<void> | undefined
165
215
  private pullAfterCurrent = false
166
216
  private pushChain: Promise<void> = Promise.resolve()
167
217
  private nextLocalCookieID: number
168
218
  private openTimer: ReturnType<typeof setTimeout> | undefined
169
219
  private pullTimer: ReturnType<typeof setInterval> | undefined
220
+ private wakeSocket: { close(): void } | undefined
221
+ private wakeReconnectTimer: ReturnType<typeof setTimeout> | undefined
170
222
 
171
223
  constructor(
172
224
  private readonly state: TransportState,
@@ -245,6 +297,7 @@ class ZeroHttpSocket {
245
297
  if (this.readyState === this.CLOSED) return
246
298
  if (this.openTimer) clearTimeout(this.openTimer)
247
299
  if (this.pullTimer) clearInterval(this.pullTimer)
300
+ this.closeWakeChannel()
248
301
  this.readyState = this.CLOSED
249
302
  this.state.sockets.delete(this)
250
303
  this.emit('close', { code, reason, wasClean: code <= 1001 })
@@ -253,8 +306,9 @@ class ZeroHttpSocket {
253
306
  pull(): Promise<void> {
254
307
  if (this.readyState !== this.OPEN) return Promise.resolve()
255
308
  if (this.pullInFlight) return this.pullInFlight
256
- this.pullInFlight = this.fetchPull(this.clientGroupID, this.cookie)
309
+ this.pullInFlight = this.fetchPull(this.clientGroupID, this.cookie, true)
257
310
  .then((response) => {
311
+ if (this.state.queryAware) this.applyServerGotQueries(response)
258
312
  if (response.unchanged) {
259
313
  this.emitGotQueriesPatch(response.cookie)
260
314
  return
@@ -285,13 +339,104 @@ class ZeroHttpSocket {
285
339
  this.run(this.pull())
286
340
  }, this.state.pullIntervalMs)
287
341
  }
342
+ if (this.state.wakeEnabled) this.openWakeChannel()
343
+ }
344
+
345
+ // notification-only wake channel: a real WebSocket to <origin>/wake that
346
+ // carries no data. any frame means "pull now", so a wake triggers an
347
+ // immediate (coalesced) pull — push-shaped propagation without waiting on
348
+ // the poll interval. advisory only: if it drops we reconnect, and the
349
+ // interval poll remains the safety net that guarantees convergence.
350
+ private openWakeChannel() {
351
+ const Native = this.state.nativeWebSocket
352
+ if (!Native || this.wakeSocket || this.readyState !== this.OPEN) return
353
+ const wsBase = this.state.originString.replace(/^http/, 'ws')
354
+ const url = `${wsBase}/wake?clientID=${encodeURIComponent(this.clientID)}`
355
+ let socket: {
356
+ onmessage: (() => void) | null
357
+ onclose: (() => void) | null
358
+ onerror: (() => void) | null
359
+ close(): void
360
+ }
361
+ try {
362
+ socket = new Native(url) as unknown as typeof socket
363
+ } catch {
364
+ return
365
+ }
366
+ this.wakeSocket = socket
367
+ const reconnect = () => {
368
+ if (this.wakeSocket !== socket) return
369
+ this.wakeSocket = undefined
370
+ if (this.readyState !== this.OPEN || this.wakeReconnectTimer) return
371
+ this.wakeReconnectTimer = setTimeout(() => {
372
+ this.wakeReconnectTimer = undefined
373
+ this.openWakeChannel()
374
+ }, 500)
375
+ }
376
+ // route through requestPullAfterCurrent, NOT pull() directly: a wake that
377
+ // lands while a pull is already in flight must set pullAfterCurrent so the
378
+ // in-flight pull re-runs and picks up the woken change. calling pull()
379
+ // directly would return the existing promise and silently drop the wake,
380
+ // leaving convergence to the safety poll (a burst-storm latency bug).
381
+ socket.onmessage = () => this.requestPullAfterCurrent()
382
+ socket.onclose = reconnect
383
+ socket.onerror = reconnect
384
+ }
385
+
386
+ private closeWakeChannel() {
387
+ if (this.wakeReconnectTimer) {
388
+ clearTimeout(this.wakeReconnectTimer)
389
+ this.wakeReconnectTimer = undefined
390
+ }
391
+ const socket = this.wakeSocket
392
+ this.wakeSocket = undefined
393
+ if (socket) {
394
+ try {
395
+ socket.close()
396
+ } catch {
397
+ // best effort: an already-closing wake socket is harmless
398
+ }
399
+ }
288
400
  }
289
401
 
290
402
  private queueDesiredQueries(body: unknown) {
291
403
  const desiredQueriesPatch = (body as { desiredQueriesPatch?: unknown })
292
404
  ?.desiredQueriesPatch
293
405
  if (!Array.isArray(desiredQueriesPatch)) return
294
- this.pendingGotQueriesPatch.push(...gotQueriesPatch(desiredQueriesPatch))
406
+ if (!this.state.queryAware) {
407
+ // baseline dialect: synthesize the got-query ack locally
408
+ this.pendingGotQueriesPatch.push(...gotQueriesPatch(desiredQueriesPatch))
409
+ return
410
+ }
411
+ // query-aware: accumulate the desired-query delta to ship to the server. a
412
+ // put ships its inline ast, or a client-resolved ast (queryTransform), or
413
+ // name+args for the server to resolve (queryForward). the server owns the
414
+ // got-query ack.
415
+ const transform = this.state.queryTransform
416
+ for (const op of desiredQueriesPatch as DesiredQueryPatchOp[]) {
417
+ if (op.op === 'clear') {
418
+ this.desiredQueryPatch.push({ op: 'clear' })
419
+ } else if (op.op === 'del') {
420
+ this.desiredQueryPatch.push({ op: 'del', hash: op.hash })
421
+ } else if (op.op === 'put') {
422
+ const inline = (op as { ast?: unknown }).ast
423
+ const name = (op as { name?: string }).name ?? ''
424
+ const args = ((op as { args?: readonly unknown[] }).args ??
425
+ []) as readonly unknown[]
426
+ if (this.state.queryForward) {
427
+ this.desiredQueryPatch.push({ op: 'put', hash: op.hash, name, args })
428
+ } else if (inline !== undefined) {
429
+ this.desiredQueryPatch.push({ op: 'put', hash: op.hash, ast: inline })
430
+ } else if (transform) {
431
+ this.desiredQueryPatch.push({
432
+ op: 'put',
433
+ hash: op.hash,
434
+ ast: transform(name, args),
435
+ })
436
+ }
437
+ }
438
+ }
439
+ this.queryVersion++
295
440
  }
296
441
 
297
442
  private async push(body: unknown) {
@@ -328,12 +473,30 @@ class ZeroHttpSocket {
328
473
  this.run(this.pull())
329
474
  }
330
475
 
476
+ // in query-aware mode the got-query ack is authoritative from the server:
477
+ // take the server's gotQueries.patch as the got patch to emit (replacing
478
+ // local synthesis), and clear the acked prefix of the shipped desired delta
479
+ // once the server acks that version (the ack never leads its row effects —
480
+ // invariant 13 — so the client marks a query got only after its rows land).
481
+ private applyServerGotQueries(response: PullResponse) {
482
+ const got = response.gotQueries
483
+ this.pendingGotQueriesPatch = got ? got.patch : []
484
+ if (
485
+ got &&
486
+ this.sentQueryVersion !== undefined &&
487
+ got.version >= this.sentQueryVersion
488
+ ) {
489
+ this.desiredQueryPatch.splice(0, this.sentQueryPatchLen)
490
+ this.sentQueryVersion = undefined
491
+ }
492
+ }
493
+
331
494
  private async answerMutationRecoveryPull(body: {
332
495
  clientGroupID: string
333
496
  cookie: string | null
334
497
  requestID: string
335
498
  }) {
336
- const response = await this.fetchPull(body.clientGroupID, body.cookie)
499
+ const response = await this.fetchPull(body.clientGroupID, body.cookie, false)
337
500
  const cookie = toWebSocketCookie(response.cookie)
338
501
  this.emitMessage([
339
502
  'pull',
@@ -345,12 +508,27 @@ class ZeroHttpSocket {
345
508
  ])
346
509
  }
347
510
 
348
- private async fetchPull(clientGroupID: string, cookie: string | null) {
349
- return (await this.postJSON('/pull', {
511
+ private async fetchPull(
512
+ clientGroupID: string,
513
+ cookie: string | null,
514
+ includeQueries: boolean,
515
+ ) {
516
+ const body: Record<string, unknown> = {
350
517
  clientID: this.clientID,
351
518
  clientGroupID,
352
519
  cookie: toHttpCookie(cookie),
353
- })) as PullResponse
520
+ }
521
+ // ship the un-acked desired-query delta with the pull; remember what we
522
+ // sent so the server ack can clear exactly that prefix. a recovery pull
523
+ // (includeQueries=false) never carries desires.
524
+ if (includeQueries && this.state.queryAware && this.desiredQueryPatch.length > 0) {
525
+ this.sentQueryVersion = this.queryVersion
526
+ this.sentQueryPatchLen = this.desiredQueryPatch.length
527
+ body.queries = { version: this.queryVersion, patch: [...this.desiredQueryPatch] }
528
+ } else {
529
+ this.sentQueryVersion = undefined
530
+ }
531
+ return (await this.postJSON('/pull', body)) as PullResponse
354
532
  }
355
533
 
356
534
  private async postJSON(path: '/pull' | '/push', body: unknown) {
@@ -410,11 +588,23 @@ class ZeroHttpSocket {
410
588
  }
411
589
 
412
590
  private emitPoke(response: Exclude<PullResponse, { unchanged: true }>) {
413
- const nextCookie = toWebSocketCookie(response.cookie)
414
- if (isStaleCookie(this.cookie, response.cookie)) {
591
+ const currentServer = toHttpCookie(this.cookie)
592
+ let nextCookie: string
593
+ if (currentServer !== null && response.cookie < currentServer) {
594
+ // the server watermark is BEHIND the client: a real reset/restore. mirror
595
+ // the 409 stale path instead of poking the client backwards.
415
596
  throw new Error(
416
597
  `zero-http pull returned stale cookie ${response.cookie} for ${this.cookie}`,
417
598
  )
599
+ } else if (currentServer !== null && response.cookie === currentServer) {
600
+ // same server watermark but a non-empty patch: a query-aware membership
601
+ // delta (a desired-query change recomputes rows without advancing the
602
+ // change log). bump a client-local cookie id so replicache sees a changed
603
+ // cookie — otherwise it trips "cookie did not change, but patch is not
604
+ // empty" and drops the patch.
605
+ nextCookie = toLocalWebSocketCookie(response.cookie, ++this.nextLocalCookieID)
606
+ } else {
607
+ nextCookie = toWebSocketCookie(response.cookie) as string
418
608
  }
419
609
 
420
610
  const pokeID = `zero-http-${++this.state.nextPokeID}`
@@ -576,11 +766,6 @@ function toLocalWebSocketCookie(cookie: number, localID: number): string {
576
766
  )}`
577
767
  }
578
768
 
579
- function isStaleCookie(current: string | null, next: number) {
580
- const currentNumber = toHttpCookie(current)
581
- return currentNumber !== null && next <= currentNumber
582
- }
583
-
584
769
  function errorMessage(error: unknown) {
585
770
  return error instanceof Error ? error.message : String(error)
586
771
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createMutators.d.ts","sourceRoot":"","sources":["../../src/helpers/createMutators.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,QAAQ,EACR,GAAG,EACH,aAAa,EACb,eAAe,EAGhB,MAAM,UAAU,CAAA;AAEjB,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,OAAO,CAAA;CACd,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE1B,YAAY,EAAE,kBAAkB,IAAI,wBAAwB,EAAE,CAAA;AAE9D,wBAAgB,cAAc,CAAC,MAAM,SAAS,aAAa,EAAE,EAC3D,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,UAAe,EACf,GAAG,EACH,MAAM,EACN,gBAAgB,EAChB,kBAAkB,GACnB,EAAE;IACD,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAChC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACvC,mBAAmB,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,gBAAgB,CAAC,EAAE,kBAAkB,CAAA;IACrC,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CACzD,GAAG,eAAe,CAAC,MAAM,CAAC,CAkK1B"}
1
+ {"version":3,"file":"createMutators.d.ts","sourceRoot":"","sources":["../../src/helpers/createMutators.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,QAAQ,EACR,GAAG,EACH,aAAa,EACb,eAAe,EAGhB,MAAM,UAAU,CAAA;AAEjB,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,OAAO,CAAA;CACd,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE1B,YAAY,EAAE,kBAAkB,IAAI,wBAAwB,EAAE,CAAA;AAE9D,wBAAgB,cAAc,CAAC,MAAM,SAAS,aAAa,EAAE,EAC3D,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,UAAe,EACf,GAAG,EACH,MAAM,EACN,gBAAgB,EAChB,kBAAkB,GACnB,EAAE;IACD,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAChC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACvC,mBAAmB,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,gBAAgB,CAAC,EAAE,kBAAkB,CAAA;IACrC,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CACzD,GAAG,eAAe,CAAC,MAAM,CAAC,CAuK1B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createMutators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMutators.test.d.ts","sourceRoot":"","sources":["../../src/helpers/createMutators.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=completeAck.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completeAck.test.d.ts","sourceRoot":"","sources":["../../src/httpPull/completeAck.test.ts"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+ export type QueryTransform = (name: string, args: readonly unknown[]) => unknown;
1
2
  export type HttpPullTransport = {
2
3
  pull(): Promise<void>;
3
4
  readonly connections: number;
@@ -7,6 +8,9 @@ export type HttpPullTransportOptions = {
7
8
  origin: string;
8
9
  fetch?: typeof fetch;
9
10
  pullIntervalMs?: number;
11
+ wake?: boolean;
12
+ queryTransform?: QueryTransform;
13
+ queryForward?: boolean;
10
14
  };
11
15
  export declare function installHttpPullTransport(opts: HttpPullTransportOptions): HttpPullTransport;
12
16
  export declare function ensureHttpPullTransport(opts: HttpPullTransportOptions): HttpPullTransport;
@@ -1 +1 @@
1
- {"version":3,"file":"httpPullTransport.d.ts","sourceRoot":"","sources":["../src/httpPullTransport.ts"],"names":[],"mappings":"AAsDA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,SAAS,IAAI,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IAGpB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,wBAAwB,GAC7B,iBAAiB,CAqDnB;AAOD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,wBAAwB,GAC7B,iBAAiB,CAOnB"}
1
+ {"version":3,"file":"httpPullTransport.d.ts","sourceRoot":"","sources":["../src/httpPullTransport.ts"],"names":[],"mappings":"AAyCA,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,CAAA;AAqChF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,SAAS,IAAI,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IAGpB,cAAc,CAAC,EAAE,MAAM,CAAA;IAMvB,IAAI,CAAC,EAAE,OAAO,CAAA;IAId,cAAc,CAAC,EAAE,cAAc,CAAA;IAI/B,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,wBAAwB,GAC7B,iBAAiB,CAyDnB;AAOD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,wBAAwB,GAC7B,iBAAiB,CAOnB"}