on-zero 0.6.18 → 0.6.19

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 (114) hide show
  1. package/dist/cjs/asyncTasks.native.js.map +1 -1
  2. package/dist/cjs/createZeroClient.cjs +1 -28
  3. package/dist/cjs/createZeroClient.connection.test.cjs +11 -40
  4. package/dist/cjs/createZeroClient.connection.test.native.js +11 -40
  5. package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -1
  6. package/dist/cjs/createZeroClient.native.js +1 -29
  7. package/dist/cjs/createZeroClient.native.js.map +1 -1
  8. package/dist/cjs/createZeroDirectServer.cjs +1 -1
  9. package/dist/cjs/createZeroDirectServer.native.js +1 -1
  10. package/dist/cjs/createZeroDirectServer.native.js.map +1 -1
  11. package/dist/cjs/createZeroServer.test.cjs +6 -0
  12. package/dist/cjs/createZeroServer.test.native.js +6 -0
  13. package/dist/cjs/createZeroServer.test.native.js.map +1 -1
  14. package/dist/cjs/createZeroServerCore.cjs +29 -1
  15. package/dist/cjs/createZeroServerCore.native.js +153 -1
  16. package/dist/cjs/createZeroServerCore.native.js.map +1 -1
  17. package/dist/cjs/httpPull/transport.test.cjs +127 -15
  18. package/dist/cjs/httpPull/transport.test.native.js +161 -16
  19. package/dist/cjs/httpPull/transport.test.native.js.map +1 -1
  20. package/dist/cjs/httpPullTransport.cjs +48 -18
  21. package/dist/cjs/httpPullTransport.native.js +57 -20
  22. package/dist/cjs/httpPullTransport.native.js.map +1 -1
  23. package/dist/cjs/modelRegistry.cjs +7 -4
  24. package/dist/cjs/modelRegistry.native.js +8 -4
  25. package/dist/cjs/modelRegistry.native.js.map +1 -1
  26. package/dist/cjs/mutations.cjs +15 -11
  27. package/dist/cjs/mutations.native.js +17 -11
  28. package/dist/cjs/mutations.native.js.map +1 -1
  29. package/dist/cjs/state.cjs +2 -3
  30. package/dist/cjs/state.native.js +2 -3
  31. package/dist/cjs/state.native.js.map +1 -1
  32. package/dist/cjs/syncHost.cjs +2 -1
  33. package/dist/cjs/syncHost.native.js +2 -1
  34. package/dist/cjs/syncHost.native.js.map +1 -1
  35. package/dist/cjs/usePermission.test.cjs +4 -2
  36. package/dist/cjs/usePermission.test.native.js +4 -2
  37. package/dist/cjs/usePermission.test.native.js.map +1 -1
  38. package/dist/esm/asyncTasks.mjs.map +1 -1
  39. package/dist/esm/asyncTasks.native.js.map +1 -1
  40. package/dist/esm/createZeroClient.connection.test.mjs +11 -40
  41. package/dist/esm/createZeroClient.connection.test.mjs.map +1 -1
  42. package/dist/esm/createZeroClient.connection.test.native.js +11 -40
  43. package/dist/esm/createZeroClient.connection.test.native.js.map +1 -1
  44. package/dist/esm/createZeroClient.mjs +2 -29
  45. package/dist/esm/createZeroClient.mjs.map +1 -1
  46. package/dist/esm/createZeroClient.native.js +2 -30
  47. package/dist/esm/createZeroClient.native.js.map +1 -1
  48. package/dist/esm/createZeroDirectServer.mjs +2 -2
  49. package/dist/esm/createZeroDirectServer.mjs.map +1 -1
  50. package/dist/esm/createZeroDirectServer.native.js +2 -2
  51. package/dist/esm/createZeroDirectServer.native.js.map +1 -1
  52. package/dist/esm/createZeroServer.test.mjs +6 -0
  53. package/dist/esm/createZeroServer.test.mjs.map +1 -1
  54. package/dist/esm/createZeroServer.test.native.js +6 -0
  55. package/dist/esm/createZeroServer.test.native.js.map +1 -1
  56. package/dist/esm/createZeroServerCore.mjs +29 -1
  57. package/dist/esm/createZeroServerCore.mjs.map +1 -1
  58. package/dist/esm/createZeroServerCore.native.js +153 -1
  59. package/dist/esm/createZeroServerCore.native.js.map +1 -1
  60. package/dist/esm/httpPull/transport.test.mjs +127 -15
  61. package/dist/esm/httpPull/transport.test.mjs.map +1 -1
  62. package/dist/esm/httpPull/transport.test.native.js +161 -16
  63. package/dist/esm/httpPull/transport.test.native.js.map +1 -1
  64. package/dist/esm/httpPullTransport.mjs +48 -18
  65. package/dist/esm/httpPullTransport.mjs.map +1 -1
  66. package/dist/esm/httpPullTransport.native.js +57 -20
  67. package/dist/esm/httpPullTransport.native.js.map +1 -1
  68. package/dist/esm/modelRegistry.mjs +7 -4
  69. package/dist/esm/modelRegistry.mjs.map +1 -1
  70. package/dist/esm/modelRegistry.native.js +8 -4
  71. package/dist/esm/modelRegistry.native.js.map +1 -1
  72. package/dist/esm/mutations.mjs +15 -11
  73. package/dist/esm/mutations.mjs.map +1 -1
  74. package/dist/esm/mutations.native.js +17 -11
  75. package/dist/esm/mutations.native.js.map +1 -1
  76. package/dist/esm/state.mjs +2 -3
  77. package/dist/esm/state.mjs.map +1 -1
  78. package/dist/esm/state.native.js +2 -3
  79. package/dist/esm/state.native.js.map +1 -1
  80. package/dist/esm/syncHost.mjs +2 -1
  81. package/dist/esm/syncHost.mjs.map +1 -1
  82. package/dist/esm/syncHost.native.js +2 -1
  83. package/dist/esm/syncHost.native.js.map +1 -1
  84. package/dist/esm/usePermission.test.mjs +6 -4
  85. package/dist/esm/usePermission.test.mjs.map +1 -1
  86. package/dist/esm/usePermission.test.native.js +6 -4
  87. package/dist/esm/usePermission.test.native.js.map +1 -1
  88. package/package.json +2 -2
  89. package/src/asyncTasks.ts +4 -1
  90. package/src/createZeroClient.connection.test.tsx +11 -35
  91. package/src/createZeroClient.tsx +7 -40
  92. package/src/createZeroDirectServer.ts +2 -2
  93. package/src/createZeroServer.test.ts +10 -0
  94. package/src/createZeroServerCore.ts +38 -1
  95. package/src/httpPull/transport.test.ts +143 -16
  96. package/src/httpPullTransport.ts +67 -30
  97. package/src/modelRegistry.ts +9 -4
  98. package/src/mutations.ts +19 -15
  99. package/src/state.ts +3 -3
  100. package/src/syncHost.ts +2 -2
  101. package/src/usePermission.test.ts +9 -3
  102. package/test-fixtures/server-return-types.ts +13 -1
  103. package/types/asyncTasks.d.ts +5 -1
  104. package/types/asyncTasks.d.ts.map +1 -1
  105. package/types/createZeroClient.d.ts.map +1 -1
  106. package/types/createZeroServerCore.d.ts.map +1 -1
  107. package/types/httpPullTransport.d.ts +13 -0
  108. package/types/httpPullTransport.d.ts.map +1 -1
  109. package/types/modelRegistry.d.ts.map +1 -1
  110. package/types/mutations.d.ts.map +1 -1
  111. package/types/state.d.ts +2 -2
  112. package/types/state.d.ts.map +1 -1
  113. package/types/syncHost.d.ts +1 -1
  114. package/types/syncHost.d.ts.map +1 -1
