on-zero 0.4.23 → 0.4.25

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 (93) hide show
  1. package/dist/cjs/combineZeroClients.cjs +101 -0
  2. package/dist/cjs/combineZeroClients.native.js +150 -0
  3. package/dist/cjs/combineZeroClients.native.js.map +1 -0
  4. package/dist/cjs/createUseQuery.cjs +96 -4
  5. package/dist/cjs/createUseQuery.native.js +132 -4
  6. package/dist/cjs/createUseQuery.native.js.map +1 -1
  7. package/dist/cjs/createZeroClient.cjs +41 -13
  8. package/dist/cjs/createZeroClient.native.js +75 -43
  9. package/dist/cjs/createZeroClient.native.js.map +1 -1
  10. package/dist/cjs/index.cjs +1 -0
  11. package/dist/cjs/index.native.js +1 -0
  12. package/dist/cjs/index.native.js.map +1 -1
  13. package/dist/cjs/instanceRegistry.cjs +65 -0
  14. package/dist/cjs/instanceRegistry.native.js +111 -0
  15. package/dist/cjs/instanceRegistry.native.js.map +1 -0
  16. package/dist/cjs/multiInstance.test.cjs +322 -0
  17. package/dist/cjs/multiInstance.test.native.js +387 -0
  18. package/dist/cjs/multiInstance.test.native.js.map +1 -0
  19. package/dist/cjs/multiInstanceNested.test.cjs +206 -0
  20. package/dist/cjs/multiInstanceNested.test.native.js +254 -0
  21. package/dist/cjs/multiInstanceNested.test.native.js.map +1 -0
  22. package/dist/cjs/run.cjs +5 -5
  23. package/dist/cjs/run.native.js +6 -5
  24. package/dist/cjs/run.native.js.map +1 -1
  25. package/dist/cjs/zeroRunner.cjs +4 -1
  26. package/dist/cjs/zeroRunner.native.js +4 -1
  27. package/dist/cjs/zeroRunner.native.js.map +1 -1
  28. package/dist/esm/combineZeroClients.mjs +76 -0
  29. package/dist/esm/combineZeroClients.mjs.map +1 -0
  30. package/dist/esm/combineZeroClients.native.js +122 -0
  31. package/dist/esm/combineZeroClients.native.js.map +1 -0
  32. package/dist/esm/createUseQuery.mjs +96 -5
  33. package/dist/esm/createUseQuery.mjs.map +1 -1
  34. package/dist/esm/createUseQuery.native.js +132 -5
  35. package/dist/esm/createUseQuery.native.js.map +1 -1
  36. package/dist/esm/createZeroClient.mjs +42 -14
  37. package/dist/esm/createZeroClient.mjs.map +1 -1
  38. package/dist/esm/createZeroClient.native.js +76 -44
  39. package/dist/esm/createZeroClient.native.js.map +1 -1
  40. package/dist/esm/index.js +1 -0
  41. package/dist/esm/index.js.map +1 -1
  42. package/dist/esm/index.mjs +1 -0
  43. package/dist/esm/index.mjs.map +1 -1
  44. package/dist/esm/index.native.js +1 -0
  45. package/dist/esm/index.native.js.map +1 -1
  46. package/dist/esm/instanceRegistry.mjs +38 -0
  47. package/dist/esm/instanceRegistry.mjs.map +1 -0
  48. package/dist/esm/instanceRegistry.native.js +81 -0
  49. package/dist/esm/instanceRegistry.native.js.map +1 -0
  50. package/dist/esm/multiInstance.test.mjs +323 -0
  51. package/dist/esm/multiInstance.test.mjs.map +1 -0
  52. package/dist/esm/multiInstance.test.native.js +385 -0
  53. package/dist/esm/multiInstance.test.native.js.map +1 -0
  54. package/dist/esm/multiInstanceNested.test.mjs +207 -0
  55. package/dist/esm/multiInstanceNested.test.mjs.map +1 -0
  56. package/dist/esm/multiInstanceNested.test.native.js +252 -0
  57. package/dist/esm/multiInstanceNested.test.native.js.map +1 -0
  58. package/dist/esm/run.mjs +5 -5
  59. package/dist/esm/run.mjs.map +1 -1
  60. package/dist/esm/run.native.js +6 -5
  61. package/dist/esm/run.native.js.map +1 -1
  62. package/dist/esm/zeroRunner.mjs +4 -1
  63. package/dist/esm/zeroRunner.mjs.map +1 -1
  64. package/dist/esm/zeroRunner.native.js +4 -1
  65. package/dist/esm/zeroRunner.native.js.map +1 -1
  66. package/package.json +5 -3
  67. package/readme.md +59 -0
  68. package/src/combineZeroClients.tsx +186 -0
  69. package/src/createUseQuery.tsx +186 -12
  70. package/src/createZeroClient.tsx +107 -42
  71. package/src/index.ts +1 -0
  72. package/src/instanceRegistry.ts +75 -0
  73. package/src/multiInstance.test.tsx +284 -0
  74. package/src/multiInstanceNested.test.tsx +205 -0
  75. package/src/run.ts +7 -6
  76. package/src/zeroRunner.ts +7 -1
  77. package/types/combineZeroClients.d.ts +38 -0
  78. package/types/combineZeroClients.d.ts.map +1 -0
  79. package/types/createUseQuery.d.ts +15 -0
  80. package/types/createUseQuery.d.ts.map +1 -1
  81. package/types/createZeroClient.d.ts +7 -2
  82. package/types/createZeroClient.d.ts.map +1 -1
  83. package/types/index.d.ts +1 -0
  84. package/types/index.d.ts.map +1 -1
  85. package/types/instanceRegistry.d.ts +15 -0
  86. package/types/instanceRegistry.d.ts.map +1 -0
  87. package/types/multiInstance.test.d.ts +2 -0
  88. package/types/multiInstance.test.d.ts.map +1 -0
  89. package/types/multiInstanceNested.test.d.ts +5 -0
  90. package/types/multiInstanceNested.test.d.ts.map +1 -0
  91. package/types/run.d.ts.map +1 -1
  92. package/types/zeroRunner.d.ts +3 -1
  93. package/types/zeroRunner.d.ts.map +1 -1
