on-zero 0.6.17 → 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.
- package/dist/cjs/asyncTasks.native.js.map +1 -1
- package/dist/cjs/createZeroClient.cjs +1 -1
- package/dist/cjs/createZeroClient.connection.test.cjs +29 -0
- package/dist/cjs/createZeroClient.connection.test.native.js +29 -0
- package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -1
- package/dist/cjs/createZeroClient.native.js +1 -1
- package/dist/cjs/createZeroClient.native.js.map +1 -1
- package/dist/cjs/createZeroDirectServer.cjs +1 -1
- package/dist/cjs/createZeroDirectServer.native.js +1 -1
- package/dist/cjs/createZeroDirectServer.native.js.map +1 -1
- package/dist/cjs/createZeroServer.test.cjs +6 -0
- package/dist/cjs/createZeroServer.test.native.js +6 -0
- package/dist/cjs/createZeroServer.test.native.js.map +1 -1
- package/dist/cjs/createZeroServerCore.cjs +29 -1
- package/dist/cjs/createZeroServerCore.native.js +153 -1
- package/dist/cjs/createZeroServerCore.native.js.map +1 -1
- package/dist/cjs/httpPull/transport.test.cjs +127 -15
- package/dist/cjs/httpPull/transport.test.native.js +161 -16
- package/dist/cjs/httpPull/transport.test.native.js.map +1 -1
- package/dist/cjs/httpPullTransport.cjs +48 -18
- package/dist/cjs/httpPullTransport.native.js +57 -20
- package/dist/cjs/httpPullTransport.native.js.map +1 -1
- package/dist/cjs/modelRegistry.cjs +7 -4
- package/dist/cjs/modelRegistry.native.js +8 -4
- package/dist/cjs/modelRegistry.native.js.map +1 -1
- package/dist/cjs/mutations.cjs +15 -11
- package/dist/cjs/mutations.native.js +17 -11
- package/dist/cjs/mutations.native.js.map +1 -1
- package/dist/cjs/state.cjs +2 -3
- package/dist/cjs/state.native.js +2 -3
- package/dist/cjs/state.native.js.map +1 -1
- package/dist/cjs/syncHost.cjs +2 -1
- package/dist/cjs/syncHost.native.js +2 -1
- package/dist/cjs/syncHost.native.js.map +1 -1
- package/dist/cjs/usePermission.test.cjs +4 -2
- package/dist/cjs/usePermission.test.native.js +4 -2
- package/dist/cjs/usePermission.test.native.js.map +1 -1
- package/dist/esm/asyncTasks.mjs.map +1 -1
- package/dist/esm/asyncTasks.native.js.map +1 -1
- package/dist/esm/createZeroClient.connection.test.mjs +29 -0
- package/dist/esm/createZeroClient.connection.test.mjs.map +1 -1
- package/dist/esm/createZeroClient.connection.test.native.js +29 -0
- package/dist/esm/createZeroClient.connection.test.native.js.map +1 -1
- package/dist/esm/createZeroClient.mjs +2 -2
- package/dist/esm/createZeroClient.mjs.map +1 -1
- package/dist/esm/createZeroClient.native.js +2 -2
- package/dist/esm/createZeroClient.native.js.map +1 -1
- package/dist/esm/createZeroDirectServer.mjs +2 -2
- package/dist/esm/createZeroDirectServer.mjs.map +1 -1
- package/dist/esm/createZeroDirectServer.native.js +2 -2
- package/dist/esm/createZeroDirectServer.native.js.map +1 -1
- package/dist/esm/createZeroServer.test.mjs +6 -0
- package/dist/esm/createZeroServer.test.mjs.map +1 -1
- package/dist/esm/createZeroServer.test.native.js +6 -0
- package/dist/esm/createZeroServer.test.native.js.map +1 -1
- package/dist/esm/createZeroServerCore.mjs +29 -1
- package/dist/esm/createZeroServerCore.mjs.map +1 -1
- package/dist/esm/createZeroServerCore.native.js +153 -1
- package/dist/esm/createZeroServerCore.native.js.map +1 -1
- package/dist/esm/httpPull/transport.test.mjs +127 -15
- package/dist/esm/httpPull/transport.test.mjs.map +1 -1
- package/dist/esm/httpPull/transport.test.native.js +161 -16
- package/dist/esm/httpPull/transport.test.native.js.map +1 -1
- package/dist/esm/httpPullTransport.mjs +48 -18
- package/dist/esm/httpPullTransport.mjs.map +1 -1
- package/dist/esm/httpPullTransport.native.js +57 -20
- package/dist/esm/httpPullTransport.native.js.map +1 -1
- package/dist/esm/modelRegistry.mjs +7 -4
- package/dist/esm/modelRegistry.mjs.map +1 -1
- package/dist/esm/modelRegistry.native.js +8 -4
- package/dist/esm/modelRegistry.native.js.map +1 -1
- package/dist/esm/mutations.mjs +15 -11
- package/dist/esm/mutations.mjs.map +1 -1
- package/dist/esm/mutations.native.js +17 -11
- package/dist/esm/mutations.native.js.map +1 -1
- package/dist/esm/state.mjs +2 -3
- package/dist/esm/state.mjs.map +1 -1
- package/dist/esm/state.native.js +2 -3
- package/dist/esm/state.native.js.map +1 -1
- package/dist/esm/syncHost.mjs +2 -1
- package/dist/esm/syncHost.mjs.map +1 -1
- package/dist/esm/syncHost.native.js +2 -1
- package/dist/esm/syncHost.native.js.map +1 -1
- package/dist/esm/usePermission.test.mjs +6 -4
- package/dist/esm/usePermission.test.mjs.map +1 -1
- package/dist/esm/usePermission.test.native.js +6 -4
- package/dist/esm/usePermission.test.native.js.map +1 -1
- package/package.json +2 -2
- package/src/asyncTasks.ts +4 -1
- package/src/createZeroClient.connection.test.tsx +32 -0
- package/src/createZeroClient.tsx +7 -2
- package/src/createZeroDirectServer.ts +2 -2
- package/src/createZeroServer.test.ts +10 -0
- package/src/createZeroServerCore.ts +38 -1
- package/src/httpPull/transport.test.ts +143 -16
- package/src/httpPullTransport.ts +67 -30
- package/src/modelRegistry.ts +9 -4
- package/src/mutations.ts +19 -15
- package/src/state.ts +3 -3
- package/src/syncHost.ts +2 -2
- package/src/usePermission.test.ts +9 -3
- package/test-fixtures/server-return-types.ts +13 -1
- package/types/asyncTasks.d.ts +5 -1
- package/types/asyncTasks.d.ts.map +1 -1
- package/types/createZeroClient.d.ts.map +1 -1
- package/types/createZeroServerCore.d.ts.map +1 -1
- package/types/httpPullTransport.d.ts +13 -0
- package/types/httpPullTransport.d.ts.map +1 -1
- package/types/modelRegistry.d.ts.map +1 -1
- package/types/mutations.d.ts.map +1 -1
- package/types/state.d.ts +2 -2
- package/types/state.d.ts.map +1 -1
- package/types/syncHost.d.ts +1 -1
- package/types/syncHost.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["asQueryInternals","createPermissions","createZeroDirectServer","resolveServerQuery","createSQLiteDatabase","createZeroSQLiteTransaction","defaultLedgerTables","encodeSQLiteValue","createMutators","runWithAuthScope","runWithQueryContext","setEnvironment","setSchema","_assert_this_initialized","self","ReferenceError","_call_super","_this","derived","args","_get_prototype_of","_possible_constructor_return","_is_native_reflect_construct","Reflect","construct","constructor","apply","_class_call_check","instance","Constructor","TypeError","_construct","Parent","Class","Parent2","args2","Class2","a","push","Function","bind","_set_prototype_of","prototype","arguments","_define_property","obj","key","value","Object","defineProperty","enumerable","configurable","writable","o","setPrototypeOf","getPrototypeOf","o2","__proto__","_inherits","subClass","superClass","create","_instanceof","left","right","Symbol","hasInstance","_is_native_function","fn","toString","call","indexOf","_type_of","p","p2","_wrap_native_super","_cache","Map","wrapNativeSuper","has","get","set","Wrapper","result","Boolean","valueOf","_","MutationApplicationError","Error1","MutationApplicationError2","details","message","length","name","Error","createZeroSyncHostAdapter","param","encodeValue","mapAuthData","defaultMapAuthData","transaction","options","schema","_options_defaultAllowAdminRole","permissions","environment","adminRoleMode","defaultAllowAdminRole","transactionOptions","mutators","_iteratorNormalCompletion","_didIteratorError","_iteratorError"],"sources":["../../src/syncHost.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,QAAwB;
|
|
1
|
+
{"version":3,"names":["asQueryInternals","createBuilder","createPermissions","createZeroDirectServer","resolveServerQuery","createSQLiteDatabase","createZeroSQLiteTransaction","defaultLedgerTables","encodeSQLiteValue","createMutators","runWithAuthScope","runWithQueryContext","setEnvironment","setSchema","_assert_this_initialized","self","ReferenceError","_call_super","_this","derived","args","_get_prototype_of","_possible_constructor_return","_is_native_reflect_construct","Reflect","construct","constructor","apply","_class_call_check","instance","Constructor","TypeError","_construct","Parent","Class","Parent2","args2","Class2","a","push","Function","bind","_set_prototype_of","prototype","arguments","_define_property","obj","key","value","Object","defineProperty","enumerable","configurable","writable","o","setPrototypeOf","getPrototypeOf","o2","__proto__","_inherits","subClass","superClass","create","_instanceof","left","right","Symbol","hasInstance","_is_native_function","fn","toString","call","indexOf","_type_of","p","p2","_wrap_native_super","_cache","Map","wrapNativeSuper","has","get","set","Wrapper","result","Boolean","valueOf","_","MutationApplicationError","Error1","MutationApplicationError2","details","message","length","name","Error","createZeroSyncHostAdapter","param","encodeValue","mapAuthData","defaultMapAuthData","transaction","options","schema","_options_defaultAllowAdminRole","permissions","environment","adminRoleMode","defaultAllowAdminRole","transactionOptions","mutators","_iteratorNormalCompletion","_didIteratorError","_iteratorError"],"sources":["../../src/syncHost.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
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
|
-
import { getMutationsPermissions, setMutationsPermissions } from "./modelRegistry.mjs";
|
|
3
|
+
import { getAllMutationsPermissions, getMutationsPermissions, setMutationsPermissions } from "./modelRegistry.mjs";
|
|
4
4
|
import { registerQuery, getQueryName } from "./queryRegistry.mjs";
|
|
5
5
|
import { setEnvironment, setSchema } from "./state.mjs";
|
|
6
6
|
describe("usePermission _uid query identity", () => {
|
|
@@ -10,12 +10,13 @@ describe("usePermission _uid query identity", () => {
|
|
|
10
10
|
ownerId: string(),
|
|
11
11
|
active: boolean()
|
|
12
12
|
}).primaryKey("id");
|
|
13
|
-
|
|
13
|
+
const schema = {
|
|
14
14
|
tables: {
|
|
15
15
|
testEntity: testTable
|
|
16
16
|
},
|
|
17
17
|
version: 1
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
|
+
setSchema(schema, createBuilder(schema));
|
|
19
20
|
setEnvironment("client");
|
|
20
21
|
const fn = args => {
|
|
21
22
|
return {
|
|
@@ -71,6 +72,7 @@ describe("usePermission _uid query identity", () => {
|
|
|
71
72
|
const perm = getMutationsPermissions("testEntity");
|
|
72
73
|
expect(perm).toBeDefined();
|
|
73
74
|
expect(perm).toBe(mockWhere);
|
|
75
|
+
expect(getAllMutationsPermissions().get("testEntity")).toBe(mockWhere);
|
|
74
76
|
});
|
|
75
77
|
test("query name registration preserves permission namespace", () => {
|
|
76
78
|
const fn = () => {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["boolean","string","table","describe","expect","test","getMutationsPermissions","setMutationsPermissions","registerQuery","getQueryName","setEnvironment","setSchema","testTable","columns","id","ownerId","active","primaryKey","tables","testEntity","version","fn","args","objOrId","result1","_uid","result2","result3","toBe","args1","JSON","stringify","args2","args3","not","mockWhere","eb","auth","cmp","perm","toBeDefined","original","activeProjects","hotReloaded","first","byId","second","toBeUndefined"],"sources":["../../src/usePermission.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAA,EAASC,MAAA,EAAQC,KAAA,QAAa;
|
|
1
|
+
{"version":3,"names":["boolean","createBuilder","string","table","describe","expect","test","getAllMutationsPermissions","getMutationsPermissions","setMutationsPermissions","registerQuery","getQueryName","setEnvironment","setSchema","testTable","columns","id","ownerId","active","primaryKey","schema","tables","testEntity","version","fn","args","objOrId","result1","_uid","result2","result3","toBe","args1","JSON","stringify","args2","args3","not","mockWhere","eb","auth","cmp","perm","toBeDefined","get","original","activeProjects","hotReloaded","first","byId","second","toBeUndefined"],"sources":["../../src/usePermission.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
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
|
-
import { getMutationsPermissions, setMutationsPermissions } from "./modelRegistry.native.js";
|
|
3
|
+
import { getAllMutationsPermissions, getMutationsPermissions, setMutationsPermissions } from "./modelRegistry.native.js";
|
|
4
4
|
import { registerQuery, getQueryName } from "./queryRegistry.native.js";
|
|
5
5
|
import { setEnvironment, setSchema } from "./state.native.js";
|
|
6
6
|
describe("usePermission _uid query identity", function () {
|
|
@@ -10,12 +10,13 @@ describe("usePermission _uid query identity", function () {
|
|
|
10
10
|
ownerId: string(),
|
|
11
11
|
active: boolean()
|
|
12
12
|
}).primaryKey("id");
|
|
13
|
-
|
|
13
|
+
var schema = {
|
|
14
14
|
tables: {
|
|
15
15
|
testEntity: testTable
|
|
16
16
|
},
|
|
17
17
|
version: 1
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
|
+
setSchema(schema, createBuilder(schema));
|
|
19
20
|
setEnvironment("client");
|
|
20
21
|
var fn = function (args) {
|
|
21
22
|
return {
|
|
@@ -73,6 +74,7 @@ describe("usePermission _uid query identity", function () {
|
|
|
73
74
|
var perm = getMutationsPermissions("testEntity");
|
|
74
75
|
expect(perm).toBeDefined();
|
|
75
76
|
expect(perm).toBe(mockWhere);
|
|
77
|
+
expect(getAllMutationsPermissions().get("testEntity")).toBe(mockWhere);
|
|
76
78
|
});
|
|
77
79
|
test("query name registration preserves permission namespace", function () {
|
|
78
80
|
var fn = function () {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["boolean","string","table","describe","expect","test","getMutationsPermissions","setMutationsPermissions","registerQuery","getQueryName","setEnvironment","setSchema","testTable","columns","id","ownerId","active","primaryKey","tables","testEntity","version","fn","args","objOrId","result1","_uid","result2","result3","toBe","args1","JSON","stringify","args2","args3","not","mockWhere","eb","auth","cmp"],"sources":["../../src/usePermission.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAA,EAASC,MAAA,EAAQC,KAAA,QAAa;
|
|
1
|
+
{"version":3,"names":["boolean","createBuilder","string","table","describe","expect","test","getAllMutationsPermissions","getMutationsPermissions","setMutationsPermissions","registerQuery","getQueryName","setEnvironment","setSchema","testTable","columns","id","ownerId","active","primaryKey","schema","tables","testEntity","version","fn","args","objOrId","result1","_uid","result2","result3","toBe","args1","JSON","stringify","args2","args3","not","mockWhere","eb","auth","cmp","perm","toBeDefined"],"sources":["../../src/usePermission.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAA,EAASC,aAAA,EAAeC,MAAA,EAAQC,KAAA,QAAa;AACtD,SAASC,QAAA,EAAUC,MAAA,EAAQC,IAAA,QAAY;AAEvC,SAAAC,0BAAA,EAAAC,uBAAA,EAAAC,uBAAA;AAAA,SACEC,aAAA,EAAAC,YAAA;AAAA,SACAC,cAAA,EAAAC,SAAA;AAAAT,QACA;EAAAE,IAAA,CACK;IACP,IAAAQ,SAAS,GAAAX,KAAe,eAAAY,OAAoB;MAC5CC,EAAA,EAASd,MAAA;MAETe,OAAS,EAAAf,MAAA;MAUPgB,MAAK,EAAAlB,OAAA;IAEH,GAAAmB,UAAM,KAAY;IACP,IACPC,MAAI,GAAO;MACXC,MAAA;QACAC,UAAQ,EAAAR;MACT,CACA;MAEHS,OAAM;IACN;IACAV,SAAA,CAAAO,MAAe,EAAAnB,aAAQ,CAAAmB,MAAA;IAIvBR,cAAY,SAAmE;IAE7E,IAAAY,EAAA,GAAO,SAAAA,CAAEC,IAAS;MACpB;QAEAC,OAAM,EAAAD,IAAU,CAAAC;MAChB;IACA;IAGA,IAAAC,OAAO,GAAAH,EAAQ;MACfE,OAAO,WAAQ;MACfE,IAAA,EAAO;IACR;IAED,IAAKC,OAAA,GAAAL,EAAA;MAGHE,OAAM,WAAa;MACnBE,IAAM;IACN;IAEA,IAAAE,OAAO,GAAON,EAAA;MACdE,OAAO;IACP;IACDrB,MAAA,CAAAsB,OAAA,CAAAD,OAAA,EAAAK,IAAA;IAED1B,MAAK,CAAAwB,OAAA,CAAAH,OAAA,EAAAK,IAAA;IAEH1B,MAAM,CAAAyB,OAAQ,CAAAJ,OAAK,EAAAK,IAAA,CAAU,SAAE;EAC/B;EAEAzB,IAAA,0DAAwB;IACzB,IAAA0B,KAAA,GAAAC,IAAA,CAAAC,SAAA;MAEDR,OAAK;MAEHE,IAAM;IACN;IAEA,IAAAO,KAAM,GAAAF,IAAO,CAAAC,SAAA;MACbR,OAAO,EAAI,UAAE;MACbE,IAAA,EAAO;IACP;IACD,IAAAQ,KAAA,GAAAH,IAAA,CAAAC,SAAA;MAEDR,OAAK;MACHE,IAAM;IAAY;IAClBvB,MAAA,CAAA2B,KAAA,EAAcK,GAAA,CAAIN,IAAA,CAAAI,KAAA;IAElB9B,MAAA,CAAO2B,KAAA,EAAAK,GAAA,CAAAN,IAAe,CAACK,KAAE;IAC1B/B,MAAA,CAAA8B,KAAA,EAAAE,GAAA,CAAAN,IAAA,CAAAK,KAAA;EAED;EACE9B,IAAA,2CAA2C;IAAC,IAAA0B,KAAA,GAAAC,IAAA,CAAAC,SAAA;MAC5CR,OAAM,YAAc;MAA2BE,IAAA;IAE/C;IAEA,IAAAO,KAAO,GAAAF,IAAA,CAAAC,SAAa;MACrBR,OAAA;MAEDE,IAAK;IACH;IAA+BvB,MAAA,CAAA2B,KAAA,EAAAD,IAAA,CAAAI,KAAA;EAC/B;EAA+B7B,IAAC;IAChC,IAAAgC,SAAM,YAAAA,CAAcC,EAAA,EAASC,IAAA;MAAQ,OAAAD,EAAA,CAAAE,GAAA,aAAAD,IAAA,aAAAA,IAAA,uBAAAA,IAAA,CAAAxB,EAAA;IAErC;IACAP,uBAAsB,aAAW,EAAA6B,SAAA;IAEjC,IAAAI,IAAO,GAAAlC,uBAA2B,cAAc;IACjDH,MAAA,CAAAqC,IAAA,EAAAC,WAAA;IACFtC,MAAA,CAAAqC,IAAA,EAAAX,IAAA,CAAAO,SAAA","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "on-zero",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.19",
|
|
4
4
|
"description": "A typed layer over @rocicorp/zero with queries, mutations, and permissions",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
}
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"@take-out/helpers": "0.6.
|
|
102
|
+
"@take-out/helpers": "0.6.19",
|
|
103
103
|
"chokidar": "^4.0.3",
|
|
104
104
|
"citty": "^0.1.6",
|
|
105
105
|
"valibot": "^1.1.0"
|
package/src/asyncTasks.ts
CHANGED
|
@@ -160,3 +160,35 @@ test('connectionDataset mirrors connection state onto the body dataset', async (
|
|
|
160
160
|
expect(document.body.dataset.zeroConnected).toBeUndefined()
|
|
161
161
|
expect(document.body.dataset.zeroReason).toBe('boom')
|
|
162
162
|
})
|
|
163
|
+
|
|
164
|
+
test('fatal error state stays terminal and reports the reason', async () => {
|
|
165
|
+
vi.useFakeTimers()
|
|
166
|
+
try {
|
|
167
|
+
const instance = await mount({}, 'conn-fatal')
|
|
168
|
+
const events: Array<{ type: string; message?: string }> = []
|
|
169
|
+
const off = client.zeroEvents.listen((event) => {
|
|
170
|
+
if (event) events.push(event)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
await act(async () => {
|
|
174
|
+
instance.connection.state.set({
|
|
175
|
+
name: 'error',
|
|
176
|
+
reason: 'Got open event but connect start time is undefined',
|
|
177
|
+
})
|
|
178
|
+
await Promise.resolve()
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
await act(async () => {
|
|
182
|
+
vi.advanceTimersByTime(60_000)
|
|
183
|
+
await Promise.resolve()
|
|
184
|
+
})
|
|
185
|
+
expect(instance.connection.connect).not.toHaveBeenCalled()
|
|
186
|
+
expect(events).toContainEqual({
|
|
187
|
+
type: 'error',
|
|
188
|
+
message: 'Got open event but connect start time is undefined',
|
|
189
|
+
})
|
|
190
|
+
off()
|
|
191
|
+
} finally {
|
|
192
|
+
vi.useRealTimers()
|
|
193
|
+
}
|
|
194
|
+
})
|
package/src/createZeroClient.tsx
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createBuilder,
|
|
3
|
+
defineQueries,
|
|
4
|
+
defineQuery,
|
|
5
|
+
Zero as ZeroClient,
|
|
6
|
+
} from '@rocicorp/zero'
|
|
2
7
|
import {
|
|
3
8
|
useConnectionState,
|
|
4
9
|
useZero,
|
|
@@ -136,7 +141,7 @@ export function createZeroClientInternal<
|
|
|
136
141
|
type ZeroInstance = Zero<Schema, ZeroMutators>
|
|
137
142
|
type TableName = keyof Schema['tables'] & string
|
|
138
143
|
|
|
139
|
-
setSchema(schema)
|
|
144
|
+
setSchema(schema, createBuilder(schema))
|
|
140
145
|
|
|
141
146
|
// only set environment to 'client' if server hasn't already claimed it
|
|
142
147
|
// (during SSR, createZeroServer runs first and sets 'server')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mustGetQuery } from '@rocicorp/zero'
|
|
1
|
+
import { createBuilder, mustGetQuery } from '@rocicorp/zero'
|
|
2
2
|
|
|
3
3
|
import { runAsyncTaskEntries } from './asyncTasks'
|
|
4
4
|
import { createPermissions } from './createPermissions'
|
|
@@ -229,7 +229,7 @@ export function createZeroDirectServerRuntime<
|
|
|
229
229
|
permissions: ReturnType<typeof createPermissions<Schema>>
|
|
230
230
|
server: ZeroDirectServer<Schema, Models>
|
|
231
231
|
} {
|
|
232
|
-
setSchema(schema)
|
|
232
|
+
setSchema(schema, createBuilder(schema))
|
|
233
233
|
setEnvironment('server')
|
|
234
234
|
|
|
235
235
|
const permissions = createPermissions<Schema>({
|
|
@@ -97,6 +97,7 @@ describe('createZeroServer mutation recovery', () => {
|
|
|
97
97
|
test('discards async tasks from a rolled-back PostgreSQL mutation', async () => {
|
|
98
98
|
const pg = new FakePgClient()
|
|
99
99
|
let effectRuns = 0
|
|
100
|
+
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
100
101
|
const zeroServer = createZeroServer({
|
|
101
102
|
schema: zeroHttpFixtureSchema,
|
|
102
103
|
models: {
|
|
@@ -127,6 +128,12 @@ describe('createZeroServer mutation recovery', () => {
|
|
|
127
128
|
})
|
|
128
129
|
expect(result.asyncTasks).toEqual([])
|
|
129
130
|
expect(effectRuns).toBe(0)
|
|
131
|
+
expect(consoleWarn).toHaveBeenCalledWith(
|
|
132
|
+
'PushProcessor',
|
|
133
|
+
expect.stringContaining('Error processing mutation'),
|
|
134
|
+
expect.stringContaining('rejected'),
|
|
135
|
+
)
|
|
136
|
+
consoleWarn.mockRestore()
|
|
130
137
|
})
|
|
131
138
|
|
|
132
139
|
test('awaits barrier tasks before resolving the push response', async () => {
|
|
@@ -321,6 +328,7 @@ describe('createZeroServer mutation recovery', () => {
|
|
|
321
328
|
|
|
322
329
|
test('persists alreadyProcessed duplicate results for zero-cache recovery rows', async () => {
|
|
323
330
|
const pg = new FakePgClient()
|
|
331
|
+
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
324
332
|
const zeroServer = createZeroServer({
|
|
325
333
|
schema: zeroHttpFixtureSchema,
|
|
326
334
|
models: {
|
|
@@ -362,6 +370,8 @@ describe('createZeroServer mutation recovery', () => {
|
|
|
362
370
|
}),
|
|
363
371
|
],
|
|
364
372
|
])
|
|
373
|
+
expect(consoleWarn).not.toHaveBeenCalled()
|
|
374
|
+
consoleWarn.mockRestore()
|
|
365
375
|
})
|
|
366
376
|
|
|
367
377
|
test('persists only alreadyProcessed results in a mixed recovery push', async () => {
|
|
@@ -190,7 +190,20 @@ function withTransactionLifecycle(
|
|
|
190
190
|
const value = await database.transaction(async (tx, hooks) => {
|
|
191
191
|
lifecycle.beginAttempt()
|
|
192
192
|
try {
|
|
193
|
-
const result = await callback(tx,
|
|
193
|
+
const result = await callback(tx, {
|
|
194
|
+
...hooks,
|
|
195
|
+
async updateClientMutationID() {
|
|
196
|
+
const result = await hooks.updateClientMutationID()
|
|
197
|
+
if (input && input.mutationID < result.lastMutationID) {
|
|
198
|
+
throw new ExpectedDuplicateMutation(
|
|
199
|
+
input.clientID,
|
|
200
|
+
input.mutationID,
|
|
201
|
+
result.lastMutationID,
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
return result
|
|
205
|
+
},
|
|
206
|
+
})
|
|
194
207
|
lifecycle.completeAttempt()
|
|
195
208
|
return result
|
|
196
209
|
} catch (error) {
|
|
@@ -202,12 +215,36 @@ function withTransactionLifecycle(
|
|
|
202
215
|
return value
|
|
203
216
|
} catch (error) {
|
|
204
217
|
lifecycle.rollbackTransaction()
|
|
218
|
+
if (error instanceof ExpectedDuplicateMutation) {
|
|
219
|
+
return {
|
|
220
|
+
id: {
|
|
221
|
+
clientID: error.clientID,
|
|
222
|
+
id: error.mutationID,
|
|
223
|
+
},
|
|
224
|
+
result: {
|
|
225
|
+
error: 'alreadyProcessed',
|
|
226
|
+
details: error.message,
|
|
227
|
+
},
|
|
228
|
+
} as never
|
|
229
|
+
}
|
|
205
230
|
throw error
|
|
206
231
|
}
|
|
207
232
|
},
|
|
208
233
|
}
|
|
209
234
|
}
|
|
210
235
|
|
|
236
|
+
class ExpectedDuplicateMutation extends Error {
|
|
237
|
+
constructor(
|
|
238
|
+
readonly clientID: string,
|
|
239
|
+
readonly mutationID: number,
|
|
240
|
+
expectedMutationID: number | bigint,
|
|
241
|
+
) {
|
|
242
|
+
super(
|
|
243
|
+
`Ignoring mutation from ${clientID} with ID ${mutationID} as it was already processed. Expected: ${expectedMutationID}`,
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
211
248
|
async function parseAlreadyProcessed(
|
|
212
249
|
request: Request,
|
|
213
250
|
response: unknown,
|
|
@@ -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 {
|
|
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('
|
|
433
|
-
const
|
|
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
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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(
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
await eventually(
|
|
447
|
-
|
|
448
|
-
|
|
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: {
|
|
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,
|