@@ -2,7 +2,11 @@ import { Zero } from '@rocicorp/zero'
2
2
  import { afterEach, describe, expect, test, vi } from 'vitest'
3
3
 
4
4
  import { zeroHttpFixtureMutators, zeroHttpFixtureSchema } from './fixtureSchema'
5
- import { ensureHttpPullTransport, installHttpPullTransport } from '../httpPullTransport'
5
+ import {
6
+ ensureHttpPullTransport,
7
+ installHttpPullTransport,
8
+ type HttpPullLifecycleEvent,
9
+ } from '../httpPullTransport'
6
10
 
7
11
  const ORIGIN = 'https://zero-http.local'
8
12
 
@@ -429,23 +433,133 @@ describe('zero-http transport', () => {
429
433
  view.destroy()
430
434
  })
431
435
 
432
- test('transient pull failures back off reconnect attempts', async () => {
433
- const requests: RequestRecord[] = []
436
+ test('pull and push 500 reconnects keep socket opens on their current Zero attempt', async () => {
437
+ const lifecycle: HttpPullLifecycleEvent[] = []
438
+ const zeroLogs: Array<{ context: Record<string, unknown>; args: unknown[] }> = []
439
+ let failPull = false
440
+ let failPush = false
434
441
  const fetch = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
435
442
  const request = recordRequest(input, init)
436
- requests.push(request)
437
- expect(request.path).toBe('/pull')
438
- throw new TypeError('Failed to fetch')
443
+ if (request.path === '/pull') {
444
+ if (failPull) {
445
+ failPull = false
446
+ return jsonResponse({ error: 'injected pull outage' }, { status: 500 })
447
+ }
448
+ return jsonResponse({ cookie: request.body.cookie, unchanged: true })
449
+ }
450
+ if (failPush) {
451
+ failPush = false
452
+ return jsonResponse({ error: 'injected push outage' }, { status: 500 })
453
+ }
454
+ const mutation = request.body.mutations[0]
455
+ return jsonResponse({
456
+ pushResponse: {
457
+ mutations: [
458
+ {
459
+ id: { clientID: mutation.clientID, id: mutation.id },
460
+ result: {},
461
+ },
462
+ ],
463
+ },
464
+ })
465
+ })
466
+ const transport = installHttpPullTransport({
467
+ origin: ORIGIN,
468
+ fetch,
469
+ lifecycle: (event) => lifecycle.push(event),
470
+ })
471
+ transports.push(transport)
472
+ const zero = createZero({
473
+ logSink: {
474
+ log: (_level, context, ...args) => {
475
+ zeroLogs.push({ context: context ?? {}, args })
476
+ },
477
+ },
439
478
  })
440
- install(fetch)
441
- createZero()
442
479
 
443
- await eventually(() => expect(requests.length).toBe(1))
444
- await sleep(150)
445
- expect(requests.length).toBe(1)
446
- await eventually(() => expect(requests.length).toBe(2), 1_500)
447
- await sleep(150)
448
- expect(requests.length).toBe(2)
480
+ await eventually(() => expect(zero.connection.state.current.name).toBe('connected'))
481
+ failPull = true
482
+ await transport.pull().catch(() => {})
483
+ await eventually(
484
+ () => expect(lifecycle.filter((event) => event.type === 'open')).toHaveLength(2),
485
+ 5_000,
486
+ )
487
+
488
+ failPush = true
489
+ const mutation = zero.mutate.project.create({
490
+ id: 'p1',
491
+ ownerId: 'u1',
492
+ name: 'after reconnect',
493
+ })
494
+ await mutation.client
495
+ await mutation.server.catch(() => {})
496
+ await eventually(
497
+ () => expect(lifecycle.filter((event) => event.type === 'open')).toHaveLength(3),
498
+ 5_000,
499
+ )
500
+ await eventually(
501
+ () => expect(zero.connection.state.current.name).toBe('connected'),
502
+ 5_000,
503
+ )
504
+
505
+ const opens = lifecycle.filter((event) => event.type === 'open')
506
+ expect(
507
+ opens.map(({ generation, activeGeneration }) => [generation, activeGeneration]),
508
+ ).toEqual([
509
+ [1, 1],
510
+ [2, 2],
511
+ [3, 3],
512
+ ])
513
+ expect(
514
+ zeroLogs.some(({ args }) =>
515
+ args.some((arg) => String(arg).includes('connect start time is undefined')),
516
+ ),
517
+ ).toBe(false)
518
+ })
519
+
520
+ test('a replacement socket supersedes stale open and connected events for the same client', async () => {
521
+ vi.useFakeTimers()
522
+ const lifecycle: HttpPullLifecycleEvent[] = []
523
+ const transport = installHttpPullTransport({
524
+ origin: ORIGIN,
525
+ fetch: vi.fn(async () => jsonResponse({ cookie: null, unchanged: true })),
526
+ lifecycle: (event) => lifecycle.push(event),
527
+ })
528
+ transports.push(transport)
529
+
530
+ let connectStart: number | undefined = Date.now()
531
+ const errors: string[] = []
532
+ const attachStockLifecycle = (socket: WebSocket) => {
533
+ socket.addEventListener('open', () => {
534
+ if (connectStart === undefined) {
535
+ errors.push('Got open event but connect start time is undefined.')
536
+ }
537
+ })
538
+ socket.addEventListener('message', (event) => {
539
+ const message = JSON.parse(String(event.data)) as [string, unknown]
540
+ if (message[0] === 'connected') connectStart = undefined
541
+ })
542
+ }
543
+
544
+ const stale = openRawSocketWithMessages({ wsid: 'stale' }).socket
545
+ attachStockLifecycle(stale)
546
+ const current = openRawSocketWithMessages({ wsid: 'current' }).socket
547
+ attachStockLifecycle(current)
548
+ await vi.advanceTimersByTimeAsync(1)
549
+
550
+ expect(
551
+ lifecycle
552
+ .filter((event) => event.type === 'open')
553
+ .map(({ generation, activeGeneration, wsid }) => [
554
+ generation,
555
+ activeGeneration,
556
+ wsid,
557
+ ]),
558
+ ).toEqual([[2, 2, 'current']])
559
+ expect(lifecycle).toContainEqual(
560
+ expect.objectContaining({ type: 'superseded', generation: 1, wsid: 'stale' }),
561
+ )
562
+ expect(errors).toEqual([])
449
563
  })