@@ -0,0 +1,252 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createSchema, string, table } from "@rocicorp/zero";
3
+ import { act } from "react";
4
+ import { createRoot } from "react-dom/client";
5
+ import { afterEach, beforeEach, expect, test } from "vitest";
6
+ import { combineZeroClients } from "./combineZeroClients.native.js";
7
+ import { createZeroClient } from "./createZeroClient.native.js";
8
+ import { zql } from "./zql.native.js";
9
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
10
+ var userTable = table("user").columns({
11
+ id: string(),
12
+ name: string()
13
+ }).primaryKey("id");
14
+ var taskTable = table("task").columns({
15
+ id: string(),
16
+ title: string()
17
+ }).primaryKey("id");
18
+ var schema = createSchema({
19
+ tables: [userTable, taskTable]
20
+ });
21
+ var controlModels = {
22
+ user: {
23
+ mutate: {
24
+ seed: async function (ctx, row) {
25
+ await ctx.tx.mutate.user.upsert(row);
26
+ }
27
+ }
28
+ }
29
+ };
30
+ var ctlUserById = function (args) {
31
+ return zql.user.where("id", args.id).one();
32
+ };
33
+ var control = createZeroClient({
34
+ schema,
35
+ models: controlModels,
36
+ groupedQueries: {
37
+ ctlUser: {
38
+ byId: ctlUserById
39
+ }
40
+ },
41
+ instanceName: "nested-control"
42
+ });
43
+ var projectModels = {
44
+ prjSeed: {
45
+ mutate: {
46
+ seedUser: async function (ctx, row) {
47
+ await ctx.tx.mutate.user.upsert(row);
48
+ }
49
+ }
50
+ }
51
+ };
52
+ var prjTaskById = function (args) {
53
+ return zql.task.where("id", args.id).one();
54
+ };
55
+ var project = createZeroClient({
56
+ schema,
57
+ models: projectModels,
58
+ groupedQueries: {
59
+ prjTask: {
60
+ byId: prjTaskById
61
+ }
62
+ },
63
+ instanceName: "nested-project"
64
+ });
65
+ var combined = combineZeroClients(control, project);
66
+ var root;
67
+ var container;
68
+ beforeEach(function () {
69
+ resetProbe();
70
+ container = document.createElement("div");
71
+ document.body.appendChild(container);
72
+ root = createRoot(container);
73
+ });
74
+ afterEach(async function () {
75
+ await act(async function () {
76
+ return root.unmount();
77
+ });
78
+ container.remove();
79
+ });
80
+ var render = function (ui) {
81
+ return act(async function () {
82
+ return root.render(ui);
83
+ });
84
+ };
85
+ async function waitFor(condition, what) {
86
+ for (var i = 0; i < 200; i++) {
87
+ if (condition()) return;
88
+ await act(async function () {
89
+ await new Promise(function (resolve) {
90
+ return setTimeout(resolve, 5);
91
+ });
92
+ });
93
+ }
94
+ throw new Error(`timed out waiting for ${what}`);
95
+ }
96
+ var probe = {
97
+ data: void 0,
98
+ renders: 0
99
+ };
100
+ function resetProbe() {
101
+ probe.data = void 0;
102
+ probe.renders = 0;
103
+ }
104
+ function ControlUserProbe(param) {
105
+ var {
106
+ id
107
+ } = param;
108
+ var [data] = combined.useQuery(ctlUserById, {
109
+ id
110
+ });
111
+ probe.data = data !== null && data !== void 0 ? data : void 0;
112
+ probe.renders++;
113
+ return null;
114
+ }
115
+ var seedControl = async function (row) {
116
+ await act(async function () {
117
+ await control.zero.mutate.user.seed(row).client;
118
+ });
119
+ };
120
+ var seedProject = async function (row) {
121
+ await act(async function () {
122
+ await project.zero.mutate.prjSeed.seedUser(row).client;
123
+ });
124
+ };
125
+ test("outer-instance query reads the OUTER store under nested providers", async function () {
126
+ var _probe_data;
127
+ await render(/* @__PURE__ */_jsx(control.ProvideZero, {
128
+ server: null,
129
+ userID: "t1-ctl",
130
+ children: /* @__PURE__ */_jsx(project.ProvideZero, {
131
+ server: null,
132
+ userID: "t1-prj",
133
+ children: /* @__PURE__ */_jsx(ControlUserProbe, {
134
+ id: "u1"
135
+ })
136
+ })
137
+ }));
138
+ await waitFor(function () {
139
+ return probe.renders > 0;
140
+ }, "probe mount");
141
+ await seedControl({
142
+ id: "u1",
143
+ name: "from-control"
144
+ });
145
+ await seedProject({
146
+ id: "u1",
147
+ name: "from-project"
148
+ });
149
+ await waitFor(function () {
150
+ return probe.data !== void 0;
151
+ }, "control row visible");
152
+ expect((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name).toBe("from-control");
153
+ });
154
+ test("inner provider unmount/remount does not break outer-instance subscriptions", async function () {
155
+ var App = function (param) {
156
+ var {
157
+ showInner
158
+ } = param;
159
+ return /* @__PURE__ */_jsx(control.ProvideZero, {
160
+ server: null,
161
+ userID: "t2-ctl",
162
+ children: showInner ? /* @__PURE__ */_jsx(project.ProvideZero, {
163
+ server: null,
164
+ userID: "t2-prj",
165
+ children: /* @__PURE__ */_jsx(ControlUserProbe, {
166
+ id: "u2"
167
+ })
168
+ }) : /* @__PURE__ */_jsx(ControlUserProbe, {
169
+ id: "u2"
170
+ })
171
+ });
172
+ };
173
+ await render(/* @__PURE__ */_jsx(App, {
174
+ showInner: true
175
+ }));
176
+ await waitFor(function () {
177
+ return probe.renders > 0;
178
+ }, "probe mount");
179
+ await seedControl({
180
+ id: "u2",
181
+ name: "v1"
182
+ });
183
+ await waitFor(function () {
184
+ var _probe_data;
185
+ return ((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name) === "v1";
186
+ }, "v1 visible");
187
+ await render(/* @__PURE__ */_jsx(App, {
188
+ showInner: false
189
+ }));
190
+ await seedControl({
191
+ id: "u2",
192
+ name: "v2"
193
+ });
194
+ await waitFor(function () {
195
+ var _probe_data;
196
+ return ((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name) === "v2";
197
+ }, "v2 visible after inner unmount");
198
+ await render(/* @__PURE__ */_jsx(App, {
199
+ showInner: true
200
+ }));
201
+ await seedControl({
202
+ id: "u2",
203
+ name: "v3"
204
+ });
205
+ await waitFor(function () {
206
+ var _probe_data;
207
+ return ((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name) === "v3";
208
+ }, "v3 visible after inner remount");
209
+ });
210
+ test("direct-path views re-materialize when the owning instance rotates", async function () {
211
+ var App = function (param) {
212
+ var {
213
+ userID
214
+ } = param;
215
+ return /* @__PURE__ */_jsx(control.ProvideZero, {
216
+ server: null,
217
+ userID,
218
+ children: /* @__PURE__ */_jsx(ControlUserProbe, {
219
+ id: "u3"
220
+ })
221
+ });
222
+ };
223
+ await render(/* @__PURE__ */_jsx(App, {
224
+ userID: "rot-1"
225
+ }));
226
+ await waitFor(function () {
227
+ return probe.renders > 0;
228
+ }, "probe mount");
229
+ await seedControl({
230
+ id: "u3",
231
+ name: "before-rotation"
232
+ });
233
+ await waitFor(function () {
234
+ var _probe_data;
235
+ return ((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name) === "before-rotation";
236
+ }, "pre-rotation row");
237
+ await render(/* @__PURE__ */_jsx(App, {
238
+ userID: "rot-2"
239
+ }));
240
+ await waitFor(function () {
241
+ return probe.data === void 0;
242
+ }, "view reset to the new empty store");
243
+ await seedControl({
244
+ id: "u3",
245
+ name: "after-rotation"
246
+ });
247
+ await waitFor(function () {
248
+ var _probe_data;
249
+ return ((_probe_data = probe.data) === null || _probe_data === void 0 ? void 0 : _probe_data.name) === "after-rotation";
250
+ }, "post-rotation row");
251
+ });
252
+ //# sourceMappingURL=multiInstanceNested.test.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["jsx","_jsx","createSchema","string","table","act","createRoot","afterEach","beforeEach","expect","test","combineZeroClients","createZeroClient","zql","globalThis","IS_REACT_ACT_ENVIRONMENT","userTable","columns","id","name","primaryKey","taskTable","title","schema","tables","controlModels","user","mutate","seed","ctx","row","tx","upsert","ctlUserById","args","where","one","control","models","groupedQueries","ctlUser","byId","instanceName","projectModels","prjSeed","seedUser","prjTaskById","task","project","prjTask","combined","root","container","resetProbe","document","createElement","body","appendChild","unmount","remove","render","ui","waitFor","condition","what","i","Promise","resolve","setTimeout","Error","probe","data","renders","ControlUserProbe","param","useQuery","seedControl","zero","client","seedProject"],"sources":["../../src/multiInstanceNested.test.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
package/dist/esm/run.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { getInstanceForQueryFn } from "./instanceRegistry.mjs";
1
2
  import { resolveQuery } from "./resolveQuery.mjs";
2
3
  import { getRunner } from "./zeroRunner.mjs";
3
4
  let customQueriesRef = null;
@@ -14,21 +15,20 @@ function run(queryOrFn, paramsOrMode, modeArg) {
14
15
  const hasParams = modeArg !== void 0 || paramsOrMode && paramsOrMode !== "complete";
15
16
  const params = hasParams ? paramsOrMode : void 0;
16
17
  const mode = hasParams ? modeArg : paramsOrMode;
17
- const runner = getRunner();
18
18
  const options = mode === "complete" ? {
19
19
  type: "complete"
20
20
  } : void 0;
21
21
  if (queryOrFn && queryOrFn["ast"]) {
22
- return runner(queryOrFn, options);
22
+ return getRunner()(queryOrFn, options);
23
23
  }
24
- const customQueries = getCustomQueries();
24
+ const instance = getInstanceForQueryFn(queryOrFn);
25
+ const customQueries = instance?.customQueries ?? getCustomQueries();
25
26
  const queryRequest = resolveQuery({
26
27
  customQueries,
27
28
  fn: queryOrFn,
28
29
  params
29
30
  });
30
- const out = runner(queryRequest, options);
31
- return out;
31
+ return getRunner(instance)(queryRequest, options);
32
32
  }
33
33
  export { run, setCustomQueries };
34
34
  //# sourceMappingURL=run.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["resolveQuery","getRunner","customQueriesRef","setCustomQueries","queries","getCustomQueries","Error","run","queryOrFn","paramsOrMode","modeArg","hasParams","params","mode","runner","options","type","customQueries","queryRequest","fn","out"],"sources":["../../src/run.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,YAAA,QAAuC;AAChD,SAASC,SAAA,QAAiB;AAS1B,IAAIC,gBAAA,GAA4C;AAEzC,SAASC,iBAAiBC,OAAA,EAA2B;EAC1DF,gBAAA,GAAmBE,OAAA;AACrB;AAEA,SAASC,iBAAA,EAAqC;EAC5C,IAAI,CAACH,gBAAA,EAAkB;IACrB,MAAM,IAAII,KAAA,CACR,8FACF;EACF;EACA,OAAOJ,gBAAA;AACT;AAiCO,SAASK,IACdC,SAAA,EACAC,YAAA,EACAC,OAAA,EACc;EACd,MAAMC,SAAA,GAAYD,OAAA,KAAY,UAAcD,YAAA,IAAgBA,YAAA,KAAiB;EAC7E,MAAMG,MAAA,GAASD,SAAA,GAAYF,YAAA,GAAe;EAC1C,MAAMI,IAAA,GAAOF,SAAA,GAAYD,OAAA,GAAUD,YAAA;EACnC,MAAMK,MAAA,GAASb,SAAA,CAAU;EACzB,MAAMc,OAAA,GACJF,IAAA,KAAS,aACJ;IACCG,IAAA,EAAM;EACR,IACA;EAEN,IAAIR,SAAA,IAAaA,SAAA,CAAU,KAAK,GAAG;IAEjC,OAAOM,MAAA,CAAON,SAAA,EAAWO,OAAO;EAClC;EAEA,MAAME,aAAA,GAAgBZ,gBAAA,CAAiB;EACvC,MAAMa,YAAA,GAAelB,YAAA,CAAa;IAAEiB,aAAA;IAAeE,EAAA,EAAIX,SAAA;IAAWI;EAAO,CAAC;EAE1E,MAAMQ,GAAA,GAAMN,MAAA,CAAOI,YAAA,EAAqBH,OAAO;EAE/C,OAAOK,GAAA;AACT","ignoreList":[]}
1
+ {"version":3,"names":["getInstanceForQueryFn","resolveQuery","getRunner","customQueriesRef","setCustomQueries","queries","getCustomQueries","Error","run","queryOrFn","paramsOrMode","modeArg","hasParams","params","mode","options","type","instance","customQueries","queryRequest","fn"],"sources":["../../src/run.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,qBAAA,QAA6B;AACtC,SAASC,YAAA,QAAuC;AAChD,SAASC,SAAA,QAAiB;AAS1B,IAAIC,gBAAA,GAA4C;AAEzC,SAASC,iBAAiBC,OAAA,EAA2B;EAC1DF,gBAAA,GAAmBE,OAAA;AACrB;AAEA,SAASC,iBAAA,EAAqC;EAC5C,IAAI,CAACH,gBAAA,EAAkB;IACrB,MAAM,IAAII,KAAA,CACR,8FACF;EACF;EACA,OAAOJ,gBAAA;AACT;AAiCO,SAASK,IACdC,SAAA,EACAC,YAAA,EACAC,OAAA,EACc;EACd,MAAMC,SAAA,GAAYD,OAAA,KAAY,UAAcD,YAAA,IAAgBA,YAAA,KAAiB;EAC7E,MAAMG,MAAA,GAASD,SAAA,GAAYF,YAAA,GAAe;EAC1C,MAAMI,IAAA,GAAOF,SAAA,GAAYD,OAAA,GAAUD,YAAA;EACnC,MAAMK,OAAA,GACJD,IAAA,KAAS,aACJ;IACCE,IAAA,EAAM;EACR,IACA;EAEN,IAAIP,SAAA,IAAaA,SAAA,CAAU,KAAK,GAAG;IAEjC,OAAOP,SAAA,CAAU,EAAEO,SAAA,EAAWM,OAAO;EACvC;EAIA,MAAME,QAAA,GAAWjB,qBAAA,CAAsBS,SAAS;EAChD,MAAMS,aAAA,GAAgBD,QAAA,EAAUC,aAAA,IAAiBZ,gBAAA,CAAiB;EAClE,MAAMa,YAAA,GAAelB,YAAA,CAAa;IAAEiB,aAAA;IAAeE,EAAA,EAAIX,SAAA;IAAWI;EAAO,CAAC;EAE1E,OAAOX,SAAA,CAAUe,QAAQ,EAAEE,YAAA,EAAqBJ,OAAO;AACzD","ignoreList":[]}
@@ -1,3 +1,4 @@
1
+ import { getInstanceForQueryFn } from "./instanceRegistry.native.js";
1
2
  import { resolveQuery } from "./resolveQuery.native.js";
2
3
  import { getRunner } from "./zeroRunner.native.js";
3
4
  var customQueriesRef = null;
@@ -14,21 +15,21 @@ function run(queryOrFn, paramsOrMode, modeArg) {
14
15
  var hasParams = modeArg !== void 0 || paramsOrMode && paramsOrMode !== "complete";
15
16
  var params = hasParams ? paramsOrMode : void 0;
16
17
  var mode = hasParams ? modeArg : paramsOrMode;
17
- var runner = getRunner();
18
18
  var options = mode === "complete" ? {
19
19
  type: "complete"
20
20
  } : void 0;
21
21
  if (queryOrFn && queryOrFn["ast"]) {
22
- return runner(queryOrFn, options);
22
+ return getRunner()(queryOrFn, options);
23
23
  }
24
- var customQueries = getCustomQueries();
24
+ var instance = getInstanceForQueryFn(queryOrFn);
25
+ var _instance_customQueries;
26
+ var customQueries = (_instance_customQueries = instance === null || instance === void 0 ? void 0 : instance.customQueries) !== null && _instance_customQueries !== void 0 ? _instance_customQueries : getCustomQueries();
25
27
  var queryRequest = resolveQuery({
26
28
  customQueries,
27
29
  fn: queryOrFn,
28
30
  params
29
31
  });
30
- var out = runner(queryRequest, options);
31
- return out;
32
+ return getRunner(instance)(queryRequest, options);
32
33
  }
33
34
  export { run, setCustomQueries };
34
35
  //# sourceMappingURL=run.native.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["resolveQuery","getRunner","customQueriesRef","setCustomQueries","queries","getCustomQueries","Error","run","queryOrFn","paramsOrMode","modeArg","hasParams","params","mode","runner","options","type","customQueries","queryRequest","fn","out"],"sources":["../../src/run.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,YAAA,QAAuC;AAChD,SAASC,SAAA,QAAiB;AAS1B,IAAIC,gBAAA,GAA4C;AAEzC,SAASC,iBAAiBC,OAAA,EAA2B;EAC1DF,gBAAA,GAAmBE,OAAA;AACrB;AAEA,SAASC,iBAAA,EAAqC;EAC5C,IAAI,CAACH,gBAAA,EAAkB;IACrB,MAAM,IAAII,KAAA;EAAA;EACR,OACFJ,gBAAA;AAAA;AAEF,SAAOK,IAAAC,SAAA,EAAAC,YAAA,EAAAC,OAAA;EACT,IAAAC,SAAA,GAAAD,OAAA,eAAAD,YAAA,IAAAA,YAAA;EAiCO,IAAAG,MAAS,GACdD,SACA,GAAAF,YACA,QACc;EACd,IAAAI,IAAM,GAAAF,SAAY,GAAAD,OAAY,GAAAD,YAAc;EAC5C,IAAAK,MAAM,GAAAb,SAAS;EACf,IAAAc,OAAM,GAAOF,IAAA,eAAY,GAAU;IACnCG,IAAM;EACN,SAAM;EAEC,IACCR,SAAM,IAAAA,SAAA;IACR,OACAM,MAAA,CAAAN,SAAA,EAAAO,OAAA;EAEN;EAEE,IAAAE,aAAc,GAAAZ,gBAAkB;EAClC,IAAAa,YAAA,GAAAlB,YAAA;IAEAiB,aAAM;IACNE,EAAA,EAAMX,SAAA;IAENI;EAEA;EACF,IAAAQ,GAAA,GAAAN,MAAA,CAAAI,YAAA,EAAAH,OAAA","ignoreList":[]}
1
+ {"version":3,"names":["getInstanceForQueryFn","resolveQuery","getRunner","customQueriesRef","setCustomQueries","queries","getCustomQueries","Error","run","queryOrFn","paramsOrMode","modeArg","hasParams","params","mode","options","type","instance","_instance_customQueries","customQueries","queryRequest","fn"],"sources":["../../src/run.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,qBAAA,QAA6B;AACtC,SAASC,YAAA,QAAuC;AAChD,SAASC,SAAA,QAAiB;AAS1B,IAAIC,gBAAA,GAA4C;AAEzC,SAASC,iBAAiBC,OAAA,EAA2B;EAC1DF,gBAAA,GAAmBE,OAAA;AACrB;AAEA,SAASC,iBAAA,EAAqC;EAC5C,IAAI,CAACH,gBAAA,EAAkB;IACrB,MAAM,IAAII,KAAA;EAAA;EACR,OACFJ,gBAAA;AAAA;AAEF,SAAOK,IAAAC,SAAA,EAAAC,YAAA,EAAAC,OAAA;EACT,IAAAC,SAAA,GAAAD,OAAA,eAAAD,YAAA,IAAAA,YAAA;EAiCO,IAAAG,MAAS,GACdD,SACA,GAAAF,YACA,QACc;EACd,IAAAI,IAAM,GAAAF,SAAY,GAAAD,OAAY,GAAAD,YAAc;EAC5C,IAAAK,OAAM,GAAAD,IAAS,eAAY;IAC3BE,IAAM;EACN,SAAM;EAEC,IACCP,SAAM,IAAAA,SAAA;IACR,OACAP,SAAA,GAAAO,SAAA,EAAAM,OAAA;EAEN;EAEE,IAAAE,QAAO,GAAAjB,qBAAuB,CAAAS,SAAO;EACvC,IAAAS,uBAAA;EAIA,IAAAC,aAAiB,IAAAD,uBAAsB,GAAAD,QAAS,aAAAA,QAAA,uBAAAA,QAAA,CAAAE,aAAA,cAAAD,uBAAA,cAAAA,uBAAA,GAAAZ,gBAAA;EAChD,IAAAc,YAAM,GAAAnB,YAAgB,CAAU;IAChCkB,aAAM;IAENE,EAAA,EAAAZ,SAAO;IACTI","ignoreList":[]}
@@ -3,10 +3,13 @@ let runner = null;
3
3
  function setRunner(r) {
4
4
  runner = r;
5
5
  }
6
- function getRunner() {
6
+ function getRunner(instance) {
7
7
  if (isInZeroMutation()) {
8
8
  return (q, o) => mutatorContext().tx.run(q, o);
9
9
  }
10
+ if (instance?.runner) {
11
+ return instance.runner;
12
+ }
10
13
  if (!runner) {
11
14
  throw new Error("Zero runner not initialized. Ensure ProvideZero is mounted (client) or createZeroServer is called (server).");
12
15
  }
@@ -1 +1 @@
1
- {"version":3,"names":["isInZeroMutation","mutatorContext","runner","setRunner","r","getRunner","q","o","tx","run","Error"],"sources":["../../src/zeroRunner.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,EAAkBC,cAAA,QAAsB;AAgBjD,IAAIC,MAAA,GAA4B;AAEzB,SAASC,UAAUC,CAAA,EAAe;EACvCF,MAAA,GAASE,CAAA;AACX;AAEO,SAASC,UAAA,EAAwB;EACtC,IAAIL,gBAAA,CAAiB,GAAG;IACtB,OAAO,CAACM,CAAA,EAAGC,CAAA,KAAMN,cAAA,CAAe,EAAEO,EAAA,CAAGC,GAAA,CAAIH,CAAA,EAAGC,CAAC;EAC/C;EAEA,IAAI,CAACL,MAAA,EAAQ;IACX,MAAM,IAAIQ,KAAA,CACR,6GACF;EACF;EAEA,OAAOR,MAAA;AACT","ignoreList":[]}
1
+ {"version":3,"names":["isInZeroMutation","mutatorContext","runner","setRunner","r","getRunner","instance","q","o","tx","run","Error"],"sources":["../../src/zeroRunner.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,EAAkBC,cAAA,QAAsB;AAgBjD,IAAIC,MAAA,GAA4B;AAEzB,SAASC,UAAUC,CAAA,EAAe;EACvCF,MAAA,GAASE,CAAA;AACX;AAEO,SAASC,UAAUC,QAAA,EAAsD;EAC9E,IAAIN,gBAAA,CAAiB,GAAG;IACtB,OAAO,CAACO,CAAA,EAAGC,CAAA,KAAMP,cAAA,CAAe,EAAEQ,EAAA,CAAGC,GAAA,CAAIH,CAAA,EAAGC,CAAC;EAC/C;EAIA,IAAIF,QAAA,EAAUJ,MAAA,EAAQ;IACpB,OAAOI,QAAA,CAASJ,MAAA;EAClB;EAEA,IAAI,CAACA,MAAA,EAAQ;IACX,MAAM,IAAIS,KAAA,CACR,6GACF;EACF;EAEA,OAAOT,MAAA;AACT","ignoreList":[]}
@@ -3,12 +3,15 @@ var runner = null;
3
3
  function setRunner(r) {
4
4
  runner = r;
5
5
  }
6
- function getRunner() {
6
+ function getRunner(instance) {
7
7
  if (isInZeroMutation()) {
8
8
  return function (q, o) {
9
9
  return mutatorContext().tx.run(q, o);
10
10
  };
11
11
  }
12
+ if (instance === null || instance === void 0 ? void 0 : instance.runner) {
13
+ return instance.runner;
14
+ }
12
15
  if (!runner) {
13
16
  throw new Error("Zero runner not initialized. Ensure ProvideZero is mounted (client) or createZeroServer is called (server).");
14
17
  }
@@ -1 +1 @@
1
- {"version":3,"names":["isInZeroMutation","mutatorContext","runner","setRunner","r","getRunner","q","o","tx","run","Error"],"sources":["../../src/zeroRunner.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,EAAkBC,cAAA,QAAsB;AAgBjD,IAAIC,MAAA,GAA4B;AAEzB,SAASC,UAAUC,CAAA,EAAe;EACvCF,MAAA,GAASE,CAAA;AACX;AAEO,SAASC,UAAA,EAAwB;EACtC,IAAIL,gBAAA,CAAiB,GAAG;IACtB,OAAO,UAAIM,CAAM,EAAAC,CAAA;MACnB,OAAAN,cAAA,GAAAO,EAAA,CAAAC,GAAA,CAAAH,CAAA,EAAAC,CAAA;IAEA;EACE;EAAU,IACR,CAAAL,MAAA;IACF,UAAAQ,KAAA;EACF;EAEA,OAAOR,MAAA;AACT","ignoreList":[]}
1
+ {"version":3,"names":["isInZeroMutation","mutatorContext","runner","setRunner","r","getRunner","instance","q","o","tx","run","Error"],"sources":["../../src/zeroRunner.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,EAAkBC,cAAA,QAAsB;AAgBjD,IAAIC,MAAA,GAA4B;AAEzB,SAASC,UAAUC,CAAA,EAAe;EACvCF,MAAA,GAASE,CAAA;AACX;AAEO,SAASC,UAAUC,QAAA,EAAsD;EAC9E,IAAIN,gBAAA,CAAiB,GAAG;IACtB,OAAO,UAAIO,CAAM,EAAAC,CAAA;MACnB,OAAAP,cAAA,GAAAQ,EAAA,CAAAC,GAAA,CAAAH,CAAA,EAAAC,CAAA;IAIA;EACE;EACF,IAAAF,QAAA,aAAAA,QAAA,uBAAAA,QAAA,CAAAJ,MAAA;IAEA,OAAKI,QAAQ,CAAAJ,MAAA;EACX;EAAU,IACR,CAAAA,MAAA;IACF,UAAAS,KAAA;EACF;EAEA,OAAOT,MAAA;AACT","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "on-zero",
3
- "version": "0.4.23",
3
+ "version": "0.4.25",
4
4
  "description": "A typed layer over @rocicorp/zero with queries, mutations, and permissions",
5
5
  "sideEffects": false,
6
6
  "source": "src/index.ts",
@@ -77,7 +77,7 @@
77
77
  }
78
78
  },
79
79
  "dependencies": {
80
- "@take-out/helpers": "0.4.23",
80
+ "@take-out/helpers": "0.4.25",
81
81
  "chokidar": "^4.0.3",
82
82
  "citty": "^0.1.6",
83
83
  "valibot": "^1.1.0"
@@ -105,14 +105,16 @@
105
105
  }
106
106
  },
107
107
  "devDependencies": {
108
- "drizzle-zero": "1.0.0-beta.0",
109
108
  "@tamagui/build": "2.1.0-1780964419737",
110
109
  "@types/node": "25.2.0",
111
110
  "@types/pg": "^8.11.10",
112
111
  "@types/react": "^19.0.0",
112
+ "drizzle-zero": "1.0.0-beta.0",
113
+ "jsdom": "29.1.1",
113
114
  "oxfmt": "^0.16.0",
114
115
  "oxlint": "^1.31.0",
115
116
  "react": "^19.0.0",
117
+ "react-dom": "^19.0.0",
116
118
  "react-native": "*",
117
119
  "typescript": "^5.9.3",
118
120
  "vitest": "^3.1.1"
package/readme.md CHANGED
@@ -517,6 +517,65 @@ app.post('/api/zero/pull', async (req) => {
517
517
  })
518
518
  ```
519
519
 
520
+ ### multiple client instances
521
+
522
+ one page can run several zero clients (e.g. a global control-plane instance
523
+ plus a per-project instance with its own storage key and sync url). give each
524
+ a unique `instanceName` and split queries/models so every namespace belongs to
525
+ exactly one instance — duplicate claims throw at create time. then combine
526
+ them into one consumer surface:
527
+
528
+ ```tsx
529
+ import { combineZeroClients, createZeroClient } from 'on-zero'
530
+
531
+ const control = createZeroClient({
532
+ schema,
533
+ models: controlModels,
534
+ groupedQueries: controlQueries,
535
+ instanceName: 'control',
536
+ })
537
+ const project = createZeroClient({
538
+ schema,
539
+ models: projectModels,
540
+ groupedQueries: projectQueries,
541
+ instanceName: 'project',
542
+ })
543
+
544
+ // useQuery/run/preload/getQuery dispatch by the query fn's namespace,
545
+ // zero.mutate.<namespace> dispatches by model namespace; anything unclaimed
546
+ // (and non-mutate zero access like userID) goes to the first client
547
+ export const { useQuery, zero, run, preload, getQuery, zeroEvents } =
548
+ combineZeroClients(control, project)
549
+
550
+ // render every instance's provider. NESTING ORDER IS A CONTRACT: the LAST
551
+ // client passed to combineZeroClients (or the `inner` option) must be the
552
+ // INNERMOST provider — zero-react's useQuery resolves the nearest provider's
553
+ // instance from context, so only the inner instance rides that path. all
554
+ // other instances' useQuery/usePermission go through a context-free direct
555
+ // materialize on their own mounted zero.
556
+ ;<control.ProvideZero server={controlUrl} userID={user.id}>
557
+ <project.ProvideZero server={projectUrl} userID={`${user.id}:${projectId}`}>
558
+ <App />
559
+ </project.ProvideZero>
560
+ </control.ProvideZero>
561
+ ```
562
+
563
+ constraints:
564
+
565
+ - each instance needs its own client-group identity (separate `userID` /
566
+ storage key / server url) — never swap the backing namespace under a live
567
+ instance.
568
+ - give the INNER slot to the instance owning the bulk of the subscriptions —
569
+ inner queries keep zero-react's viewStore dedup + ttl. outer instances use
570
+ the direct path, which has no cross-component view dedup (each hook
571
+ materializes its own view), so keep outer instances on bounded, tiny
572
+ queries (current user, settings, directories).
573
+ - a mutator may only read/write tables owned by its own instance. its
574
+ transaction runs on that instance alone; cross-instance writes are not
575
+ detectable at registration and will silently miss the other store.
576
+ - the server stays single: one `createZeroServer` per backend process.
577
+ - omitting `instanceName` keeps the exact single-instance behavior.
578
+
520
579
  ### server validation hooks
521
580
 
522
581
  add custom validation for all queries and mutations: