on-zero 0.6.2 → 0.6.4

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 (82) hide show
  1. package/dist/cjs/createZeroClient.cjs +91 -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 +99 -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 +197 -14
  11. package/dist/cjs/helpers/recoverZeroClient.native.js +220 -24
  12. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  13. package/dist/cjs/helpers/recoverZeroClient.test.cjs +241 -0
  14. package/dist/cjs/helpers/recoverZeroClient.test.native.js +269 -0
  15. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  16. package/dist/cjs/index.cjs +2 -0
  17. package/dist/cjs/index.native.js +2 -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/multiPartition.test.cjs +42 -0
  23. package/dist/cjs/multiPartition.test.native.js +51 -0
  24. package/dist/cjs/multiPartition.test.native.js.map +1 -0
  25. package/dist/esm/createZeroClient.connection.test.mjs +164 -0
  26. package/dist/esm/createZeroClient.connection.test.mjs.map +1 -0
  27. package/dist/esm/createZeroClient.connection.test.native.js +240 -0
  28. package/dist/esm/createZeroClient.connection.test.native.js.map +1 -0
  29. package/dist/esm/createZeroClient.mjs +92 -13
  30. package/dist/esm/createZeroClient.mjs.map +1 -1
  31. package/dist/esm/createZeroClient.native.js +100 -13
  32. package/dist/esm/createZeroClient.native.js.map +1 -1
  33. package/dist/esm/createZeroClient.recovery.test.mjs +52 -0
  34. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  35. package/dist/esm/createZeroClient.recovery.test.native.js +52 -0
  36. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  37. package/dist/esm/helpers/recoverZeroClient.mjs +196 -15
  38. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  39. package/dist/esm/helpers/recoverZeroClient.native.js +219 -25
  40. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  41. package/dist/esm/helpers/recoverZeroClient.test.mjs +242 -1
  42. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  43. package/dist/esm/helpers/recoverZeroClient.test.native.js +270 -1
  44. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  45. package/dist/esm/index.js +2 -2
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/index.mjs +2 -2
  48. package/dist/esm/index.mjs.map +1 -1
  49. package/dist/esm/index.native.js +2 -2
  50. package/dist/esm/index.native.js.map +1 -1
  51. package/dist/esm/multi.mjs +13 -1
  52. package/dist/esm/multi.mjs.map +1 -1
  53. package/dist/esm/multi.native.js +35 -1
  54. package/dist/esm/multi.native.js.map +1 -1
  55. package/dist/esm/multiPartition.test.mjs +43 -0
  56. package/dist/esm/multiPartition.test.mjs.map +1 -0
  57. package/dist/esm/multiPartition.test.native.js +49 -0
  58. package/dist/esm/multiPartition.test.native.js.map +1 -0
  59. package/lint/ssr-guards.js +164 -0
  60. package/package.json +2 -2
  61. package/readme.md +126 -0
  62. package/src/createZeroClient.connection.test.tsx +162 -0
  63. package/src/createZeroClient.recovery.test.tsx +68 -0
  64. package/src/createZeroClient.tsx +159 -13
  65. package/src/helpers/recoverZeroClient.test.ts +270 -1
  66. package/src/helpers/recoverZeroClient.ts +347 -50
  67. package/src/index.ts +6 -0
  68. package/src/multi.ts +33 -0
  69. package/src/multiPartition.test.ts +38 -0
  70. package/types/createZeroClient.connection.test.d.ts +5 -0
  71. package/types/createZeroClient.connection.test.d.ts.map +1 -0
  72. package/types/createZeroClient.d.ts +17 -0
  73. package/types/createZeroClient.d.ts.map +1 -1
  74. package/types/createZeroServer.d.ts +4 -4
  75. package/types/helpers/recoverZeroClient.d.ts +23 -1
  76. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  77. package/types/index.d.ts +1 -1
  78. package/types/index.d.ts.map +1 -1
  79. package/types/multi.d.ts +1 -0
  80. package/types/multi.d.ts.map +1 -1
  81. package/types/multiPartition.test.d.ts +2 -0
  82. package/types/multiPartition.test.d.ts.map +1 -0
