orez 0.4.10 → 0.4.12

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.
@@ -0,0 +1,111 @@
1
+ import type { Transaction } from '@rocicorp/zero';
2
+ export declare const zeroHttpFixtureSchema: {
3
+ tables: {
4
+ readonly user: {
5
+ name: "user";
6
+ columns: {
7
+ readonly id: {
8
+ type: "string";
9
+ optional: false;
10
+ customType: string;
11
+ };
12
+ readonly name: {
13
+ type: "string";
14
+ optional: false;
15
+ customType: string;
16
+ };
17
+ };
18
+ primaryKey: readonly [string, ...string[]];
19
+ } & {
20
+ primaryKey: ["id"];
21
+ };
22
+ readonly project: {
23
+ name: "project";
24
+ columns: {
25
+ readonly id: {
26
+ type: "string";
27
+ optional: false;
28
+ customType: string;
29
+ };
30
+ readonly ownerId: {
31
+ type: "string";
32
+ optional: false;
33
+ customType: string;
34
+ };
35
+ readonly name: {
36
+ type: "string";
37
+ optional: false;
38
+ customType: string;
39
+ };
40
+ };
41
+ primaryKey: readonly [string, ...string[]];
42
+ } & {
43
+ primaryKey: ["id"];
44
+ };
45
+ readonly member: {
46
+ name: "member";
47
+ columns: {
48
+ readonly id: {
49
+ type: "string";
50
+ optional: false;
51
+ customType: string;
52
+ };
53
+ readonly projectId: {
54
+ type: "string";
55
+ optional: false;
56
+ customType: string;
57
+ };
58
+ readonly userId: {
59
+ type: "string";
60
+ optional: false;
61
+ customType: string;
62
+ };
63
+ };
64
+ primaryKey: readonly [string, ...string[]];
65
+ } & {
66
+ primaryKey: ["id"];
67
+ };
68
+ };
69
+ relationships: {
70
+ readonly project: {
71
+ members: [{
72
+ readonly sourceField: readonly ("id" | "name" | "ownerId")[];
73
+ readonly destField: readonly ("id" | "projectId" | "userId")[];
74
+ readonly destSchema: "member";
75
+ readonly cardinality: "many";
76
+ }];
77
+ };
78
+ };
79
+ enableLegacyQueries: true;
80
+ enableLegacyMutators: boolean | undefined;
81
+ };
82
+ type FixtureTransaction = Transaction<typeof zeroHttpFixtureSchema>;
83
+ export type ProjectCreateArgs = {
84
+ id: string;
85
+ ownerId: string;
86
+ name: string;
87
+ };
88
+ export type ProjectRenameArgs = {
89
+ id: string;
90
+ name: string;
91
+ };
92
+ export type MemberAddArgs = {
93
+ id: string;
94
+ projectId: string;
95
+ userId: string;
96
+ };
97
+ export type MemberRemoveArgs = {
98
+ id: string;
99
+ };
100
+ export declare const zeroHttpFixtureMutators: {
101
+ project: {
102
+ create: (tx: FixtureTransaction, args: ProjectCreateArgs) => Promise<void>;
103
+ rename: (tx: FixtureTransaction, args: ProjectRenameArgs) => Promise<void>;
104
+ };
105
+ member: {
106
+ add: (tx: FixtureTransaction, args: MemberAddArgs) => Promise<void>;
107
+ remove: (tx: FixtureTransaction, args: MemberRemoveArgs) => Promise<void>;
108
+ };
109
+ };
110
+ export {};
111
+ //# sourceMappingURL=fixture-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture-schema.d.ts","sourceRoot":"","sources":["../../src/zero-http/fixture-schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAyBjD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYhC,CAAA;AAEF,KAAK,kBAAkB,GAAG,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,eAAO,MAAM,uBAAuB;;qBAEb,kBAAkB,QAAQ,iBAAiB;qBAG3C,kBAAkB,QAAQ,iBAAiB;;;kBAK9C,kBAAkB,QAAQ,aAAa;qBAGpC,kBAAkB,QAAQ,gBAAgB;;CAIhE,CAAA"}
@@ -0,0 +1,53 @@
1
+ import { createSchema, relationships, string, table } from '@rocicorp/zero';
2
+ const user = table('user')
3
+ .columns({
4
+ id: string(),
5
+ name: string(),
6
+ })
7
+ .primaryKey('id');
8
+ const project = table('project')
9
+ .columns({
10
+ id: string(),
11
+ ownerId: string(),
12
+ name: string(),
13
+ })
14
+ .primaryKey('id');
15
+ const member = table('member')
16
+ .columns({
17
+ id: string(),
18
+ projectId: string(),
19
+ userId: string(),
20
+ })
21
+ .primaryKey('id');
22
+ export const zeroHttpFixtureSchema = createSchema({
23
+ tables: [user, project, member],
24
+ relationships: [
25
+ relationships(project, ({ many }) => ({
26
+ members: many({
27
+ sourceField: ['id'],
28
+ destField: ['projectId'],
29
+ destSchema: member,
30
+ }),
31
+ })),
32
+ ],
33
+ enableLegacyQueries: true,
34
+ });
35
+ export const zeroHttpFixtureMutators = {
36
+ project: {
37
+ create: async (tx, args) => {
38
+ await tx.mutate.project.insert(args);
39
+ },
40
+ rename: async (tx, args) => {
41
+ await tx.mutate.project.update(args);
42
+ },
43
+ },
44
+ member: {
45
+ add: async (tx, args) => {
46
+ await tx.mutate.member.insert(args);
47
+ },
48
+ remove: async (tx, args) => {
49
+ await tx.mutate.member.delete({ id: args.id });
50
+ },
51
+ },
52
+ };
53
+ //# sourceMappingURL=fixture-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture-schema.js","sourceRoot":"","sources":["../../src/zero-http/fixture-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAI3E,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;KACvB,OAAO,CAAC;IACP,EAAE,EAAE,MAAM,EAAE;IACZ,IAAI,EAAE,MAAM,EAAE;CACf,CAAC;KACD,UAAU,CAAC,IAAI,CAAC,CAAA;AAEnB,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC;KAC7B,OAAO,CAAC;IACP,EAAE,EAAE,MAAM,EAAE;IACZ,OAAO,EAAE,MAAM,EAAE;IACjB,IAAI,EAAE,MAAM,EAAE;CACf,CAAC;KACD,UAAU,CAAC,IAAI,CAAC,CAAA;AAEnB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;KAC3B,OAAO,CAAC;IACP,EAAE,EAAE,MAAM,EAAE;IACZ,SAAS,EAAE,MAAM,EAAE;IACnB,MAAM,EAAE,MAAM,EAAE;CACjB,CAAC;KACD,UAAU,CAAC,IAAI,CAAC,CAAA;AAEnB,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC;IAChD,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE;QACb,aAAa,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACpC,OAAO,EAAE,IAAI,CAAC;gBACZ,WAAW,EAAE,CAAC,IAAI,CAAC;gBACnB,SAAS,EAAE,CAAC,WAAW,CAAC;gBACxB,UAAU,EAAE,MAAM;aACnB,CAAC;SACH,CAAC,CAAC;KACJ;IACD,mBAAmB,EAAE,IAAI;CAC1B,CAAC,CAAA;AAyBF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO,EAAE;QACP,MAAM,EAAE,KAAK,EAAE,EAAsB,EAAE,IAAuB,EAAE,EAAE;YAChE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACtC,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,EAAsB,EAAE,IAAuB,EAAE,EAAE;YAChE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACtC,CAAC;KACF;IACD,MAAM,EAAE;QACN,GAAG,EAAE,KAAK,EAAE,EAAsB,EAAE,IAAmB,EAAE,EAAE;YACzD,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACrC,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,EAAsB,EAAE,IAAsB,EAAE,EAAE;YAC/D,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;QAChD,CAAC;KACF;CACF,CAAA"}
@@ -0,0 +1,14 @@
1
+ export type Row = Record<string, string>;
2
+ export declare function startZeroHttpServer(opts?: {
3
+ seed?: {
4
+ user?: Row[];
5
+ project?: Row[];
6
+ member?: Row[];
7
+ };
8
+ }): Promise<{
9
+ url: string;
10
+ version(): number;
11
+ rows(table: string): Row[];
12
+ close(): Promise<void>;
13
+ }>;
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/zero-http/server.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AA6BxC,wBAAsB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAC/C,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;CACzD,GAAG,OAAO,CAAC;IACV,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,IAAI,MAAM,CAAA;IACjB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAAA;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAC,CA8HD"}
@@ -0,0 +1,284 @@
1
+ import { createServer } from 'node:http';
2
+ const tableNames = ['user', 'project', 'member'];
3
+ export async function startZeroHttpServer(opts) {
4
+ const tables = seedTables(opts?.seed);
5
+ const lmids = new Map();
6
+ const mutationResults = new Map();
7
+ const clientGroupUsers = new Map();
8
+ let cookie = 1;
9
+ const server = createServer(async (req, res) => {
10
+ try {
11
+ if (req.method !== 'POST') {
12
+ sendJSON(res, 404, { error: 'not found' });
13
+ return;
14
+ }
15
+ const path = new URL(req.url || '/', 'http://127.0.0.1').pathname;
16
+ const userID = authenticate(req, tables);
17
+ if (!userID) {
18
+ sendJSON(res, 401, { error: 'unauthorized' });
19
+ return;
20
+ }
21
+ if (path === '/pull') {
22
+ const body = (await readJSON(req));
23
+ if (!bindClientGroup(clientGroupUsers, body.clientGroupID, userID)) {
24
+ sendJSON(res, 403, { error: 'client group belongs to a different user' });
25
+ return;
26
+ }
27
+ if (body.cookie === cookie) {
28
+ sendJSON(res, 200, { cookie, unchanged: true });
29
+ return;
30
+ }
31
+ if (typeof body.cookie === 'number' && body.cookie > cookie) {
32
+ sendJSON(res, 409, {
33
+ error: `future cookie ${body.cookie} is ahead of server cookie ${cookie}`,
34
+ });
35
+ return;
36
+ }
37
+ sendJSON(res, 200, {
38
+ cookie,
39
+ lastMutationIDChanges: lastMutationIDChanges(lmids, body.clientGroupID),
40
+ rowsPatch: [{ op: 'clear' }, ...visibleRowsPatch(tables, userID)],
41
+ });
42
+ return;
43
+ }
44
+ if (path === '/push') {
45
+ const body = (await readJSON(req));
46
+ if (!bindClientGroup(clientGroupUsers, body.clientGroupID, userID)) {
47
+ sendJSON(res, 403, { error: 'client group belongs to a different user' });
48
+ return;
49
+ }
50
+ const mutations = Array.isArray(body.mutations) ? body.mutations : [];
51
+ const gap = findMutationGap(lmids, body.clientGroupID, mutations);
52
+ if (gap) {
53
+ sendJSON(res, 500, { error: gap });
54
+ return;
55
+ }
56
+ const pushResults = [];
57
+ let processedNewMutation = false;
58
+ for (const mutation of mutations) {
59
+ const current = lmidFor(lmids, body.clientGroupID, mutation.clientID);
60
+ if (mutation.id <= current) {
61
+ pushResults.push({
62
+ id: { clientID: mutation.clientID, id: mutation.id },
63
+ result: resultForMutation(mutationResults, body.clientGroupID, mutation.clientID, mutation.id) || {},
64
+ });
65
+ continue;
66
+ }
67
+ const result = applyMutation(tables, userID, mutation);
68
+ setLMID(lmids, body.clientGroupID, mutation.clientID, mutation.id);
69
+ setMutationResult(mutationResults, body.clientGroupID, mutation.clientID, mutation.id, result);
70
+ processedNewMutation = true;
71
+ pushResults.push({
72
+ id: { clientID: mutation.clientID, id: mutation.id },
73
+ result,
74
+ });
75
+ }
76
+ if (processedNewMutation)
77
+ cookie += 1;
78
+ sendJSON(res, 200, { pushResponse: { mutations: pushResults } });
79
+ return;
80
+ }
81
+ sendJSON(res, 404, { error: 'not found' });
82
+ }
83
+ catch (err) {
84
+ sendJSON(res, 500, { error: err instanceof Error ? err.message : String(err) });
85
+ }
86
+ });
87
+ await new Promise((resolve, reject) => {
88
+ server.once('error', reject);
89
+ server.listen(0, '127.0.0.1', () => {
90
+ server.off('error', reject);
91
+ resolve();
92
+ });
93
+ });
94
+ const address = server.address();
95
+ return {
96
+ url: `http://127.0.0.1:${address.port}`,
97
+ version: () => cookie,
98
+ rows: (table) => rowsForTable(tables, table),
99
+ close: () => new Promise((resolve, reject) => {
100
+ server.close((err) => (err ? reject(err) : resolve()));
101
+ }),
102
+ };
103
+ }
104
+ function seedTables(seed) {
105
+ const tables = {
106
+ user: new Map(),
107
+ project: new Map(),
108
+ member: new Map(),
109
+ };
110
+ for (const table of tableNames) {
111
+ for (const row of seed?.[table] || []) {
112
+ if (typeof row.id === 'string')
113
+ tables[table].set(row.id, cloneRow(row));
114
+ }
115
+ }
116
+ return tables;
117
+ }
118
+ function authenticate(req, tables) {
119
+ const header = req.headers.authorization;
120
+ if (!header?.startsWith('Bearer token-'))
121
+ return null;
122
+ const userID = header.slice('Bearer token-'.length);
123
+ return tables.user.has(userID) ? userID : null;
124
+ }
125
+ function bindClientGroup(clientGroupUsers, clientGroupID, userID) {
126
+ const owner = clientGroupUsers.get(clientGroupID);
127
+ if (owner)
128
+ return owner === userID;
129
+ clientGroupUsers.set(clientGroupID, userID);
130
+ return true;
131
+ }
132
+ function visibleRowsPatch(tables, userID) {
133
+ const visibleProjectIDs = visibleProjectIDSet(tables, userID);
134
+ const rows = [];
135
+ const user = tables.user.get(userID);
136
+ if (user)
137
+ rows.push({ op: 'put', tableName: 'user', value: cloneRow(user) });
138
+ for (const project of tables.project.values()) {
139
+ if (visibleProjectIDs.has(project.id)) {
140
+ rows.push({ op: 'put', tableName: 'project', value: cloneRow(project) });
141
+ }
142
+ }
143
+ for (const member of tables.member.values()) {
144
+ if (visibleProjectIDs.has(member.projectId)) {
145
+ rows.push({ op: 'put', tableName: 'member', value: cloneRow(member) });
146
+ }
147
+ }
148
+ return rows;
149
+ }
150
+ function visibleProjectIDSet(tables, userID) {
151
+ const projectIDs = new Set();
152
+ for (const project of tables.project.values()) {
153
+ if (project.ownerId === userID)
154
+ projectIDs.add(project.id);
155
+ }
156
+ for (const member of tables.member.values()) {
157
+ if (member.userId === userID && tables.project.has(member.projectId)) {
158
+ projectIDs.add(member.projectId);
159
+ }
160
+ }
161
+ return projectIDs;
162
+ }
163
+ function findMutationGap(lmids, clientGroupID, mutations) {
164
+ const nextLMIDs = new Map();
165
+ for (const mutation of mutations) {
166
+ const current = nextLMIDs.get(mutation.clientID) ?? lmidFor(lmids, clientGroupID, mutation.clientID);
167
+ if (mutation.id <= current)
168
+ continue;
169
+ if (mutation.id !== current + 1) {
170
+ return `mutation id gap for ${mutation.clientID}: got ${mutation.id}, expected ${current + 1}`;
171
+ }
172
+ nextLMIDs.set(mutation.clientID, mutation.id);
173
+ }
174
+ return null;
175
+ }
176
+ function applyMutation(tables, userID, mutation) {
177
+ if (mutation.type !== 'custom')
178
+ return appError('unsupported');
179
+ const args = mutation.args[0] || {};
180
+ if (mutation.name === 'project|create') {
181
+ if (tables.project.has(args.id))
182
+ return appError('exists');
183
+ if (args.ownerId !== userID)
184
+ return appError('forbidden');
185
+ tables.project.set(args.id, {
186
+ id: args.id,
187
+ ownerId: args.ownerId,
188
+ name: args.name,
189
+ });
190
+ return {};
191
+ }
192
+ if (mutation.name === 'project|rename') {
193
+ const project = tables.project.get(args.id);
194
+ if (!project)
195
+ return appError('not-found');
196
+ if (project.ownerId !== userID)
197
+ return appError('forbidden');
198
+ tables.project.set(args.id, { ...project, name: args.name });
199
+ return {};
200
+ }
201
+ if (mutation.name === 'member|add') {
202
+ const project = tables.project.get(args.projectId);
203
+ if (!project)
204
+ return appError('not-found');
205
+ if (project.ownerId !== userID)
206
+ return appError('forbidden');
207
+ if (tables.member.has(args.id))
208
+ return appError('exists');
209
+ tables.member.set(args.id, {
210
+ id: args.id,
211
+ projectId: args.projectId,
212
+ userId: args.userId,
213
+ });
214
+ return {};
215
+ }
216
+ if (mutation.name === 'member|remove') {
217
+ const member = tables.member.get(args.id);
218
+ if (!member)
219
+ return appError('not-found');
220
+ const project = tables.project.get(member.projectId);
221
+ if (!project)
222
+ return appError('not-found');
223
+ if (project.ownerId !== userID)
224
+ return appError('forbidden');
225
+ tables.member.delete(args.id);
226
+ return {};
227
+ }
228
+ return appError('unsupported');
229
+ }
230
+ function appError(details) {
231
+ return { error: 'app', details };
232
+ }
233
+ function lastMutationIDChanges(lmids, clientGroupID) {
234
+ return Object.fromEntries(lmids.get(clientGroupID) || []);
235
+ }
236
+ function lmidFor(lmids, clientGroupID, clientID) {
237
+ return lmids.get(clientGroupID)?.get(clientID) || 0;
238
+ }
239
+ function setLMID(lmids, clientGroupID, clientID, id) {
240
+ let group = lmids.get(clientGroupID);
241
+ if (!group) {
242
+ group = new Map();
243
+ lmids.set(clientGroupID, group);
244
+ }
245
+ group.set(clientID, id);
246
+ }
247
+ function resultForMutation(results, clientGroupID, clientID, id) {
248
+ return results.get(clientGroupID)?.get(clientID)?.get(id);
249
+ }
250
+ function setMutationResult(results, clientGroupID, clientID, id, result) {
251
+ let group = results.get(clientGroupID);
252
+ if (!group) {
253
+ group = new Map();
254
+ results.set(clientGroupID, group);
255
+ }
256
+ let client = group.get(clientID);
257
+ if (!client) {
258
+ client = new Map();
259
+ group.set(clientID, client);
260
+ }
261
+ client.set(id, result);
262
+ }
263
+ function rowsForTable(tables, table) {
264
+ if (!isTableName(table))
265
+ return [];
266
+ return [...tables[table].values()].map(cloneRow);
267
+ }
268
+ function isTableName(table) {
269
+ return tableNames.includes(table);
270
+ }
271
+ function cloneRow(row) {
272
+ return { ...row };
273
+ }
274
+ async function readJSON(req) {
275
+ let body = '';
276
+ for await (const chunk of req)
277
+ body += chunk;
278
+ return body ? JSON.parse(body) : {};
279
+ }
280
+ function sendJSON(res, status, body) {
281
+ res.writeHead(status, { 'content-type': 'application/json' });
282
+ res.end(JSON.stringify(body));
283
+ }
284
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/zero-http/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Zero } from '@rocicorp/zero';
2
+ import { zeroHttpFixtureMutators, zeroHttpFixtureSchema } from './fixture-schema.js';
3
+ import { type Row } from './server.js';
4
+ export type FixtureZero = Zero<typeof zeroHttpFixtureSchema, typeof zeroHttpFixtureMutators>;
5
+ export type ZeroHttpHarness = Awaited<ReturnType<typeof startZeroHttpHarness>>;
6
+ export declare function startZeroHttpHarness(opts?: {
7
+ seed?: {
8
+ user?: Row[];
9
+ project?: Row[];
10
+ member?: Row[];
11
+ };
12
+ interceptFetch?: (next: typeof fetch) => typeof fetch;
13
+ }): Promise<{
14
+ server: {
15
+ url: string;
16
+ version(): number;
17
+ rows(table: string): Row[];
18
+ close(): Promise<void>;
19
+ };
20
+ transport: {
21
+ pull(): Promise<void>;
22
+ readonly connections: number;
23
+ uninstall(): void;
24
+ };
25
+ createZero(userID: string, createOpts?: {
26
+ storageKey?: string;
27
+ pingTimeoutMs?: number;
28
+ }): FixtureZero;
29
+ close(): Promise<void>;
30
+ }>;
31
+ export declare function waitForComplete<T>(view: {
32
+ addListener(listener: (data: T, resultType: string) => void): () => void;
33
+ }): Promise<T>;
34
+ export declare function eventually(assertion: () => void | Promise<void>, timeout?: number): Promise<void>;
35
+ export declare function sleep(ms: number): Promise<unknown>;
36
+ //# sourceMappingURL=test-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-harness.d.ts","sourceRoot":"","sources":["../../src/zero-http/test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAErC,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,EAAuB,KAAK,GAAG,EAAE,MAAM,aAAa,CAAA;AAK3D,MAAM,MAAM,WAAW,GAAG,IAAI,CAC5B,OAAO,qBAAqB,EAC5B,OAAO,uBAAuB,CAC/B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAA;AAE9E,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE;IAChD,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;IACxD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,OAAO,KAAK,CAAA;CACtD;;;;;;;;;;;;uBAca,MAAM,eACD;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,WAAW;;GAqBjB;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE;IACvC,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;CACzE,GAAG,OAAO,CAAC,CAAC,CAAC,CAcb;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,SAAQ,iBAatF;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,oBAE/B"}
@@ -0,0 +1,72 @@
1
+ import { Zero } from '@rocicorp/zero';
2
+ import { zeroHttpFixtureMutators, zeroHttpFixtureSchema } from './fixture-schema.js';
3
+ import { startZeroHttpServer } from './server.js';
4
+ import { installZeroHttpTransport } from './transport.js';
5
+ let storageID = 0;
6
+ export async function startZeroHttpHarness(opts) {
7
+ const server = await startZeroHttpServer({ seed: opts?.seed });
8
+ const baseFetch = (input, init) => globalThis.fetch(input, init);
9
+ const transportFetch = opts?.interceptFetch ? opts.interceptFetch(baseFetch) : baseFetch;
10
+ const transport = installZeroHttpTransport({
11
+ origin: server.url,
12
+ fetch: transportFetch,
13
+ });
14
+ const clients = [];
15
+ return {
16
+ server,
17
+ transport,
18
+ createZero(userID, createOpts) {
19
+ const zero = new Zero({
20
+ server: server.url,
21
+ userID,
22
+ auth: `token-${userID}`,
23
+ schema: zeroHttpFixtureSchema,
24
+ kvStore: 'mem',
25
+ storageKey: createOpts?.storageKey ?? `zero-http-harness-${++storageID}`,
26
+ mutators: zeroHttpFixtureMutators,
27
+ pingTimeoutMs: createOpts?.pingTimeoutMs,
28
+ });
29
+ clients.push(zero);
30
+ return zero;
31
+ },
32
+ async close() {
33
+ await transport.pull().catch(() => { });
34
+ while (clients.length)
35
+ await clients.pop()?.close();
36
+ transport.uninstall();
37
+ await server.close();
38
+ },
39
+ };
40
+ }
41
+ export function waitForComplete(view) {
42
+ return new Promise((resolve, reject) => {
43
+ const timeout = setTimeout(() => reject(new Error('timed out waiting for complete query')), 5_000);
44
+ let cleanup = () => { };
45
+ cleanup = view.addListener((data, resultType) => {
46
+ if (resultType !== 'complete')
47
+ return;
48
+ clearTimeout(timeout);
49
+ cleanup();
50
+ resolve(JSON.parse(JSON.stringify(data)));
51
+ });
52
+ });
53
+ }
54
+ export async function eventually(assertion, timeout = 3_000) {
55
+ const started = Date.now();
56
+ let lastError;
57
+ while (Date.now() - started < timeout) {
58
+ try {
59
+ await assertion();
60
+ return;
61
+ }
62
+ catch (error) {
63
+ lastError = error;
64
+ await sleep(10);
65
+ }
66
+ }
67
+ throw lastError;
68
+ }
69
+ export function sleep(ms) {
70
+ return new Promise((resolve) => setTimeout(resolve, ms));
71
+ }
72
+ //# sourceMappingURL=test-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../../src/zero-http/test-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function installZeroHttpTransport(opts: {
2
+ origin: string;
3
+ fetch?: typeof fetch;
4
+ }): {
5
+ pull(): Promise<void>;
6
+ readonly connections: number;
7
+ uninstall(): void;
8
+ };
9
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/zero-http/transport.ts"],"names":[],"mappings":"AAyCA,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACrB,GAAG;IACF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,SAAS,IAAI,IAAI,CAAA;CAClB,CAgDA"}