on-zero 0.6.3 → 0.6.5

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 (90) hide show
  1. package/dist/cjs/createZeroClient.cjs +111 -12
  2. package/dist/cjs/createZeroClient.connection.test.cjs +163 -0
  3. package/dist/cjs/createZeroClient.connection.test.native.js +242 -0
  4. package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -0
  5. package/dist/cjs/createZeroClient.native.js +145 -12
  6. package/dist/cjs/createZeroClient.native.js.map +1 -1
  7. package/dist/cjs/createZeroClient.recovery.test.cjs +52 -0
  8. package/dist/cjs/createZeroClient.recovery.test.native.js +52 -0
  9. package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
  10. package/dist/cjs/helpers/recoverZeroClient.cjs +140 -14
  11. package/dist/cjs/helpers/recoverZeroClient.native.js +155 -22
  12. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  13. package/dist/cjs/helpers/recoverZeroClient.test.cjs +181 -0
  14. package/dist/cjs/helpers/recoverZeroClient.test.native.js +209 -0
  15. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  16. package/dist/cjs/index.cjs +1 -0
  17. package/dist/cjs/index.native.js +1 -0
  18. package/dist/cjs/index.native.js.map +1 -1
  19. package/dist/cjs/multi.cjs +13 -0
  20. package/dist/cjs/multi.native.js +35 -0
  21. package/dist/cjs/multi.native.js.map +1 -1
  22. package/dist/cjs/multiInstance.test.cjs +12 -0
  23. package/dist/cjs/multiInstance.test.native.js +21 -0
  24. package/dist/cjs/multiInstance.test.native.js.map +1 -1
  25. package/dist/cjs/multiPartition.test.cjs +42 -0
  26. package/dist/cjs/multiPartition.test.native.js +51 -0
  27. package/dist/cjs/multiPartition.test.native.js.map +1 -0
  28. package/dist/esm/createZeroClient.connection.test.mjs +164 -0
  29. package/dist/esm/createZeroClient.connection.test.mjs.map +1 -0
  30. package/dist/esm/createZeroClient.connection.test.native.js +240 -0
  31. package/dist/esm/createZeroClient.connection.test.native.js.map +1 -0
  32. package/dist/esm/createZeroClient.mjs +112 -13
  33. package/dist/esm/createZeroClient.mjs.map +1 -1
  34. package/dist/esm/createZeroClient.native.js +146 -13
  35. package/dist/esm/createZeroClient.native.js.map +1 -1
  36. package/dist/esm/createZeroClient.recovery.test.mjs +52 -0
  37. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  38. package/dist/esm/createZeroClient.recovery.test.native.js +52 -0
  39. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  40. package/dist/esm/helpers/recoverZeroClient.mjs +140 -15
  41. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  42. package/dist/esm/helpers/recoverZeroClient.native.js +155 -23
  43. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  44. package/dist/esm/helpers/recoverZeroClient.test.mjs +182 -1
  45. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  46. package/dist/esm/helpers/recoverZeroClient.test.native.js +210 -1
  47. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  48. package/dist/esm/index.js +2 -2
  49. package/dist/esm/index.js.map +1 -1
  50. package/dist/esm/index.mjs +2 -2
  51. package/dist/esm/index.mjs.map +1 -1
  52. package/dist/esm/index.native.js +2 -2
  53. package/dist/esm/index.native.js.map +1 -1
  54. package/dist/esm/multi.mjs +13 -1
  55. package/dist/esm/multi.mjs.map +1 -1
  56. package/dist/esm/multi.native.js +35 -1
  57. package/dist/esm/multi.native.js.map +1 -1
  58. package/dist/esm/multiInstance.test.mjs +12 -0
  59. package/dist/esm/multiInstance.test.mjs.map +1 -1
  60. package/dist/esm/multiInstance.test.native.js +21 -0
  61. package/dist/esm/multiInstance.test.native.js.map +1 -1
  62. package/dist/esm/multiPartition.test.mjs +43 -0
  63. package/dist/esm/multiPartition.test.mjs.map +1 -0
  64. package/dist/esm/multiPartition.test.native.js +49 -0
  65. package/dist/esm/multiPartition.test.native.js.map +1 -0
  66. package/lint/ssr-guards.js +164 -0
  67. package/package.json +2 -2
  68. package/readme.md +126 -0
  69. package/src/createZeroClient.connection.test.tsx +162 -0
  70. package/src/createZeroClient.recovery.test.tsx +68 -0
  71. package/src/createZeroClient.tsx +188 -13
  72. package/src/helpers/recoverZeroClient.test.ts +204 -1
  73. package/src/helpers/recoverZeroClient.ts +263 -42
  74. package/src/index.ts +3 -0
  75. package/src/multi.ts +33 -0
  76. package/src/multiInstance.test.tsx +13 -0
  77. package/src/multiPartition.test.ts +38 -0
  78. package/types/createZeroClient.connection.test.d.ts +5 -0
  79. package/types/createZeroClient.connection.test.d.ts.map +1 -0
  80. package/types/createZeroClient.d.ts +17 -0
  81. package/types/createZeroClient.d.ts.map +1 -1
  82. package/types/createZeroServer.d.ts +4 -4
  83. package/types/helpers/recoverZeroClient.d.ts +15 -1
  84. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  85. package/types/index.d.ts +1 -1
  86. package/types/index.d.ts.map +1 -1
  87. package/types/multi.d.ts +1 -0
  88. package/types/multi.d.ts.map +1 -1
  89. package/types/multiPartition.test.d.ts +2 -0
  90. package/types/multiPartition.test.d.ts.map +1 -0