@@ -211,6 +211,14 @@ function createZeroClientInternal({
211
211
  const usePermission = createUsePermission(useQuery);
212
212
  const usePermissionDirect = createUsePermission(useQueryDirect);
213
213
  let cachedZero = null;
214
+ const REMINT_GUARD_MS = 12e3;
215
+ const REMINT_MAX_ATTEMPTS = 5;
216
+ const REMINT_ATTEMPT_RESET_MS = 6e4;
217
+ const remintControl = {
218
+ bump: null
219
+ };
220
+ let lastRemintAt = 0;
221
+ let remintAttempts = 0;
214
222
  function invalidateZeroInstance(instanceToInvalidate) {
215
223
  if (!instanceToInvalidate) return;
216
224
  if (cachedZero?.instance === instanceToInvalidate) {
@@ -233,6 +241,26 @@ function createZeroClientInternal({
233
241
  invalidateZeroInstance(instanceToDelete);
234
242
  }
235
243
  }
244
+ async function remint(opts = {}) {
245
+ if (!remintControl.bump) return false;
246
+ const now = Date.now();
247
+ const sinceLast = now - lastRemintAt;
248
+ if (lastRemintAt > 0 && sinceLast < REMINT_GUARD_MS) return false;
249
+ if (sinceLast > REMINT_ATTEMPT_RESET_MS) remintAttempts = 0;
250
+ if (remintAttempts >= REMINT_MAX_ATTEMPTS) return false;
251
+ lastRemintAt = now;
252
+ remintAttempts += 1;
253
+ const {
254
+ dropLocalState = true
255
+ } = opts;
256
+ if (dropLocalState && latestZeroInstance) {
257
+ await deleteZeroInstance(latestZeroInstance).catch(() => {});
258
+ }
259
+ const bump = remintControl.bump;
260
+ if (!bump) return false;
261
+ bump();
262
+ return true;
263
+ }
236
264
  const DISABLED_ZERO_STUB_CONNECTION_STATE = {
237
265
  current: {
238
266
  name: "closed"
@@ -266,6 +294,11 @@ function createZeroClientInternal({
266
294
  transport,
267
295
  pullIntervalMs = 3e4,
268
296
  beforeReload,
297
+ scheduleReload,
298
+ guardStorage,
299
+ benignLogFilter,
300
+ refreshAuth,
301
+ connectionDataset,
269
302
  disable,
270
303
  ...props
271
304
  }) => {
@@ -287,10 +320,17 @@ function createZeroClientInternal({
287
320
  can: permissionsHelpers.can
288
321
  });
289
322
  }, []);
323
+ const [remintGeneration, setRemintGeneration] = (0, import_react2.useState)(0);
324
+ (0, import_react2.useEffect)(() => {
325
+ remintControl.bump = () => setRemintGeneration(generation => generation + 1);
326
+ return () => {
327
+ remintControl.bump = null;
328
+ };
329
+ }, []);
290
330
  const instanceKey = JSON.stringify([Object.entries({
291
331
  kvStore: "mem",
292
332
  ...props
293
- }).filter(([key, value]) => key !== "auth" && typeof value !== "function" && value !== void 0).sort(([a], [b]) => a < b ? -1 : 1), hasAuth, transport]);
333
+ }).filter(([key, value]) => key !== "auth" && typeof value !== "function" && value !== void 0).sort(([a], [b]) => a < b ? -1 : 1), hasAuth, transport, remintGeneration]);
294
334
  const [instance2, setInstance] = (0, import_react2.useState)();
295
335
  (0, import_react2.useEffect)(() => {
296
336
  if (disable) {
@@ -317,7 +357,10 @@ function createZeroClientInternal({
317
357
  const recoveryDeps = {
318
358
  deleteLocalState: () => deleteZeroInstance(instanceRef.current),
319
359
  zeroEvents,
320
- beforeReload
360
+ beforeReload,
361
+ scheduleReload,
362
+ guardStorage,
363
+ benignLogFilter
321
364
  };
322
365
  const recovery = (0, import_recoverZeroClient.makeZeroRecovery)(recoveryDeps);
323
366
  const createdInstance = new import_zero.Zero({
@@ -365,7 +408,10 @@ function createZeroClientInternal({
365
408
  children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_react.ZeroContext.Provider, {
366
409
  value: liveInstance ?? DISABLED_ZERO_STUB,
367
410
  children: [liveInstance ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(SetZeroInstance, {}) : null, liveInstance ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(ConnectionMonitor, {
368
- zeroEvents
411
+ zeroEvents,
412
+ refreshAuth,
413
+ exposeDataset: connectionDataset,
414
+ datasetCacheUrl: connectionDataset ? props.cacheURL ?? props.server : void 0
369
415
  }) : null, children]
370
416
  })
371
417
  })
@@ -386,23 +432,55 @@ function createZeroClientInternal({
386
432
  return null;
387
433
  };
388
434
  const ConnectionMonitor = (0, import_react2.memo)(({
389
- zeroEvents: zeroEvents2
435
+ zeroEvents: zeroEvents2,
436
+ refreshAuth,
437
+ exposeDataset,
438
+ datasetCacheUrl
390
439
  }) => {
440
+ const zeroInstance = (0, import_react.useZero)();
391
441
  const state = (0, import_react.useConnectionState)();
392
442
  const prevState = (0, import_react2.useRef)(state.name);
443
+ const staleReconnectRef = (0, import_react2.useRef)(null);
444
+ const needsAuthRef = (0, import_react2.useRef)(false);
393
445
  (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;
446
+ const name = state.name;
447
+ const reason = "reason" in state && typeof state.reason === "string" ? state.reason : "";
448
+ if (exposeDataset && typeof document !== "undefined" && document.body) {
449
+ document.body.dataset.zeroState = name;
450
+ if (datasetCacheUrl) document.body.dataset.zeroCacheUrl = datasetCacheUrl;
451
+ if (reason) document.body.dataset.zeroReason = reason.slice(0, 200);else delete document.body.dataset.zeroReason;
452
+ if (name === "connected") document.body.dataset.zeroConnected = "true";else delete document.body.dataset.zeroConnected;
453
+ }
454
+ if (name === "error" && (0, import_recoverZeroClient.isRecoverableZeroStalePokeMessage)(reason)) {
455
+ if (staleReconnectRef.current !== reason) {
456
+ staleReconnectRef.current = reason;
457
+ void Promise.resolve(zeroInstance.connection?.connect?.()).catch(() => {});
458
+ }
459
+ return;
460
+ }
461
+ if (name !== "error") staleReconnectRef.current = null;
462
+ if (name === "needs-auth") {
463
+ if (refreshAuth && !needsAuthRef.current) {
464
+ needsAuthRef.current = true;
465
+ void refreshAuth().then(token => {
466
+ if (token) zeroInstance.connection?.connect?.({
467
+ auth: token
468
+ });
469
+ }).catch(() => {});
470
+ }
471
+ } else {
472
+ needsAuthRef.current = false;
473
+ }
474
+ if (name !== prevState.current) {
475
+ prevState.current = name;
476
+ if (name === "error" || name === "needs-auth") {
399
477
  zeroEvents2.emit({
400
478
  type: "error",
401
- message
479
+ message: reason || name
402
480
  });
403
481
  }
404
482
  }
405
- }, [state, zeroEvents2]);
483
+ }, [state, zeroEvents2, zeroInstance, refreshAuth, exposeDataset, datasetCacheUrl]);
406
484
  return null;
407
485
  });
408
486
  function preload(fnArg, paramsOrOptions, optionsArg) {
@@ -445,6 +523,7 @@ function createZeroClientInternal({
445
523
  usePermissionDirect,
446
524
  zero,
447
525
  preload,
448
- getQuery
526
+ getQuery,
527
+ remint
449
528
  };
450
529
  }
@@ -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":"AAEA;;AACA,IAAAA,kBAAoB,GAAAC,OAAA;AACpB,IAAAC,WAAA,GAAAD,OAAsC;AACtC,IAAAE,YAAA,GAAAF,OAAwD;AAgDxD,IAAAG,aAAA,GAAAH,OAAA,mBAAiC;AA2CzB,IAAAI,aAAA,GAAAJ,OAAA;AAvFR,IAAAK,uBAAiB,GAAAL,OAAG,+BAAc;AAAA,SAC1BM,kBAAAC,QAAoB,EAAAC,WAAA;EAAA,IACxB,EAAAD,QAAA,YAAAC,WAAA;IACA,UAAAC,SAAY,oCAAoB;EAAA;AAE9B;AAAe,SACjBC,kBAAAC,MAAA,EAAAC,KAAA;EAAA,KACA,IAAAC,CAAA,IAAY,EAACA,CAAA,GAAAD,KAAmB,CAAAE,MAAA,EAAAD,CAAA;IAC9B,IAAAE,UAAK,GAAUH,KAAI,CAAEC,CAAA;IACrBE,UAAO,CAAAC,UAAM,GAAAD,UAAA,CAAAC,UAAA;IACXD,UAAK,CAAAE,YAAU,GAAO,IAAE;IAAA,IAC1B,WAAAF,UAAA,EAAAA,UAAA,CAAAG,QAAA;IACFC,MAAA,CAAAC,cAAA,CAAAT,MAAA,EAAAI,UAAA,CAAAM,GAAA,EAAAN,UAAA;EAAA;AAEE;AACA,SAAAO,aAAWA,CAAMd,WAAK,EAAAe,UAAc,EAAAC,WAAA;EAAA,IACtCD,UAAA,EAAAb,iBAAA,CAAAF,WAAA,CAAAiB,SAAA,EAAAF,UAAA;EACF,IAAAC,WAAA,EAAAd,iBAAA,CAAAF,WAAA,EAAAgB,WAAA;EAEA,OAAMhB,WAAS;AAAA;AACO,SACXkB,gBAAaA,CAAAC,GAAA,EAAAN,GAAA,EAAAO,KAAA;EAAA,IACpBP,GAAA,IAAOM,GAAA,EAAI;IAA0CR,MACrD,CAAAC,cAAS,CAAAO,GAAA,EAAAN,GAAG,EAAG;MAAaO,KAAC;MAC/BZ,UAAA;MACSC,YAAS;MACTC,QAAQ;IACR;EAA0B,OAC1B;IAAyCS,GAAG,CAAAN,GAAA,IAAAO,KAAU;EAAoB;EAGjF,OAAAD,GAAA;AAAmB;AACrB,IACFE,QAAA,GAAAzB,aAAA,CAAA0B,EAAA,CAAAC,OAAA;EAEA,IAAAC,mBAA+B;IAC/B,YAAS;;IACV,SAAAC,qBAAAC,OAAA;MAED,IAAAC,KAAA,GAAG,IAAK;MACN7B,iBAAqB,OAAA2B,oBAAgD;MACrEP,gBAAoB,OAAM,SAAS,QAAS;MAC7CA,gBAAA,uCAAAU,GAAA;MAQDV,gBAAW,kBAA2B,YAAAW,EAAA;QAEhCF,KAAA,CAAAG,SAAY,CAAAC,GAAA,CAAAF,EAAA;QACZ,mBAAS;UAETF,KAAA,CAAAG,SAAS,CAAAE,MAAA,CAAAH,EAAA;QACb;MACA;MACA,KAAAI,OAAgB,GAACP,OAAA;IACjB;IACDZ,aAAA,CAAAW,oBAAA,GAEG;MACAZ,GAAA;MAEJO,KAAA,WAAAc,IAAAC,IAAW;QACT,IAAS,CAAAF,OAAU,GAAAE,IAAA;QACnB,IAAYC,yBAAuB,GAAK;UAAAC,iBAAA;UAAAC,cAAA;QACjC;UACA,SAASC,SAAK,GAAQ,KAAAT,SAAA,CAAAU,MAAA,CAAAC,QAAA,KAAAC,KAAA,IAAAN,yBAAA,IAAAM,KAAA,GAAAH,SAAA,CAAAJ,IAAA,IAAAQ,IAAA,GAAAP,yBAAA;YACtB,IAASP,EAAA,GAAKa,KAAA,CAAAtB,KAAQ;YACtBS,EAAA,EAAS;UACjB;QAED,SAAAe,GAAA;UACYP,iBAAA,OAAI;UACfC,cAAA,GAAAM,GAAA;QAED,UAAe;UACb,IAAO;YACD,KAAAR,yBAAgB,IAAAG,SAAA,CAAAM,MAAA;cACdN,SAAA,CAAAM,MAAA;YACJ;UAAC,UAAO;YAAP,IAAAR,iBAAA;cACC,MAASC,cAAA;YACT;UACC;QAED;MAAQ;IACV,EACF;IACA,OAAMb,oBAAgB;EACxB,CAAC;EACD,IAAAqB,QAAO,YAASC,SAAeA,CAAA;IACjC;;IAEAjD,iBAAA,KAAK,EAAAiD,SAAA;IACH7B,gBAAM,KAAc,cAAG;IACvBA,gBAAiB,KAAM,cAAQ;MAE/B8B,KAAA,EAAM,IAAAxB,mBAAI;QACRyB,IAAA,EAAS;MACT;MACDC,OAAA,EAAAtD,aAAA,CAAA0B,EAAA,CAAA6B,EAAA,oBAED;IACA;IACEjC,gBAAc,OAAQ,UAAAtB,aAAA,CAAA0B,EAAA,CAAA6B,EAAA;MACvB;QACDC,MAAA;MACD;IAED;IACElC,gBAAyC,gBAAAtB,aAAA,CAAA0B,EAAA,CAAA6B,EAAA;IACzCjC,gBAAY,CAAO,WAAW,EAAAtB,aAAQ,CAAA0B,EAAU,CAAA6B,EAAA;MAC9C,OAAI,EAAO;IACZ;IACDjC,gBAAiB,KAAM,WAAU,EAAAtB,aAAY,CAAA0B,EAAA,CAAA6B,EAAA;MAE7C,OAAM;QACJE,OAAS,WAAAA,CAAA,EAAW,CAClB;QACAC,QAAQ,EAAAC,OAAA,CAAAC,OAAA;MACT;IACD;IACDC,SAAA,CAAAC,IAAA;EAGD;EACA,IAAAD,SAAA;EAEA;IACAX,QAAI;IACLtB,mBAAA;IAEDiC;EACE;AAEA;AACE7D,aAAS,CAAA0B,EAAA,CAAAqC,IAAA,iBAAuB,kBAAmBC,cAAA;EACnD,IAAAC,MAAM,SAAQD,cAAQ;EACxB,OAAC;IACD,GAAAC,MAAA;IACAC,IAAA,EAAAzC,QAAA,CAAAyB;EACA;AAEA;AACEiB,UAAA,CAAAC,wBAA8B,GAAE,IAAM;AACtC,IAAAC,SAAM,KAAQ,EAAAxE,WAAQ,CAAAyE,KAAA,UAAAC,OAAA;EACxBC,EAAC,MAAA3E,WAAA,CAAA4E,MAAA;EACDC,IAAA,MAAA7E,WAAA,CAAA4E,MAAO;AACP,GAAAE,UAAA;AACA,IAAAC,MAAA,OAAA/E,WAAO,CAAAgF,YAAS,EAAK;EACtBC,MAAA,G","ignoreList":[]}