450
564
 
451
565
  test('non-origin WebSockets pass through to the native implementation', () => {
@@ -557,7 +671,17 @@ function install(fetch: typeof globalThis.fetch) {
557
671
  }
558
672
 
559
673
  function createZero(
560
- options: { pingTimeoutMs?: number; onClientStateNotFound?: () => void } = {},
674
+ options: {
675
+ pingTimeoutMs?: number
676
+ onClientStateNotFound?: () => void
677
+ logSink?: {
678
+ log(
679
+ level: string,
680
+ context: Record<string, unknown> | undefined,
681
+ ...args: unknown[]
682
+ ): void
683
+ }
684
+ } = {},
561
685
  ) {
562
686
  const zero = new Zero({
563
687
  server: ORIGIN,
@@ -569,6 +693,8 @@ function createZero(
569
693
  mutators: zeroHttpFixtureMutators,
570
694
  pingTimeoutMs: options.pingTimeoutMs,
571
695
  onClientStateNotFound: options.onClientStateNotFound,
696
+ logLevel: options.logSink ? 'debug' : undefined,
697
+ logSink: options.logSink,
572
698
  })
573
699
  zeros.push(zero)
574
700
  return zero
@@ -644,6 +770,7 @@ function openRawSocket() {
644
770
  function openRawSocketWithMessages(opts?: {
645
771
  authToken?: string
646
772
  desiredQueriesPatch?: unknown[]
773
+ wsid?: string
647
774
  }) {
648
775
  const url = new URL(`${ORIGIN}/sync/v51/connect`)
649
776
  url.protocol = 'wss:'
@@ -652,7 +779,7 @@ function openRawSocketWithMessages(opts?: {
652
779
  url.searchParams.set('userID', 'u1')
653
780
  url.searchParams.set('baseCookie', '')
654
781
  url.searchParams.set('lmid', '0')
655
- url.searchParams.set('wsid', 'ws-test')
782
+ url.searchParams.set('wsid', opts?.wsid ?? 'ws-test')
656
783
  const messages: Array<[string, any]> = []
657
784
  const socket = new WebSocket(
658
785
  url,
@@ -71,12 +71,13 @@ type TransportState = {
71
71
  readonly queryForward: boolean
72
72
  readonly queryAware: boolean
73
73
  nextPokeID: number
74
- transientFailureCount: number
74
+ nextSocketGeneration: number
75
+ readonly activeSocketGenerationByClient: Map<string, number>
76
+ readonly activeSocketByClient: Map<string, ZeroHttpSocket>
77
+ readonly lifecycle: ((event: HttpPullLifecycleEvent) => void) | undefined
75
78
  }
76
79
 
77
80
  const COOKIE_WIDTH = 20
78
- const TRANSIENT_RECONNECT_BACKOFF_BASE_MS = 1_000
79
- const TRANSIENT_RECONNECT_BACKOFF_MAX_MS = 30_000
80
81
 
81
82
  export type HttpPullTransport = {
82
83
  pull(): Promise<void>
@@ -108,6 +109,19 @@ export type HttpPullTransportOptions = {
108
109
  // queries ship as name+args for the SERVER (consumer worker) to resolve with
109
110
  // auth. the production path for permission-transformed queries.
110
111
  queryForward?: boolean
112
+ // optional generation trace for connection-lifecycle diagnostics
113
+ lifecycle?: (event: HttpPullLifecycleEvent) => void
114
+ }
115
+
116
+ export type HttpPullLifecycleEvent = {
117
+ type: 'created' | 'listener' | 'open' | 'close' | 'failure' | 'superseded'
118
+ generation: number
119
+ activeGeneration: number
120
+ clientID: string
121
+ wsid: string
122
+ listener?: SocketEventType
123
+ code?: number
124
+ reason?: string
111
125
  }
112
126
 
113
127
  export function installHttpPullTransport(
@@ -140,7 +154,10 @@ export function installHttpPullTransport(
140
154
  queryForward: opts.queryForward === true,
141
155
  queryAware: opts.queryTransform !== undefined || opts.queryForward === true,
142
156
  nextPokeID: 0,
143
- transientFailureCount: 0,
157
+ nextSocketGeneration: 0,
158
+ activeSocketGenerationByClient: new Map(),
159
+ activeSocketByClient: new Map(),
160
+ lifecycle: opts.lifecycle,
144
161
  }
145
162
 
146
163
  const Shim = class {
@@ -231,6 +248,7 @@ class ZeroHttpSocket {
231
248
  private pullTimer: ReturnType<typeof setInterval> | undefined
232
249
  private wakeSocket: { close(): void } | undefined
233
250
  private wakeReconnectTimer: ReturnType<typeof setTimeout> | undefined
251
+ private readonly generation: number
234
252
 
235
253
  constructor(
236
254
  private readonly state: TransportState,
@@ -242,6 +260,11 @@ class ZeroHttpSocket {
242
260
  this.clientID = this.connectURL.searchParams.get('clientID') ?? ''
243
261
  this.clientGroupID = this.connectURL.searchParams.get('clientGroupID') ?? ''
244
262
  this.wsid = this.connectURL.searchParams.get('wsid') ?? `zero-http-${Date.now()}`
263
+ this.generation = ++this.state.nextSocketGeneration
264
+ this.state.activeSocketByClient.get(this.clientID)?.supersede()
265
+ this.state.activeSocketGenerationByClient.set(this.clientID, this.generation)
266
+ this.state.activeSocketByClient.set(this.clientID, this)
267
+ this.emitLifecycle('created')
245
268
  const baseCookie = this.connectURL.searchParams.get('baseCookie')
246
269
  this.cookie = baseCookie ? baseCookie : null
247
270
  // the local cookie ID is encoded into the suffix of any cookie we
@@ -258,11 +281,17 @@ class ZeroHttpSocket {
258
281
  this.queueDesiredQueries(decoded.initConnectionMessage?.[1])
259
282
 
260
283
  this.state.sockets.add(this)
261
- this.openTimer = setTimeout(() => this.open(), reconnectDelayMs(this.state))
284
+ // open on the next task so Zero can attach its listeners. Zero owns the
285
+ // connection timeout and retry cadence; delaying this synthetic open here
286
+ // can outlive Zero's 10s attempt and deliver an event to abandoned state.
287
+ this.openTimer = setTimeout(() => this.open(), 0)
262
288
  }
263
289
 
264
290
  addEventListener(type: SocketEventType, listener: SocketListener | null) {
265
- if (listener) this.listeners[type]?.add(listener)
291
+ if (listener) {
292
+ this.listeners[type]?.add(listener)
293
+ this.emitLifecycle('listener', { listener: type })
294
+ }
266
295
  }
267
296
 
268
297
  removeEventListener(type: SocketEventType, listener: SocketListener | null) {
@@ -312,6 +341,11 @@ class ZeroHttpSocket {
312
341
  this.closeWakeChannel()
313
342
  this.readyState = this.CLOSED
314
343
  this.state.sockets.delete(this)
344
+ if (this.state.activeSocketByClient.get(this.clientID) === this) {
345
+ this.state.activeSocketByClient.delete(this.clientID)
346
+ this.state.activeSocketGenerationByClient.delete(this.clientID)
347
+ }
348
+ this.emitLifecycle('close', { code, reason })
315
349
  this.emit('close', { code, reason, wasClean: code <= 1001 })
316
350
  }
317
351
 
@@ -343,6 +377,7 @@ class ZeroHttpSocket {
343
377
  private open() {
344
378
  if (this.readyState !== this.CONNECTING) return
345
379
  this.readyState = this.OPEN
380
+ this.emitLifecycle('open')
346
381
  this.emit('open', {})
347
382
  this.emitMessage(['connected', { wsid: this.wsid, timestamp: Date.now() }])
348
383
  setTimeout(() => this.run(this.pull()), 0)
@@ -557,7 +592,6 @@ class ZeroHttpSocket {
557
592
  if (!response.ok) {
558
593
  throw new ZeroHttpResponseError(path, response.status)
559
594
  }
560
- resetTransientFailures(this.state)
561
595
  return response.json()
562
596
  }
563
597
 
@@ -567,6 +601,7 @@ class ZeroHttpSocket {
567
601
 
568
602
  private fail(error: unknown) {
569
603
  if (this.readyState === this.CLOSED) return
604
+ this.emitLifecycle('failure', { reason: errorMessage(error) })
570
605
  if (isAuthHTTPError(error)) {
571
606
  this.emitMessage([
572
607
  'error',
@@ -596,7 +631,6 @@ class ZeroHttpSocket {
596
631
  if (this.readyState !== this.CLOSED) this.close(1000, error.message)
597
632
  return
598
633
  }
599
- recordTransientFailure(this.state)
600
634
  this.emit('error', { error })
601
635
  this.close(1011, errorMessage(error))
602
636
  }
@@ -704,6 +738,31 @@ class ZeroHttpSocket {
704
738
  else listener.handleEvent(event)
705
739
  }
706
740
  }
741
+
742
+ private supersede() {
743
+ if (this.readyState === this.CLOSED) return
744
+ if (this.openTimer !== undefined) clearTimeout(this.openTimer)
745
+ if (this.pullTimer !== undefined) clearInterval(this.pullTimer)
746
+ this.closeWakeChannel()
747
+ this.readyState = this.CLOSED
748
+ this.state.sockets.delete(this)
749
+ this.emitLifecycle('superseded')
750
+ }
751
+
752
+ private emitLifecycle(
753
+ type: HttpPullLifecycleEvent['type'],
754
+ detail: Pick<HttpPullLifecycleEvent, 'listener' | 'code' | 'reason'> = {},
755
+ ) {
756
+ this.state.lifecycle?.({
757
+ type,
758
+ generation: this.generation,
759
+ activeGeneration:
760
+ this.state.activeSocketGenerationByClient.get(this.clientID) ?? this.generation,
761
+ clientID: this.clientID,
762
+ wsid: this.wsid,
763
+ ...detail,
764
+ })
765
+ }
707
766
  }
708
767
 
709
768
  function shouldIntercept(origin: URL, url: string | URL) {
@@ -823,25 +882,3 @@ function isStaleClientCookieError(error: unknown): error is ZeroHttpResponseErro
823
882
  error.status === 409
824
883
  )
825
884
  }
826
-
827
- function reconnectDelayMs(state: TransportState) {
828
- if (state.transientFailureCount === 0) return 0
829
- return Math.min(
830
- TRANSIENT_RECONNECT_BACKOFF_BASE_MS * 2 ** (state.transientFailureCount - 1),
831
- TRANSIENT_RECONNECT_BACKOFF_MAX_MS,
832
- )
833
- }
834
-
835
- function recordTransientFailure(state: TransportState) {
836
- const maxExponent = Math.log2(
837
- TRANSIENT_RECONNECT_BACKOFF_MAX_MS / TRANSIENT_RECONNECT_BACKOFF_BASE_MS,
838
- )
839
- state.transientFailureCount = Math.min(
840
- state.transientFailureCount + 1,
841
- Math.ceil(maxExponent) + 1,
842
- )
843
- }
844
-
845
- function resetTransientFailures(state: TransportState) {
846
- state.transientFailureCount = 0
847
- }
@@ -1,15 +1,20 @@
1
1
  import type { Where } from './types'
2
2
 
3
- const mutationsToPermissionsRegistry = new Map<string, Where>()
3
+ function mutationsToPermissionsRegistry(): Map<string, Where> {
4
+ const global = globalThis as typeof globalThis & {
5
+ __onZeroMutationPermissionsRegistry__?: Map<string, Where>
6
+ }
7
+ return (global.__onZeroMutationPermissionsRegistry__ ||= new Map())
8
+ }
4
9
 
5
10
  export function setMutationsPermissions(tableName: string, permissions: Where) {
6
- mutationsToPermissionsRegistry.set(tableName, permissions)
11
+ mutationsToPermissionsRegistry().set(tableName, permissions)
7
12
  }
8
13
 
9
14
  export function getMutationsPermissions(tableName: string): Where | undefined {
10
- return mutationsToPermissionsRegistry.get(tableName)
15
+ return mutationsToPermissionsRegistry().get(tableName)
11
16
  }
12
17
 
13
18
  export function getAllMutationsPermissions(): Map<string, Where> {
14
- return mutationsToPermissionsRegistry
19
+ return mutationsToPermissionsRegistry()
15
20
  }
package/src/mutations.ts CHANGED
@@ -20,15 +20,19 @@ type SchemaTableBuilder<TName extends TableName> = TableBuilderWithColumns<
20
20
  // HMR registry - stores mutation implementations and proxies by table name
21
21
  // allows hot-swapping implementations without changing object references
22
22
  // stored on globalThis to persist across HMR module reloads
23
- const registryKey = '__onZeroMutationRegistry__'
24
- const proxyKey = '__onZeroProxyRegistry__'
23
+ function mutationRegistry(): Map<string, Record<string, Function>> {
24
+ const global = globalThis as typeof globalThis & {
25
+ __onZeroMutationRegistry__?: Map<string, Record<string, Function>>
26
+ }
27
+ return (global.__onZeroMutationRegistry__ ||= new Map())
28
+ }
25
29
 
26
- // @ts-ignore
27
- const mutationRegistry: Map<string, Record<string, Function>> = globalThis[registryKey] ||
28
- (globalThis[registryKey] = new Map())
29
- // @ts-ignore
30
- const proxyRegistry: Map<string, any> =
31
- globalThis[proxyKey] || (globalThis[proxyKey] = new Map())
30
+ function proxyRegistry(): Map<string, any> {
31
+ const global = globalThis as typeof globalThis & {
32
+ __onZeroProxyRegistry__?: Map<string, any>
33
+ }
34
+ return (global.__onZeroProxyRegistry__ ||= new Map())
35
+ }
32
36
 
33
37
  // get or create a proxy that delegates to the registry
34
38
  // returns the SAME proxy object on subsequent calls so HMR works
@@ -37,10 +41,10 @@ function getOrCreateMutationProxy<T extends Record<string, Function>>(
37
41
  implementations: T,
38
42
  ): T {
39
43
  // always update implementations (supports HMR)
40
- mutationRegistry.set(tableName, implementations)
44
+ mutationRegistry().set(tableName, implementations)
41
45
 
42
46
  // return existing proxy if we have one (HMR case)
43
- const existing = proxyRegistry.get(tableName)
47
+ const existing = proxyRegistry().get(tableName)
44
48
  if (existing) {
45
49
  return existing as T
46
50
  }
@@ -48,25 +52,25 @@ function getOrCreateMutationProxy<T extends Record<string, Function>>(
48
52
  // first time - create the proxy
49
53
  const proxy = new Proxy({} as T, {
50
54
  get(_, key: string) {
51
- return mutationRegistry.get(tableName)?.[key]
55
+ return mutationRegistry().get(tableName)?.[key]
52
56
  },
53
57
  ownKeys() {
54
- const current = mutationRegistry.get(tableName)
58
+ const current = mutationRegistry().get(tableName)
55
59
  return current ? Object.keys(current) : []
56
60
  },
57
61
  getOwnPropertyDescriptor(_, key: string) {
58
- const current = mutationRegistry.get(tableName)
62
+ const current = mutationRegistry().get(tableName)
59
63
  if (current && key in current) {
60
64
  return { enumerable: true, configurable: true, value: current[key] }
61
65
  }
62
66
  },
63
67
  has(_, key: string) {
64
- const current = mutationRegistry.get(tableName)
68
+ const current = mutationRegistry().get(tableName)
65
69
  return current ? key in current : false
66
70
  },
67
71
  })
68
72
 
69
- proxyRegistry.set(tableName, proxy)
73
+ proxyRegistry().set(tableName, proxy)
70
74
  return proxy
71
75
  }
72
76
 
package/src/state.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createBuilder, type Schema } from '@rocicorp/zero'
1
+ import type { Schema, SchemaQuery } from '@rocicorp/zero'
2
2
  import { globalValue } from '@take-out/helpers'
3
3
 
4
4
  import type { AuthData, QueryBuilder } from './types'
@@ -32,10 +32,10 @@ export const getSchema = () => {
32
32
  return schema
33
33
  }
34
34
 
35
- export const setSchema = (_: Schema) => {
35
+ export const setSchema = <S extends Schema>(_: S, zql: SchemaQuery<S>) => {
36
36
  const state = getState()
37
37
  state.schema = _
38
- state.zql = createBuilder(_) as QueryBuilder
38
+ state.zql = zql as QueryBuilder
39
39
  }
40
40
 
41
41
  export const getAuthData = () => {
package/src/syncHost.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { asQueryInternals } from '@rocicorp/zero/bindings'
2
+ import { createBuilder, type Schema as ZeroSchema } from '@rocicorp/zero'
2
3
 
3
4
  import { createPermissions } from './createPermissions'
4
5
  import {
@@ -24,7 +25,6 @@ import { runWithQueryContext } from './helpers/queryContext'
24
25
  import { setEnvironment, setSchema } from './state'
25
26
 
26
27
  import type { AsyncTaskEntry, AuthData, GenericModels } from './types'
27
- import type { Schema as ZeroSchema } from '@rocicorp/zero'
28
28
 
29
29
  export type SyncHostJsonValue =
30
30
  | string
@@ -129,7 +129,7 @@ export function createZeroSyncHostAdapter<
129
129
  Schema,
130
130
  Models
131
131
  > {
132
- setSchema(options.schema)
132
+ setSchema(options.schema, createBuilder(options.schema))
133
133
  setEnvironment('server')
134
134
 
135
135
  const permissions = createPermissions({
@@ -1,7 +1,11 @@
1
- import { boolean, string, table } from '@rocicorp/zero'
1
+ import { boolean, createBuilder, string, table } from '@rocicorp/zero'
2
2
  import { describe, expect, test } from 'vitest'
3
3
 
4
- import { getMutationsPermissions, setMutationsPermissions } from './modelRegistry'
4
+ import {
5
+ getAllMutationsPermissions,
6
+ getMutationsPermissions,
7
+ setMutationsPermissions,
8
+ } from './modelRegistry'
5
9
  import { registerQuery, getQueryName } from './queryRegistry'
6
10
  import { setEnvironment, setSchema } from './state'
7
11
 
@@ -25,7 +29,8 @@ describe('usePermission _uid query identity', () => {
25
29
  })
26
30
  .primaryKey('id')
27
31
 
28
- setSchema({ tables: { testEntity: testTable }, version: 1 } as any)
32
+ const schema = { tables: { testEntity: testTable }, version: 1 } as any
33
+ setSchema(schema, createBuilder(schema) as any)
29
34
  setEnvironment('client')
30
35
 
31
36
  // simulate what createPermissionCheckFn does:
@@ -73,6 +78,7 @@ describe('usePermission _uid query identity', () => {
73
78
  const perm = getMutationsPermissions('testEntity')
74
79
  expect(perm).toBeDefined()
75
80
  expect(perm).toBe(mockWhere)
81
+ expect(getAllMutationsPermissions().get('testEntity')).toBe(mockWhere)
76
82
  })
77
83
 
78
84
  test('query name registration preserves permission namespace', () => {
@@ -7,7 +7,12 @@ import {
7
7
  } from 'on-zero/server'
8
8
  import { createZeroSQLiteServer, type SqlStatementMetadata } from 'on-zero/sqlite'
9
9
 
10
- import type { Config, MutatorContext } from 'on-zero'
10
+ import {
11
+ runAsyncTaskEntries as runAsyncTaskEntriesFromRoot,
12
+ type Config,
13
+ type MutatorContext,
14
+ type RunAsyncTaskEntriesOptions,
15
+ } from 'on-zero'
11
16
  import type { Schema as ZeroSchema } from '@rocicorp/zero'
12
17
 
13
18
  type AppAuthData = {
@@ -57,6 +62,13 @@ void runAsyncTaskEntries(taskEntries, {
57
62
  },
58
63
  })
59
64
 
65
+ const rootTaskOptions: RunAsyncTaskEntriesOptions = {
66
+ background(promise) {
67
+ void promise
68
+ },
69
+ }
70
+ void runAsyncTaskEntriesFromRoot(taskEntries, rootTaskOptions)
71
+
60
72
  const scheduleBackgroundTask: BackgroundTaskScheduler = (promise) => {
61
73
  void promise
62
74
  }
@@ -1,7 +1,11 @@
1
- import type { AsyncTaskEntry } from './types';
1
+ type AsyncTaskEntry = {
2
+ task: () => Promise<void>;
3
+ barrier: boolean;
4
+ };
2
5
  export type RunAsyncTaskEntriesOptions = {
3
6
  /** Receives the background-task promise. Omit this to await all entries. */
4
7
  background?: (promise: Promise<void>) => void;
5
8
  };
6
9
  export declare function runAsyncTaskEntries(entries: readonly AsyncTaskEntry[], { background }?: RunAsyncTaskEntriesOptions): Promise<void>;
10
+ export {};
7
11
  //# sourceMappingURL=asyncTasks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"asyncTasks.d.ts","sourceRoot":"","sources":["../src/asyncTasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,MAAM,0BAA0B,GAAG;IACvC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;CAC9C,CAAA;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,EAAE,UAAU,EAAE,GAAE,0BAA+B,GAC9C,OAAO,CAAC,IAAI,CAAC,CAsBf"}
1
+ {"version":3,"file":"asyncTasks.d.ts","sourceRoot":"","sources":["../src/asyncTasks.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;CAC9C,CAAA;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,EAAE,UAAU,EAAE,GAAE,0BAA+B,GAC9C,OAAO,CAAC,IAAI,CAAC,CAsBf"}
@@ -1 +1 @@
1
- {"version":3,"file":"createZeroClient.d.ts","sourceRoot":"","sources":["../src/createZeroClient.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createZeroClient.d.ts","sourceRoot":"","sources":["../src/createZeroClient.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"createZeroServerCore.d.ts","sourceRoot":"","sources":["../src/createZeroServerCore.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAA;AAKjC,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE1D,KAAK,wBAAwB,GAAG;IAC9B,EAAE,EAAE;QACF,QAAQ,EAAE,MAAM,CAAA;QAChB,EAAE,EAAE,MAAM,CAAA;KACX,CAAA;IACD,MAAM,EAAE;QACN,KAAK,EAAE,kBAAkB,CAAA;QACzB,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;CACF,CAAA;AAMD,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;AAEtE,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,sBAAsB,CAAC,EAAE,uBAAuB,CAAA;IAChD,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,wBAAwB,EAAE,CAAA;IACrC,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,KAAK,qBAAqB,CACxB,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC3C,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG;IAC3D,cAAc,EAAE,MAAM,kBAAkB,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,2BAA2B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/E,CAAA;AAED,wBAAgB,oBAAoB,CAClC,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,EACA,cAAc,EACd,mBAAmB,EACnB,qBAA6B,EAC7B,qBAAqB,EACrB,MAAM,EACN,SAAS,EAAE,kBAAkB,EAC7B,uBAAuB,EACvB,OAAO,EACP,MAAM,EACN,gBAAgB,EAChB,aAAa,GACd,EAAE,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC;;;;4FAmBlD,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDAwC5B;QACD,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;QACzB,OAAO,EAAE,OAAO,CAAA;KACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCF;AAED,MAAM,MAAM,UAAU,CACpB,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC3C,UAAU,CAAC,OAAO,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;AAuE1E,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"createZeroServerCore.d.ts","sourceRoot":"","sources":["../src/createZeroServerCore.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAA;AAKjC,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE1D,KAAK,wBAAwB,GAAG;IAC9B,EAAE,EAAE;QACF,QAAQ,EAAE,MAAM,CAAA;QAChB,EAAE,EAAE,MAAM,CAAA;KACX,CAAA;IACD,MAAM,EAAE;QACN,KAAK,EAAE,kBAAkB,CAAA;QACzB,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;CACF,CAAA;AAMD,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;AAEtE,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,sBAAsB,CAAC,EAAE,uBAAuB,CAAA;IAChD,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,wBAAwB,EAAE,CAAA;IACrC,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,KAAK,qBAAqB,CACxB,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC3C,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG;IAC3D,cAAc,EAAE,MAAM,kBAAkB,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,2BAA2B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/E,CAAA;AAED,wBAAgB,oBAAoB,CAClC,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,EACA,cAAc,EACd,mBAAmB,EACnB,qBAA6B,EAC7B,qBAAqB,EACrB,MAAM,EACN,SAAS,EAAE,kBAAkB,EAC7B,uBAAuB,EACvB,OAAO,EACP,MAAM,EACN,gBAAgB,EAChB,aAAa,GACd,EAAE,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC;;;;4FAmBlD,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDAwC5B;QACD,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;QACzB,OAAO,EAAE,OAAO,CAAA;KACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCF;AAED,MAAM,MAAM,UAAU,CACpB,MAAM,SAAS,UAAU,EACzB,MAAM,SAAS,aAAa,EAC5B,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC3C,UAAU,CAAC,OAAO,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;AA4G1E,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,0BAA0B,CAAA"}
@@ -1,3 +1,4 @@
1
+ type SocketEventType = 'open' | 'message' | 'close' | 'error';
1
2
  export type QueryTransform = (name: string, args: readonly unknown[]) => unknown;
2
3
  export type HttpPullTransport = {
3
4
  pull(): Promise<void>;
@@ -13,7 +14,19 @@ export type HttpPullTransportOptions = {
13
14
  wake?: boolean;
14
15
  queryTransform?: QueryTransform;
15
16
  queryForward?: boolean;
17
+ lifecycle?: (event: HttpPullLifecycleEvent) => void;
18
+ };
19
+ export type HttpPullLifecycleEvent = {
20
+ type: 'created' | 'listener' | 'open' | 'close' | 'failure' | 'superseded';
21
+ generation: number;
22
+ activeGeneration: number;
23
+ clientID: string;
24
+ wsid: string;
25
+ listener?: SocketEventType;
26
+ code?: number;
27
+ reason?: string;
16
28
  };
17
29
  export declare function installHttpPullTransport(opts: HttpPullTransportOptions): HttpPullTransport;
18
30
  export declare function ensureHttpPullTransport(opts: HttpPullTransportOptions): HttpPullTransport;
31
+ export {};
19
32
  //# sourceMappingURL=httpPullTransport.d.ts.map