@@ -145,9 +145,29 @@ function createZeroClientInternal({
145
145
  (0, import_run.setCustomQueries)(customQueries);
146
146
  const DisabledContext = (0, import_react2.createContext)(false);
147
147
  let latestZeroInstance = null;
148
+ function lazyMutatePath(path) {
149
+ const resolve = () => {
150
+ if (latestZeroInstance === null) {
151
+ throw new Error(`Zero instance not initialized. Ensure ZeroProvider is mounted before accessing 'zero'.`);
152
+ }
153
+ let target = latestZeroInstance.mutate;
154
+ for (const key of path) target = target[key];
155
+ return target;
156
+ };
157
+ return new Proxy(function lazyMutator() {}, {
158
+ get(_, key) {
159
+ if (typeof key === "symbol") return void 0;
160
+ return lazyMutatePath([...path, key]);
161
+ },
162
+ apply(_, __, args) {
163
+ return resolve()(...args);
164
+ }
165
+ });
166
+ }
148
167
  const zero = new Proxy({}, {
149
168
  get(_, key) {
150
169
  if (latestZeroInstance === null) {
170
+ if (key === "mutate") return lazyMutatePath([]);
151
171
  throw new Error(`Zero instance not initialized. Ensure ZeroProvider is mounted before accessing 'zero'.`);
152
172
  }
153
173
  if (key === "delete") {
@@ -211,6 +231,14 @@ function createZeroClientInternal({
211
231
  const usePermission = createUsePermission(useQuery);
212
232
  const usePermissionDirect = createUsePermission(useQueryDirect);
213
233
  let cachedZero = null;
234
+ const REMINT_GUARD_MS = 12e3;
235
+ const REMINT_MAX_ATTEMPTS = 5;
236
+ const REMINT_ATTEMPT_RESET_MS = 6e4;
237
+ const remintControl = {
238
+ bump: null
239
+ };
240
+ let lastRemintAt = 0;
241
+ let remintAttempts = 0;
214
242
  function invalidateZeroInstance(instanceToInvalidate) {
215
243
  if (!instanceToInvalidate) return;
216
244
  if (cachedZero?.instance === instanceToInvalidate) {
@@ -233,6 +261,26 @@ function createZeroClientInternal({
233
261
  invalidateZeroInstance(instanceToDelete);
234
262
  }
235
263
  }
264
+ async function remint(opts = {}) {
265
+ if (!remintControl.bump) return false;
266
+ const now = Date.now();
267
+ const sinceLast = now - lastRemintAt;
268
+ if (lastRemintAt > 0 && sinceLast < REMINT_GUARD_MS) return false;
269
+ if (sinceLast > REMINT_ATTEMPT_RESET_MS) remintAttempts = 0;
270
+ if (remintAttempts >= REMINT_MAX_ATTEMPTS) return false;
271
+ lastRemintAt = now;
272
+ remintAttempts += 1;
273
+ const {
274
+ dropLocalState = true
275
+ } = opts;
276
+ if (dropLocalState && latestZeroInstance) {
277
+ await deleteZeroInstance(latestZeroInstance).catch(() => {});
278
+ }
279
+ const bump = remintControl.bump;
280
+ if (!bump) return false;
281
+ bump();
282
+ return true;
283
+ }
236
284
  const DISABLED_ZERO_STUB_CONNECTION_STATE = {
237
285
  current: {
238
286
  name: "closed"
@@ -266,6 +314,11 @@ function createZeroClientInternal({
266
314
  transport,
267
315
  pullIntervalMs = 3e4,
268
316
  beforeReload,
317
+ scheduleReload,
318
+ guardStorage,
319
+ benignLogFilter,
320
+ refreshAuth,
321
+ connectionDataset,
269
322
  disable,
270
323
  ...props
271
324
  }) => {
@@ -287,10 +340,17 @@ function createZeroClientInternal({
287
340
  can: permissionsHelpers.can
288
341
  });
289
342
  }, []);
343
+ const [remintGeneration, setRemintGeneration] = (0, import_react2.useState)(0);
344
+ (0, import_react2.useEffect)(() => {
345
+ remintControl.bump = () => setRemintGeneration(generation => generation + 1);
346
+ return () => {
347
+ remintControl.bump = null;
348
+ };
349
+ }, []);
290
350
  const instanceKey = JSON.stringify([Object.entries({
291
351
  kvStore: "mem",
292
352
  ...props
293
- }).filter(([key, value]) => key !== "auth" && typeof value !== "function" && value !== void 0).sort(([a], [b]) => a < b ? -1 : 1), hasAuth, transport]);
353
+ }).filter(([key, value]) => key !== "auth" && typeof value !== "function" && value !== void 0).sort(([a], [b]) => a < b ? -1 : 1), hasAuth, transport, remintGeneration]);
294
354
  const [instance2, setInstance] = (0, import_react2.useState)();
295
355
  (0, import_react2.useEffect)(() => {
296
356
  if (disable) {
@@ -317,7 +377,10 @@ function createZeroClientInternal({
317
377
  const recoveryDeps = {
318
378
  deleteLocalState: () => deleteZeroInstance(instanceRef.current),
319
379
  zeroEvents,
320
- beforeReload
380
+ beforeReload,
381
+ scheduleReload,
382
+ guardStorage,
383
+ benignLogFilter
321
384
  };
322
385
  const recovery = (0, import_recoverZeroClient.makeZeroRecovery)(recoveryDeps);
323
386
  const createdInstance = new import_zero.Zero({
@@ -365,7 +428,10 @@ function createZeroClientInternal({
365
428
  children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_react.ZeroContext.Provider, {
366
429
  value: liveInstance ?? DISABLED_ZERO_STUB,
367
430
  children: [liveInstance ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(SetZeroInstance, {}) : null, liveInstance ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(ConnectionMonitor, {
368
- zeroEvents
431
+ zeroEvents,
432
+ refreshAuth,
433
+ exposeDataset: connectionDataset,
434
+ datasetCacheUrl: connectionDataset ? props.cacheURL ?? props.server : void 0
369
435
  }) : null, children]
370
436
  })
371
437
  })
@@ -386,23 +452,55 @@ function createZeroClientInternal({
386
452
  return null;
387
453
  };
388
454
  const ConnectionMonitor = (0, import_react2.memo)(({
389
- zeroEvents: zeroEvents2
455
+ zeroEvents: zeroEvents2,
456
+ refreshAuth,
457
+ exposeDataset,
458
+ datasetCacheUrl
390
459
  }) => {
460
+ const zeroInstance = (0, import_react.useZero)();
391
461
  const state = (0, import_react.useConnectionState)();
392
462
  const prevState = (0, import_react2.useRef)(state.name);
463
+ const staleReconnectRef = (0, import_react2.useRef)(null);
464
+ const needsAuthRef = (0, import_react2.useRef)(false);
393
465
  (0, import_react2.useEffect)(() => {
394
- if (state.name !== prevState.current) {
395
- const reason = "reason" in state ? state.reason : "";
396
- prevState.current = state.name;
397
- if (state.name === "error" || state.name === "needs-auth") {
398
- const message = typeof reason === "string" ? reason : state.name;
466
+ const name = state.name;
467
+ const reason = "reason" in state && typeof state.reason === "string" ? state.reason : "";
468
+ if (exposeDataset && typeof document !== "undefined" && document.body) {
469
+ document.body.dataset.zeroState = name;
470
+ if (datasetCacheUrl) document.body.dataset.zeroCacheUrl = datasetCacheUrl;
471
+ if (reason) document.body.dataset.zeroReason = reason.slice(0, 200);else delete document.body.dataset.zeroReason;
472
+ if (name === "connected") document.body.dataset.zeroConnected = "true";else delete document.body.dataset.zeroConnected;
473
+ }
474
+ if (name === "error" && (0, import_recoverZeroClient.isRecoverableZeroStalePokeMessage)(reason)) {
475
+ if (staleReconnectRef.current !== reason) {
476
+ staleReconnectRef.current = reason;
477
+ void Promise.resolve(zeroInstance.connection?.connect?.()).catch(() => {});
478
+ }
479
+ return;
480
+ }
481
+ if (name !== "error") staleReconnectRef.current = null;
482
+ if (name === "needs-auth") {
483
+ if (refreshAuth && !needsAuthRef.current) {
484
+ needsAuthRef.current = true;
485
+ void refreshAuth().then(token => {
486
+ if (token) zeroInstance.connection?.connect?.({
487
+ auth: token
488
+ });
489
+ }).catch(() => {});
490
+ }
491
+ } else {
492
+ needsAuthRef.current = false;
493
+ }
494
+ if (name !== prevState.current) {
495
+ prevState.current = name;
496
+ if (name === "error" || name === "needs-auth") {
399
497
  zeroEvents2.emit({
400
498
  type: "error",
401
- message
499
+ message: reason || name
402
500
  });
403
501
  }
404
502
  }
405
- }, [state, zeroEvents2]);
503
+ }, [state, zeroEvents2, zeroInstance, refreshAuth, exposeDataset, datasetCacheUrl]);
406
504
  return null;
407
505
  });
408
506
  function preload(fnArg, paramsOrOptions, optionsArg) {
@@ -445,6 +543,7 @@ function createZeroClientInternal({
445
543
  usePermissionDirect,
446
544
  zero,
447
545
  preload,
448
- getQuery
546
+ getQuery,
547
+ remint
449
548
  };
450
549
  }
@@ -0,0 +1,163 @@
1
+ var import_zero = require("@rocicorp/zero");
2
+ var import_react = require("react");
3
+ var import_client = require("react-dom/client");
4
+ var import_vitest = require("vitest");
5
+ var import_createZeroClient = require("./createZeroClient.cjs");
6
+ var import_jsx_runtime = require("react/jsx-runtime");
7
+ const fakeZero = import_vitest.vi.hoisted(() => {
8
+ class FakeConnectionState {
9
+ current;
10
+ listeners = /* @__PURE__ */new Set();
11
+ constructor(initial) {
12
+ this.current = initial;
13
+ }
14
+ subscribe = cb => {
15
+ this.listeners.add(cb);
16
+ return () => {
17
+ this.listeners.delete(cb);
18
+ };
19
+ };
20
+ set(next) {
21
+ this.current = next;
22
+ for (const cb of this.listeners) cb();
23
+ }
24
+ }
25
+ class FakeZero {
26
+ context = {};
27
+ connection = {
28
+ state: new FakeConnectionState({
29
+ name: "connecting"
30
+ }),
31
+ connect: import_vitest.vi.fn(async () => {})
32
+ };
33
+ delete = import_vitest.vi.fn(async () => ({
34
+ errors: []
35
+ }));
36
+ close = import_vitest.vi.fn();
37
+ run = import_vitest.vi.fn(async () => []);
38
+ preload = import_vitest.vi.fn(() => ({
39
+ cleanup: () => {},
40
+ complete: Promise.resolve()
41
+ }));
42
+ constructor() {
43
+ instances.push(this);
44
+ }
45
+ }
46
+ const instances = [];
47
+ return {
48
+ FakeZero,
49
+ FakeConnectionState,
50
+ instances
51
+ };
52
+ });
53
+ import_vitest.vi.mock("@rocicorp/zero", async importOriginal => {
54
+ const actual = await importOriginal();
55
+ return {
56
+ ...actual,
57
+ Zero: fakeZero.FakeZero
58
+ };
59
+ });
60
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
61
+ const noteTable = (0, import_zero.table)("note").columns({
62
+ id: (0, import_zero.string)(),
63
+ body: (0, import_zero.string)()
64
+ }).primaryKey("id");
65
+ const schema = (0, import_zero.createSchema)({
66
+ tables: [noteTable]
67
+ });
68
+ const client = (0, import_createZeroClient.createZeroClient)({
69
+ schema,
70
+ models: {},
71
+ groupedQueries: {},
72
+ instanceName: "connection-test"
73
+ });
74
+ let container;
75
+ let root;
76
+ (0, import_vitest.beforeEach)(() => {
77
+ fakeZero.instances.length = 0;
78
+ container = document.createElement("div");
79
+ root = null;
80
+ delete document.body.dataset.zeroState;
81
+ delete document.body.dataset.zeroConnected;
82
+ delete document.body.dataset.zeroReason;
83
+ });
84
+ (0, import_vitest.afterEach)(() => {
85
+ if (root) (0, import_react.act)(() => root?.unmount());
86
+ });
87
+ async function mount(extraProps = {}, userID = "conn") {
88
+ root = (0, import_client.createRoot)(container);
89
+ await (0, import_react.act)(async () => {
90
+ root?.render(/* @__PURE__ */(0, import_jsx_runtime.jsx)(client.ProvideZero, {
91
+ cacheURL: "http://127.0.0.1:7788/zero",
92
+ userID,
93
+ ...extraProps,
94
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("span", {
95
+ children: "ok"
96
+ })
97
+ }));
98
+ await Promise.resolve();
99
+ });
100
+ return fakeZero.instances.at(-1);
101
+ }
102
+ (0, import_vitest.test)("refreshAuth reconnects in place on needs-auth, once per transition", async () => {
103
+ const refreshAuth = import_vitest.vi.fn(async () => "fresh-token");
104
+ const instance = await mount({
105
+ refreshAuth
106
+ }, "conn-auth");
107
+ await (0, import_react.act)(async () => {
108
+ instance.connection.state.set({
109
+ name: "needs-auth",
110
+ reason: "token expired"
111
+ });
112
+ await Promise.resolve();
113
+ });
114
+ (0, import_vitest.expect)(refreshAuth).toHaveBeenCalledTimes(1);
115
+ await (0, import_react.act)(async () => {
116
+ await Promise.resolve();
117
+ });
118
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledWith({
119
+ auth: "fresh-token"
120
+ });
121
+ });
122
+ (0, import_vitest.test)("stale-poke error reconnects instead of surfacing a fatal error", async () => {
123
+ const events = [];
124
+ const off = client.zeroEvents.listen(event => {
125
+ if (event) events.push(event);
126
+ });
127
+ const instance = await mount({}, "conn-stale");
128
+ await (0, import_react.act)(async () => {
129
+ instance.connection.state.set({
130
+ name: "error",
131
+ reason: "Server returned unexpected base cookie during sync"
132
+ });
133
+ await Promise.resolve();
134
+ });
135
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledTimes(1);
136
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledWith();
137
+ (0, import_vitest.expect)(events.some(event => event.type === "error")).toBe(false);
138
+ off();
139
+ });
140
+ (0, import_vitest.test)("connectionDataset mirrors connection state onto the body dataset", async () => {
141
+ const instance = await mount({
142
+ connectionDataset: true
143
+ }, "conn-dataset");
144
+ await (0, import_react.act)(async () => {
145
+ instance.connection.state.set({
146
+ name: "connected"
147
+ });
148
+ await Promise.resolve();
149
+ });
150
+ (0, import_vitest.expect)(document.body.dataset.zeroState).toBe("connected");
151
+ (0, import_vitest.expect)(document.body.dataset.zeroConnected).toBe("true");
152
+ (0, import_vitest.expect)(document.body.dataset.zeroCacheUrl).toBe("http://127.0.0.1:7788/zero");
153
+ await (0, import_react.act)(async () => {
154
+ instance.connection.state.set({
155
+ name: "error",
156
+ reason: "boom"
157
+ });
158
+ await Promise.resolve();
159
+ });
160
+ (0, import_vitest.expect)(document.body.dataset.zeroState).toBe("error");
161
+ (0, import_vitest.expect)(document.body.dataset.zeroConnected).toBeUndefined();
162
+ (0, import_vitest.expect)(document.body.dataset.zeroReason).toBe("boom");
163
+ });
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+
3
+ var import_jsx_runtime = require("react/jsx-runtime");
4
+ var import_zero = require("@rocicorp/zero");
5
+ var import_react = require("react");
6
+ var import_client = require("react-dom/client");
7
+ var import_vitest = require("vitest");
8
+ var import_createZeroClient = require("./createZeroClient.native.js");
9
+ function _class_call_check(instance, Constructor) {
10
+ if (!(instance instanceof Constructor)) {
11
+ throw new TypeError("Cannot call a class as a function");
12
+ }
13
+ }
14
+ function _defineProperties(target, props) {
15
+ for (var i = 0; i < props.length; i++) {
16
+ var descriptor = props[i];
17
+ descriptor.enumerable = descriptor.enumerable || false;
18
+ descriptor.configurable = true;
19
+ if ("value" in descriptor) descriptor.writable = true;
20
+ Object.defineProperty(target, descriptor.key, descriptor);
21
+ }
22
+ }
23
+ function _create_class(Constructor, protoProps, staticProps) {
24
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
25
+ if (staticProps) _defineProperties(Constructor, staticProps);
26
+ return Constructor;
27
+ }
28
+ function _define_property(obj, key, value) {
29
+ if (key in obj) {
30
+ Object.defineProperty(obj, key, {
31
+ value,
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true
35
+ });
36
+ } else {
37
+ obj[key] = value;
38
+ }
39
+ return obj;
40
+ }
41
+ var fakeZero = import_vitest.vi.hoisted(function () {
42
+ var FakeConnectionState = /* @__PURE__ */function () {
43
+ "use strict";
44
+
45
+ function FakeConnectionState2(initial) {
46
+ var _this = this;
47
+ _class_call_check(this, FakeConnectionState2);
48
+ _define_property(this, "current", void 0);
49
+ _define_property(this, "listeners", /* @__PURE__ */new Set());
50
+ _define_property(this, "subscribe", function (cb) {
51
+ _this.listeners.add(cb);
52
+ return function () {
53
+ _this.listeners.delete(cb);
54
+ };
55
+ });
56
+ this.current = initial;
57
+ }
58
+ _create_class(FakeConnectionState2, [{
59
+ key: "set",
60
+ value: function set(next) {
61
+ this.current = next;
62
+ var _iteratorNormalCompletion = true,
63
+ _didIteratorError = false,
64
+ _iteratorError = void 0;
65
+ try {
66
+ for (var _iterator = this.listeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
67
+ var cb = _step.value;
68
+ cb();
69
+ }
70
+ } catch (err) {
71
+ _didIteratorError = true;
72
+ _iteratorError = err;
73
+ } finally {
74
+ try {
75
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
76
+ _iterator.return();
77
+ }
78
+ } finally {
79
+ if (_didIteratorError) {
80
+ throw _iteratorError;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }]);
86
+ return FakeConnectionState2;
87
+ }();
88
+ var FakeZero = function FakeZero2() {
89
+ "use strict";
90
+
91
+ _class_call_check(this, FakeZero2);
92
+ _define_property(this, "context", {});
93
+ _define_property(this, "connection", {
94
+ state: new FakeConnectionState({
95
+ name: "connecting"
96
+ }),
97
+ connect: import_vitest.vi.fn(async function () {})
98
+ });
99
+ _define_property(this, "delete", import_vitest.vi.fn(async function () {
100
+ return {
101
+ errors: []
102
+ };
103
+ }));
104
+ _define_property(this, "close", import_vitest.vi.fn());
105
+ _define_property(this, "run", import_vitest.vi.fn(async function () {
106
+ return [];
107
+ }));
108
+ _define_property(this, "preload", import_vitest.vi.fn(function () {
109
+ return {
110
+ cleanup: function () {},
111
+ complete: Promise.resolve()
112
+ };
113
+ }));
114
+ instances.push(this);
115
+ };
116
+ var instances = [];
117
+ return {
118
+ FakeZero,
119
+ FakeConnectionState,
120
+ instances
121
+ };
122
+ });
123
+ import_vitest.vi.mock("@rocicorp/zero", async function (importOriginal) {
124
+ var actual = await importOriginal();
125
+ return {
126
+ ...actual,
127
+ Zero: fakeZero.FakeZero
128
+ };
129
+ });
130
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
131
+ var noteTable = (0, import_zero.table)("note").columns({
132
+ id: (0, import_zero.string)(),
133
+ body: (0, import_zero.string)()
134
+ }).primaryKey("id");
135
+ var schema = (0, import_zero.createSchema)({
136
+ tables: [noteTable]
137
+ });
138
+ var client = (0, import_createZeroClient.createZeroClient)({
139
+ schema,
140
+ models: {},
141
+ groupedQueries: {},
142
+ instanceName: "connection-test"
143
+ });
144
+ var container;
145
+ var root;
146
+ (0, import_vitest.beforeEach)(function () {
147
+ fakeZero.instances.length = 0;
148
+ container = document.createElement("div");
149
+ root = null;
150
+ delete document.body.dataset.zeroState;
151
+ delete document.body.dataset.zeroConnected;
152
+ delete document.body.dataset.zeroReason;
153
+ });
154
+ (0, import_vitest.afterEach)(function () {
155
+ if (root) (0, import_react.act)(function () {
156
+ return root === null || root === void 0 ? void 0 : root.unmount();
157
+ });
158
+ });
159
+ async function mount() {
160
+ var extraProps = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {},
161
+ userID = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "conn";
162
+ root = (0, import_client.createRoot)(container);
163
+ await (0, import_react.act)(async function () {
164
+ root === null || root === void 0 ? void 0 : root.render(/* @__PURE__ */(0, import_jsx_runtime.jsx)(client.ProvideZero, {
165
+ cacheURL: "http://127.0.0.1:7788/zero",
166
+ userID,
167
+ ...extraProps,
168
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("span", {
169
+ children: "ok"
170
+ })
171
+ }));
172
+ await Promise.resolve();
173
+ });
174
+ return fakeZero.instances.at(-1);
175
+ }
176
+ (0, import_vitest.test)("refreshAuth reconnects in place on needs-auth, once per transition", async function () {
177
+ var refreshAuth = import_vitest.vi.fn(async function () {
178
+ return "fresh-token";
179
+ });
180
+ var instance = await mount({
181
+ refreshAuth
182
+ }, "conn-auth");
183
+ await (0, import_react.act)(async function () {
184
+ instance.connection.state.set({
185
+ name: "needs-auth",
186
+ reason: "token expired"
187
+ });
188
+ await Promise.resolve();
189
+ });
190
+ (0, import_vitest.expect)(refreshAuth).toHaveBeenCalledTimes(1);
191
+ await (0, import_react.act)(async function () {
192
+ await Promise.resolve();
193
+ });
194
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledWith({
195
+ auth: "fresh-token"
196
+ });
197
+ });
198
+ (0, import_vitest.test)("stale-poke error reconnects instead of surfacing a fatal error", async function () {
199
+ var events = [];
200
+ var off = client.zeroEvents.listen(function (event) {
201
+ if (event) events.push(event);
202
+ });
203
+ var instance = await mount({}, "conn-stale");
204
+ await (0, import_react.act)(async function () {
205
+ instance.connection.state.set({
206
+ name: "error",
207
+ reason: "Server returned unexpected base cookie during sync"
208
+ });
209
+ await Promise.resolve();
210
+ });
211
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledTimes(1);
212
+ (0, import_vitest.expect)(instance.connection.connect).toHaveBeenCalledWith();
213
+ (0, import_vitest.expect)(events.some(function (event) {
214
+ return event.type === "error";
215
+ })).toBe(false);
216
+ off();
217
+ });
218
+ (0, import_vitest.test)("connectionDataset mirrors connection state onto the body dataset", async function () {
219
+ var instance = await mount({
220
+ connectionDataset: true
221
+ }, "conn-dataset");
222
+ await (0, import_react.act)(async function () {
223
+ instance.connection.state.set({
224
+ name: "connected"
225
+ });
226
+ await Promise.resolve();
227
+ });
228
+ (0, import_vitest.expect)(document.body.dataset.zeroState).toBe("connected");
229
+ (0, import_vitest.expect)(document.body.dataset.zeroConnected).toBe("true");
230
+ (0, import_vitest.expect)(document.body.dataset.zeroCacheUrl).toBe("http://127.0.0.1:7788/zero");
231
+ await (0, import_react.act)(async function () {
232
+ instance.connection.state.set({
233
+ name: "error",
234
+ reason: "boom"
235
+ });
236
+ await Promise.resolve();
237
+ });
238
+ (0, import_vitest.expect)(document.body.dataset.zeroState).toBe("error");
239
+ (0, import_vitest.expect)(document.body.dataset.zeroConnected).toBeUndefined();
240
+ (0, import_vitest.expect)(document.body.dataset.zeroReason).toBe("boom");
241
+ });
242
+ //# sourceMappingURL=createZeroClient.connection.test.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["import_jsx_runtime","require","import_zero","import_react","import_client","import_vitest","import_createZeroClient","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","fakeZero","vi","hoisted","FakeConnectionState","FakeConnectionState2","initial","_this","Set","cb","listeners","add","delete","current","set","next","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_iterator","Symbol","iterator","_step","done","err","return","FakeZero","FakeZero2","state","name","connect","fn","errors","cleanup","complete","Promise","resolve","instances","push","mock","importOriginal","actual","Zero","globalThis","IS_REACT_ACT_ENVIRONMENT","noteTable","table","columns","id","string","body","primaryKey","schema","createSchema","tables"],"sources":["../../src/createZeroClient.connection.test.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}