jazz-tools 0.18.27 → 0.18.29
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/.turbo/turbo-build.log +47 -47
- package/CHANGELOG.md +23 -0
- package/dist/{chunk-ZIAN4UY5.js → chunk-F55R554M.js} +171 -120
- package/dist/chunk-F55R554M.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/inspector/{custom-element-A7UAELEG.js → custom-element-35MDW4SW.js} +1840 -1837
- package/dist/inspector/{custom-element-A7UAELEG.js.map → custom-element-35MDW4SW.js.map} +1 -1
- package/dist/inspector/custom-element.d.ts.map +1 -1
- package/dist/inspector/index.d.ts +1 -1
- package/dist/inspector/index.d.ts.map +1 -1
- package/dist/inspector/index.js +0 -1
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/react-core/hooks.d.ts +4 -0
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +5 -0
- package/dist/react-core/index.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/coList.d.ts +11 -3
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +21 -5
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/group.d.ts +2 -2
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/inbox.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +17 -1
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/tests/coList.unique.test.d.ts +2 -0
- package/dist/tools/tests/coList.unique.test.d.ts.map +1 -0
- package/dist/tools/tests/coMap.unique.test.d.ts +2 -0
- package/dist/tools/tests/coMap.unique.test.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/inspector/custom-element.tsx +4 -0
- package/src/inspector/index.tsx +0 -2
- package/src/react-core/hooks.ts +8 -0
- package/src/react-core/tests/useAccount.test.ts +61 -1
- package/src/react-core/tests/usePassPhraseAuth.test.ts +74 -2
- package/src/tools/coValues/coList.ts +38 -35
- package/src/tools/coValues/coMap.ts +38 -38
- package/src/tools/coValues/group.ts +5 -1
- package/src/tools/coValues/inbox.ts +4 -3
- package/src/tools/coValues/interfaces.ts +119 -0
- package/src/tools/exports.ts +1 -0
- package/src/tools/tests/coList.test.ts +0 -190
- package/src/tools/tests/coList.unique.test.ts +244 -0
- package/src/tools/tests/coMap.test.ts +0 -433
- package/src/tools/tests/coMap.unique.test.ts +579 -0
- package/dist/chunk-ZIAN4UY5.js.map +0 -1
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import { cojsonInternals } from "cojson";
|
|
2
|
+
import { assert, beforeEach, describe, expect, test } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
setupJazzTestSync,
|
|
5
|
+
createJazzTestAccount,
|
|
6
|
+
runWithoutActiveAccount,
|
|
7
|
+
} from "../testing";
|
|
8
|
+
import {
|
|
9
|
+
Group,
|
|
10
|
+
co,
|
|
11
|
+
activeAccountContext,
|
|
12
|
+
unstable_loadUnique,
|
|
13
|
+
} from "../internal";
|
|
14
|
+
import { z } from "../exports";
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
cojsonInternals.CO_VALUE_LOADING_CONFIG.RETRY_DELAY = 1000;
|
|
18
|
+
|
|
19
|
+
await setupJazzTestSync();
|
|
20
|
+
|
|
21
|
+
await createJazzTestAccount({
|
|
22
|
+
isCurrentActiveAccount: true,
|
|
23
|
+
creationProps: { name: "Hermes Puggington" },
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("Creating and finding unique CoMaps", async () => {
|
|
28
|
+
test("Creating and finding unique CoMaps", async () => {
|
|
29
|
+
const group = Group.create();
|
|
30
|
+
|
|
31
|
+
const Person = co.map({
|
|
32
|
+
name: z.string(),
|
|
33
|
+
_height: z.number(),
|
|
34
|
+
birthday: z.date(),
|
|
35
|
+
color: z.string(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const alice = Person.create(
|
|
39
|
+
{
|
|
40
|
+
name: "Alice",
|
|
41
|
+
_height: 100,
|
|
42
|
+
birthday: new Date("1990-01-01"),
|
|
43
|
+
color: "red",
|
|
44
|
+
},
|
|
45
|
+
{ owner: group, unique: { name: "Alice" } },
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const foundAlice = await Person.loadUnique(
|
|
49
|
+
{ name: "Alice" },
|
|
50
|
+
group.$jazz.id,
|
|
51
|
+
);
|
|
52
|
+
expect(foundAlice).toEqual(alice);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("should work with unstable_loadUnique", async () => {
|
|
56
|
+
const group = Group.create();
|
|
57
|
+
|
|
58
|
+
const Person = co.map({
|
|
59
|
+
name: z.string(),
|
|
60
|
+
_height: z.number(),
|
|
61
|
+
birthday: z.date(),
|
|
62
|
+
color: z.string(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const alice = Person.create(
|
|
66
|
+
{
|
|
67
|
+
name: "Alice",
|
|
68
|
+
_height: 100,
|
|
69
|
+
birthday: new Date("1990-01-01"),
|
|
70
|
+
color: "red",
|
|
71
|
+
},
|
|
72
|
+
{ owner: group, unique: { name: "Alice" } },
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const foundAlice = await unstable_loadUnique(Person, {
|
|
76
|
+
unique: { name: "Alice" },
|
|
77
|
+
owner: group,
|
|
78
|
+
});
|
|
79
|
+
expect(foundAlice).toEqual(alice);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("should upsert with unstable_loadUnique", async () => {
|
|
83
|
+
const group = Group.create();
|
|
84
|
+
|
|
85
|
+
const Person = co.map({
|
|
86
|
+
name: z.string(),
|
|
87
|
+
_height: z.number(),
|
|
88
|
+
birthday: z.date(),
|
|
89
|
+
color: z.string(),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const alice = await unstable_loadUnique(Person, {
|
|
93
|
+
unique: { name: "Alice" },
|
|
94
|
+
onCreateWhenMissing: () => {
|
|
95
|
+
Person.create(
|
|
96
|
+
{
|
|
97
|
+
name: "Alice",
|
|
98
|
+
_height: 100,
|
|
99
|
+
birthday: new Date("1990-01-01"),
|
|
100
|
+
color: "red",
|
|
101
|
+
},
|
|
102
|
+
{ owner: group, unique: { name: "Alice" } },
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
owner: group,
|
|
106
|
+
});
|
|
107
|
+
expect(alice?.name).toEqual("Alice");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("manual upserting pattern", async () => {
|
|
111
|
+
// Schema
|
|
112
|
+
const Event = co.map({
|
|
113
|
+
title: z.string(),
|
|
114
|
+
identifier: z.string(),
|
|
115
|
+
external_id: z.string(),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Data
|
|
119
|
+
const sourceData = {
|
|
120
|
+
title: "Test Event Title",
|
|
121
|
+
identifier: "test-event-identifier",
|
|
122
|
+
_id: "test-event-external-id",
|
|
123
|
+
};
|
|
124
|
+
const workspace = Group.create();
|
|
125
|
+
|
|
126
|
+
// Pattern
|
|
127
|
+
let activeEvent = await Event.loadUnique(
|
|
128
|
+
{ identifier: sourceData.identifier },
|
|
129
|
+
workspace.$jazz.id,
|
|
130
|
+
);
|
|
131
|
+
if (!activeEvent) {
|
|
132
|
+
activeEvent = Event.create(
|
|
133
|
+
{
|
|
134
|
+
title: sourceData.title,
|
|
135
|
+
identifier: sourceData.identifier,
|
|
136
|
+
external_id: sourceData._id,
|
|
137
|
+
},
|
|
138
|
+
workspace,
|
|
139
|
+
);
|
|
140
|
+
} else {
|
|
141
|
+
activeEvent.$jazz.applyDiff({
|
|
142
|
+
title: sourceData.title,
|
|
143
|
+
identifier: sourceData.identifier,
|
|
144
|
+
external_id: sourceData._id,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
expect(activeEvent).toEqual({
|
|
148
|
+
title: sourceData.title,
|
|
149
|
+
identifier: sourceData.identifier,
|
|
150
|
+
external_id: sourceData._id,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("upserting a non-existent value", async () => {
|
|
155
|
+
// Schema
|
|
156
|
+
const Event = co.map({
|
|
157
|
+
title: z.string(),
|
|
158
|
+
identifier: z.string(),
|
|
159
|
+
external_id: z.string(),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Data
|
|
163
|
+
const sourceData = {
|
|
164
|
+
title: "Test Event Title",
|
|
165
|
+
identifier: "test-event-identifier",
|
|
166
|
+
_id: "test-event-external-id",
|
|
167
|
+
};
|
|
168
|
+
const workspace = Group.create();
|
|
169
|
+
|
|
170
|
+
// Upserting
|
|
171
|
+
const activeEvent = await Event.upsertUnique({
|
|
172
|
+
value: {
|
|
173
|
+
title: sourceData.title,
|
|
174
|
+
identifier: sourceData.identifier,
|
|
175
|
+
external_id: sourceData._id,
|
|
176
|
+
},
|
|
177
|
+
unique: sourceData.identifier,
|
|
178
|
+
owner: workspace,
|
|
179
|
+
});
|
|
180
|
+
expect(activeEvent).toEqual({
|
|
181
|
+
title: sourceData.title,
|
|
182
|
+
identifier: sourceData.identifier,
|
|
183
|
+
external_id: sourceData._id,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("upserting a existent value without enough permissions should not throw", async () => {
|
|
188
|
+
const Event = co.map({
|
|
189
|
+
title: z.string(),
|
|
190
|
+
identifier: z.string(),
|
|
191
|
+
external_id: z.string(),
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const sourceData = {
|
|
195
|
+
title: "Test Event Title",
|
|
196
|
+
identifier: "test-event-identifier",
|
|
197
|
+
_id: "test-event-external-id",
|
|
198
|
+
};
|
|
199
|
+
const workspace = Group.create();
|
|
200
|
+
|
|
201
|
+
const initialEvent = await Event.upsertUnique({
|
|
202
|
+
value: {
|
|
203
|
+
title: sourceData.title,
|
|
204
|
+
identifier: sourceData.identifier,
|
|
205
|
+
external_id: sourceData._id,
|
|
206
|
+
},
|
|
207
|
+
unique: sourceData.identifier,
|
|
208
|
+
owner: workspace,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const alice = await createJazzTestAccount({
|
|
212
|
+
isCurrentActiveAccount: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const workspaceOnAlice = await Group.load(workspace.$jazz.id, {
|
|
216
|
+
loadAs: alice,
|
|
217
|
+
});
|
|
218
|
+
assert(workspaceOnAlice);
|
|
219
|
+
|
|
220
|
+
const eventOnAlice = await Event.upsertUnique({
|
|
221
|
+
value: {
|
|
222
|
+
title: sourceData.title,
|
|
223
|
+
identifier: sourceData.identifier,
|
|
224
|
+
external_id: sourceData._id,
|
|
225
|
+
},
|
|
226
|
+
unique: sourceData.identifier,
|
|
227
|
+
owner: workspaceOnAlice,
|
|
228
|
+
});
|
|
229
|
+
expect(eventOnAlice).toBeNull();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("upserting without an active account", async () => {
|
|
233
|
+
const account = activeAccountContext.get();
|
|
234
|
+
|
|
235
|
+
// Schema
|
|
236
|
+
const Event = co.map({
|
|
237
|
+
title: z.string(),
|
|
238
|
+
identifier: z.string(),
|
|
239
|
+
external_id: z.string(),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Data
|
|
243
|
+
const sourceData = {
|
|
244
|
+
title: "Test Event Title",
|
|
245
|
+
identifier: "test-event-identifier",
|
|
246
|
+
_id: "test-event-external-id",
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const activeEvent = await runWithoutActiveAccount(() => {
|
|
250
|
+
return Event.upsertUnique({
|
|
251
|
+
value: {
|
|
252
|
+
title: sourceData.title,
|
|
253
|
+
identifier: sourceData.identifier,
|
|
254
|
+
external_id: sourceData._id,
|
|
255
|
+
},
|
|
256
|
+
unique: sourceData.identifier,
|
|
257
|
+
owner: account,
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
expect(activeEvent).toEqual({
|
|
262
|
+
title: sourceData.title,
|
|
263
|
+
identifier: sourceData.identifier,
|
|
264
|
+
external_id: sourceData._id,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
assert(activeEvent);
|
|
268
|
+
|
|
269
|
+
expect(activeEvent.$jazz.owner).toEqual(account);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("upserting an existing value", async () => {
|
|
273
|
+
// Schema
|
|
274
|
+
const Event = co.map({
|
|
275
|
+
title: z.string(),
|
|
276
|
+
identifier: z.string(),
|
|
277
|
+
external_id: z.string(),
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Data
|
|
281
|
+
const oldSourceData = {
|
|
282
|
+
title: "Old Event Title",
|
|
283
|
+
identifier: "test-event-identifier",
|
|
284
|
+
_id: "test-event-external-id",
|
|
285
|
+
};
|
|
286
|
+
const newSourceData = {
|
|
287
|
+
title: "New Event Title",
|
|
288
|
+
identifier: "test-event-identifier",
|
|
289
|
+
_id: "test-event-external-id",
|
|
290
|
+
};
|
|
291
|
+
expect(oldSourceData.identifier).toEqual(newSourceData.identifier);
|
|
292
|
+
const workspace = Group.create();
|
|
293
|
+
const oldActiveEvent = Event.create(
|
|
294
|
+
{
|
|
295
|
+
title: oldSourceData.title,
|
|
296
|
+
identifier: oldSourceData.identifier,
|
|
297
|
+
external_id: oldSourceData._id,
|
|
298
|
+
},
|
|
299
|
+
workspace,
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
// Upserting
|
|
303
|
+
const activeEvent = await Event.upsertUnique({
|
|
304
|
+
value: {
|
|
305
|
+
title: newSourceData.title,
|
|
306
|
+
identifier: newSourceData.identifier,
|
|
307
|
+
external_id: newSourceData._id,
|
|
308
|
+
},
|
|
309
|
+
unique: newSourceData.identifier,
|
|
310
|
+
owner: workspace,
|
|
311
|
+
});
|
|
312
|
+
expect(activeEvent).toEqual({
|
|
313
|
+
title: newSourceData.title,
|
|
314
|
+
identifier: newSourceData.identifier,
|
|
315
|
+
external_id: newSourceData._id,
|
|
316
|
+
});
|
|
317
|
+
expect(activeEvent).not.toEqual(oldActiveEvent);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test("upserting a non-existent value with resolve", async () => {
|
|
321
|
+
const Project = co.map({
|
|
322
|
+
name: z.string(),
|
|
323
|
+
});
|
|
324
|
+
const Organisation = co.map({
|
|
325
|
+
name: z.string(),
|
|
326
|
+
projects: co.list(Project),
|
|
327
|
+
});
|
|
328
|
+
const workspace = Group.create();
|
|
329
|
+
|
|
330
|
+
const myOrg = await Organisation.upsertUnique({
|
|
331
|
+
value: {
|
|
332
|
+
name: "My organisation",
|
|
333
|
+
projects: co.list(Project).create(
|
|
334
|
+
[
|
|
335
|
+
Project.create(
|
|
336
|
+
{
|
|
337
|
+
name: "My project",
|
|
338
|
+
},
|
|
339
|
+
workspace,
|
|
340
|
+
),
|
|
341
|
+
],
|
|
342
|
+
workspace,
|
|
343
|
+
),
|
|
344
|
+
},
|
|
345
|
+
unique: { name: "My organisation" },
|
|
346
|
+
owner: workspace,
|
|
347
|
+
resolve: {
|
|
348
|
+
projects: {
|
|
349
|
+
$each: true,
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
assert(myOrg);
|
|
354
|
+
expect(myOrg).not.toBeNull();
|
|
355
|
+
expect(myOrg.name).toEqual("My organisation");
|
|
356
|
+
expect(myOrg.projects.length).toBe(1);
|
|
357
|
+
expect(myOrg.projects[0]).toMatchObject({
|
|
358
|
+
name: "My project",
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test("upserting an existing value with resolve", async () => {
|
|
363
|
+
const Project = co.map({
|
|
364
|
+
name: z.string(),
|
|
365
|
+
});
|
|
366
|
+
const Organisation = co.map({
|
|
367
|
+
name: z.string(),
|
|
368
|
+
projects: co.list(Project),
|
|
369
|
+
});
|
|
370
|
+
const workspace = Group.create();
|
|
371
|
+
const initialProject = await Project.upsertUnique({
|
|
372
|
+
value: {
|
|
373
|
+
name: "My project",
|
|
374
|
+
},
|
|
375
|
+
unique: { unique: "First project" },
|
|
376
|
+
owner: workspace,
|
|
377
|
+
});
|
|
378
|
+
assert(initialProject);
|
|
379
|
+
expect(initialProject).not.toBeNull();
|
|
380
|
+
expect(initialProject.name).toEqual("My project");
|
|
381
|
+
|
|
382
|
+
const myOrg = await Organisation.upsertUnique({
|
|
383
|
+
value: {
|
|
384
|
+
name: "My organisation",
|
|
385
|
+
projects: co.list(Project).create([initialProject], workspace),
|
|
386
|
+
},
|
|
387
|
+
unique: { name: "My organisation" },
|
|
388
|
+
owner: workspace,
|
|
389
|
+
resolve: {
|
|
390
|
+
projects: {
|
|
391
|
+
$each: true,
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
assert(myOrg);
|
|
396
|
+
expect(myOrg).not.toBeNull();
|
|
397
|
+
expect(myOrg.name).toEqual("My organisation");
|
|
398
|
+
expect(myOrg.projects.length).toBe(1);
|
|
399
|
+
expect(myOrg.projects.at(0)?.name).toEqual("My project");
|
|
400
|
+
|
|
401
|
+
const updatedProject = await Project.upsertUnique({
|
|
402
|
+
value: {
|
|
403
|
+
name: "My updated project",
|
|
404
|
+
},
|
|
405
|
+
unique: { unique: "First project" },
|
|
406
|
+
owner: workspace,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
assert(updatedProject);
|
|
410
|
+
expect(updatedProject).not.toBeNull();
|
|
411
|
+
expect(updatedProject).toEqual(initialProject);
|
|
412
|
+
expect(updatedProject.name).toEqual("My updated project");
|
|
413
|
+
expect(myOrg.projects.length).toBe(1);
|
|
414
|
+
expect(myOrg.projects.at(0)?.name).toEqual("My updated project");
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
test("upserting a partially loaded value on an new value with resolve", async () => {
|
|
418
|
+
const Project = co.map({
|
|
419
|
+
name: z.string(),
|
|
420
|
+
});
|
|
421
|
+
const Organisation = co.map({
|
|
422
|
+
name: z.string(),
|
|
423
|
+
projects: co.list(Project),
|
|
424
|
+
});
|
|
425
|
+
const publicAccess = Group.create();
|
|
426
|
+
publicAccess.addMember("everyone", "writer");
|
|
427
|
+
|
|
428
|
+
const initialProject = await Project.upsertUnique({
|
|
429
|
+
value: {
|
|
430
|
+
name: "My project",
|
|
431
|
+
},
|
|
432
|
+
unique: { unique: "First project" },
|
|
433
|
+
owner: publicAccess,
|
|
434
|
+
});
|
|
435
|
+
assert(initialProject);
|
|
436
|
+
expect(initialProject).not.toBeNull();
|
|
437
|
+
expect(initialProject.name).toEqual("My project");
|
|
438
|
+
|
|
439
|
+
const fullProjectList = co
|
|
440
|
+
.list(Project)
|
|
441
|
+
.create([initialProject], publicAccess);
|
|
442
|
+
|
|
443
|
+
const account = await createJazzTestAccount({
|
|
444
|
+
isCurrentActiveAccount: true,
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
const shallowProjectList = await co
|
|
448
|
+
.list(Project)
|
|
449
|
+
.load(fullProjectList.$jazz.id, {
|
|
450
|
+
loadAs: account,
|
|
451
|
+
});
|
|
452
|
+
assert(shallowProjectList);
|
|
453
|
+
|
|
454
|
+
const publicAccessAsNewAccount = await Group.load(publicAccess.$jazz.id, {
|
|
455
|
+
loadAs: account,
|
|
456
|
+
});
|
|
457
|
+
assert(publicAccessAsNewAccount);
|
|
458
|
+
|
|
459
|
+
const updatedOrg = await Organisation.upsertUnique({
|
|
460
|
+
value: {
|
|
461
|
+
name: "My organisation",
|
|
462
|
+
projects: shallowProjectList,
|
|
463
|
+
},
|
|
464
|
+
unique: { name: "My organisation" },
|
|
465
|
+
owner: publicAccessAsNewAccount,
|
|
466
|
+
resolve: {
|
|
467
|
+
projects: {
|
|
468
|
+
$each: true,
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
assert(updatedOrg);
|
|
474
|
+
|
|
475
|
+
expect(updatedOrg.projects.$jazz.id).toEqual(fullProjectList.$jazz.id);
|
|
476
|
+
expect(updatedOrg.projects.length).toBe(1);
|
|
477
|
+
expect(updatedOrg.projects.at(0)?.name).toEqual("My project");
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
test("upserting a partially loaded value on an existing value with resolve", async () => {
|
|
481
|
+
const Project = co.map({
|
|
482
|
+
name: z.string(),
|
|
483
|
+
});
|
|
484
|
+
const Organisation = co.map({
|
|
485
|
+
name: z.string(),
|
|
486
|
+
projects: co.list(Project),
|
|
487
|
+
});
|
|
488
|
+
const publicAccess = Group.create();
|
|
489
|
+
publicAccess.addMember("everyone", "writer");
|
|
490
|
+
|
|
491
|
+
const initialProject = await Project.upsertUnique({
|
|
492
|
+
value: {
|
|
493
|
+
name: "My project",
|
|
494
|
+
},
|
|
495
|
+
unique: { unique: "First project" },
|
|
496
|
+
owner: publicAccess,
|
|
497
|
+
});
|
|
498
|
+
assert(initialProject);
|
|
499
|
+
|
|
500
|
+
const myOrg = await Organisation.upsertUnique({
|
|
501
|
+
value: {
|
|
502
|
+
name: "My organisation",
|
|
503
|
+
projects: co.list(Project).create([], publicAccess),
|
|
504
|
+
},
|
|
505
|
+
unique: { name: "My organisation" },
|
|
506
|
+
owner: publicAccess,
|
|
507
|
+
resolve: {
|
|
508
|
+
projects: {
|
|
509
|
+
$each: true,
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
assert(myOrg);
|
|
514
|
+
|
|
515
|
+
const fullProjectList = co
|
|
516
|
+
.list(Project)
|
|
517
|
+
.create([initialProject], publicAccess);
|
|
518
|
+
|
|
519
|
+
const account = await createJazzTestAccount({
|
|
520
|
+
isCurrentActiveAccount: true,
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
const shallowProjectList = await co
|
|
524
|
+
.list(Project)
|
|
525
|
+
.load(fullProjectList.$jazz.id, {
|
|
526
|
+
loadAs: account,
|
|
527
|
+
});
|
|
528
|
+
assert(shallowProjectList);
|
|
529
|
+
|
|
530
|
+
const publicAccessAsNewAccount = await Group.load(publicAccess.$jazz.id, {
|
|
531
|
+
loadAs: account,
|
|
532
|
+
});
|
|
533
|
+
assert(publicAccessAsNewAccount);
|
|
534
|
+
|
|
535
|
+
const updatedOrg = await Organisation.upsertUnique({
|
|
536
|
+
value: {
|
|
537
|
+
name: "My organisation",
|
|
538
|
+
projects: shallowProjectList,
|
|
539
|
+
},
|
|
540
|
+
unique: { name: "My organisation" },
|
|
541
|
+
owner: publicAccessAsNewAccount,
|
|
542
|
+
resolve: {
|
|
543
|
+
projects: {
|
|
544
|
+
$each: true,
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
assert(updatedOrg);
|
|
550
|
+
|
|
551
|
+
expect(updatedOrg.projects.$jazz.id).toEqual(fullProjectList.$jazz.id);
|
|
552
|
+
expect(updatedOrg.projects.length).toBe(1);
|
|
553
|
+
expect(updatedOrg.projects.at(0)?.name).toEqual("My project");
|
|
554
|
+
expect(updatedOrg.$jazz.id).toEqual(myOrg.$jazz.id);
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
test("concurrently upserting the same value", async () => {
|
|
558
|
+
const Project = co.map({
|
|
559
|
+
name: z.string(),
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
const owner = Group.create();
|
|
563
|
+
|
|
564
|
+
const promises = Array.from({ length: 3 }, (_, i) =>
|
|
565
|
+
Project.upsertUnique({
|
|
566
|
+
owner,
|
|
567
|
+
unique: "concurrent",
|
|
568
|
+
value: { name: `Project ${i}` },
|
|
569
|
+
}),
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
await Promise.all(promises);
|
|
573
|
+
|
|
574
|
+
const result = await Project.loadUnique("concurrent", owner.$jazz.id);
|
|
575
|
+
assert(result);
|
|
576
|
+
|
|
577
|
+
expect(result.name).toBe(`Project 2`);
|
|
578
|
+
});
|
|
579
|
+
});
|