jazz-tools 0.15.15 → 0.16.0
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/.svelte-kit/__package__/jazz.class.svelte.d.ts +2 -2
- package/.svelte-kit/__package__/jazz.class.svelte.d.ts.map +1 -1
- package/.svelte-kit/__package__/jazz.class.svelte.js +5 -5
- package/.svelte-kit/__package__/jazz.svelte.d.ts +2 -2
- package/.svelte-kit/__package__/jazz.svelte.d.ts.map +1 -1
- package/.turbo/turbo-build.log +46 -50
- package/CHANGELOG.md +35 -0
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser-media-images/index.d.ts +3 -1
- package/dist/browser-media-images/index.d.ts.map +1 -1
- package/dist/browser-media-images/index.js.map +1 -1
- package/dist/{chunk-4CFNXQE7.js → chunk-MLCNE3TL.js} +791 -698
- package/dist/chunk-MLCNE3TL.js.map +1 -0
- package/dist/index.js +363 -11
- package/dist/index.js.map +1 -1
- package/dist/react/hooks.d.ts +2 -2
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/testing.js +3 -1
- package/dist/react/testing.js.map +1 -1
- package/dist/react-core/hooks.d.ts +2 -2
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +3 -3
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native-core/hooks.d.ts +2 -2
- package/dist/react-native-core/hooks.d.ts.map +1 -1
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/svelte/jazz.class.svelte.d.ts +2 -2
- package/dist/svelte/jazz.class.svelte.d.ts.map +1 -1
- package/dist/svelte/jazz.class.svelte.js +5 -5
- package/dist/svelte/jazz.svelte.d.ts +2 -2
- package/dist/svelte/jazz.svelte.d.ts.map +1 -1
- package/dist/testing.js +3 -3
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/CoValueBase.d.ts +3 -13
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/coValues/account.d.ts +2 -2
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coFeed.d.ts.map +1 -1
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +5 -18
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +4 -1
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/extensions/imageDef.d.ts +4 -7
- package/dist/tools/coValues/extensions/imageDef.d.ts.map +1 -1
- package/dist/tools/coValues/group.d.ts +1 -0
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/inbox.d.ts +2 -2
- package/dist/tools/coValues/inbox.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +58 -17
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/request.d.ts +82 -0
- package/dist/tools/coValues/request.d.ts.map +1 -0
- package/dist/tools/coValues/schemaUnion.d.ts +5 -1
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +4 -3
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/createContext.d.ts +4 -4
- package/dist/tools/implementation/createContext.d.ts.map +1 -1
- package/dist/tools/implementation/invites.d.ts +2 -2
- package/dist/tools/implementation/invites.d.ts.map +1 -1
- package/dist/tools/implementation/schemaUtils.d.ts +8 -0
- package/dist/tools/implementation/schemaUtils.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/coExport.d.ts +11 -1
- package/dist/tools/implementation/zodSchema/coExport.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts +22 -0
- package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +10 -0
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +11 -11
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +34 -24
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +16 -14
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +23 -17
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +24 -16
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.d.ts +20 -9
- package/dist/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +18 -12
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoValueSchema.d.ts +18 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoValueSchema.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +14 -9
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +14 -9
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +14 -9
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +15 -13
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +12 -15
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts +17 -20
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts +17 -20
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts +3 -5
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts +10 -8
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts +4 -8
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts +21 -30
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +3 -2
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/lib/id.d.ts +2 -0
- package/dist/tools/lib/id.d.ts.map +1 -0
- package/dist/tools/lib/utilityTypes.d.ts +10 -0
- package/dist/tools/lib/utilityTypes.d.ts.map +1 -0
- package/dist/tools/subscribe/SubscriptionScope.d.ts +3 -2
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/subscribe/utils.d.ts.map +1 -1
- package/dist/tools/testing.d.ts +2 -2
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/exportImport.test.d.ts +2 -0
- package/dist/tools/tests/exportImport.test.d.ts.map +1 -0
- package/dist/tools/tests/request.test.d.ts +2 -0
- package/dist/tools/tests/request.test.d.ts.map +1 -0
- package/dist/worker/index.d.ts.map +1 -1
- package/dist/worker/index.js +2 -2
- package/dist/worker/index.js.map +1 -1
- package/package.json +7 -6
- package/src/browser/index.ts +2 -4
- package/src/browser-media-images/index.ts +1 -1
- package/src/react/hooks.tsx +2 -2
- package/src/react-core/hooks.ts +6 -6
- package/src/react-core/tests/useAccount.test.ts +2 -2
- package/src/react-core/tests/useCoState.test.ts +3 -2
- package/src/react-native-core/hooks.tsx +2 -2
- package/src/svelte/jazz.class.svelte.ts +10 -7
- package/src/svelte/jazz.svelte.ts +2 -2
- package/src/tools/coValues/CoValueBase.ts +8 -20
- package/src/tools/coValues/account.ts +18 -14
- package/src/tools/coValues/coFeed.ts +0 -4
- package/src/tools/coValues/coList.ts +7 -9
- package/src/tools/coValues/coMap.ts +1 -6
- package/src/tools/coValues/coPlainText.ts +4 -4
- package/src/tools/coValues/deepLoading.ts +4 -1
- package/src/tools/coValues/extensions/imageDef.ts +3 -3
- package/src/tools/coValues/group.ts +1 -0
- package/src/tools/coValues/inbox.ts +8 -7
- package/src/tools/coValues/interfaces.ts +177 -69
- package/src/tools/coValues/request.ts +633 -0
- package/src/tools/coValues/schemaUnion.ts +8 -4
- package/src/tools/exports.ts +11 -14
- package/src/tools/implementation/createContext.ts +9 -9
- package/src/tools/implementation/invites.ts +2 -2
- package/src/tools/implementation/schemaUtils.ts +18 -0
- package/src/tools/implementation/zodSchema/coExport.ts +14 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.ts +156 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +133 -0
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +36 -17
- package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +101 -52
- package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +54 -50
- package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +54 -46
- package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +187 -137
- package/src/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.ts +29 -27
- package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +28 -18
- package/src/tools/implementation/zodSchema/schemaTypes/CoValueSchema.ts +18 -0
- package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +45 -36
- package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +47 -35
- package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +43 -30
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +28 -23
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +28 -25
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.ts +86 -78
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.ts +91 -82
- package/src/tools/implementation/zodSchema/unionUtils.ts +47 -51
- package/src/tools/implementation/zodSchema/zodCo.ts +42 -75
- package/src/tools/implementation/zodSchema/zodReExport.ts +44 -24
- package/src/tools/implementation/zodSchema/zodSchema.ts +64 -102
- package/src/tools/internal.ts +3 -2
- package/src/tools/lib/id.ts +3 -0
- package/src/tools/lib/utilityTypes.ts +7 -0
- package/src/tools/subscribe/SubscriptionScope.ts +10 -1
- package/src/tools/subscribe/utils.ts +4 -2
- package/src/tools/testing.ts +4 -4
- package/src/tools/tests/ContextManager.test.ts +8 -9
- package/src/tools/tests/account.test.ts +65 -3
- package/src/tools/tests/coDiscriminatedUnion.test-d.ts +38 -0
- package/src/tools/tests/coDiscriminatedUnion.test.ts +219 -1
- package/src/tools/tests/coFeed.test-d.ts +4 -3
- package/src/tools/tests/coList.test-d.ts +32 -3
- package/src/tools/tests/coList.test.ts +20 -2
- package/src/tools/tests/coMap.record.test-d.ts +31 -3
- package/src/tools/tests/coMap.record.test.ts +9 -9
- package/src/tools/tests/coMap.test-d.ts +8 -8
- package/src/tools/tests/coMap.test.ts +19 -5
- package/src/tools/tests/coOptional.test.ts +63 -1
- package/src/tools/tests/createContext.test.ts +7 -9
- package/src/tools/tests/deepLoading.test.ts +4 -10
- package/src/tools/tests/exportImport.test.ts +526 -0
- package/src/tools/tests/groupsAndAccounts.test.ts +5 -4
- package/src/tools/tests/inbox.test.ts +3 -2
- package/src/tools/tests/load.test.ts +3 -29
- package/src/tools/tests/request.test.ts +951 -0
- package/src/tools/tests/schemaUnion.test.ts +2 -2
- package/src/tools/tests/subscribe.test.ts +22 -114
- package/src/tools/tests/testing.test.ts +6 -6
- package/src/tools/tests/zod.test-d.ts +27 -0
- package/src/tools/tests/zod.test.ts +50 -45
- package/src/worker/index.ts +0 -1
- package/tsup.config.ts +0 -2
- package/dist/chunk-4CFNXQE7.js.map +0 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts +0 -12
- package/dist/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts.map +0 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts +0 -9
- package/dist/tools/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts.map +0 -1
- package/src/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.ts +0 -172
- package/src/tools/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.ts +0 -218
@@ -0,0 +1,526 @@
|
|
1
|
+
import { cojsonInternals } from "cojson";
|
2
|
+
import { assert, beforeEach, describe, expect, test } from "vitest";
|
3
|
+
import { exportCoValue, importContentPieces } from "../coValues/interfaces.js";
|
4
|
+
import { Account, CoPlainText, Group, co, z } from "../exports.js";
|
5
|
+
import {
|
6
|
+
createJazzTestAccount,
|
7
|
+
createJazzTestGuest,
|
8
|
+
setupJazzTestSync,
|
9
|
+
} from "../testing.js";
|
10
|
+
|
11
|
+
cojsonInternals.CO_VALUE_LOADING_CONFIG.RETRY_DELAY = 10;
|
12
|
+
|
13
|
+
beforeEach(async () => {
|
14
|
+
await setupJazzTestSync();
|
15
|
+
await createJazzTestAccount({
|
16
|
+
isCurrentActiveAccount: true,
|
17
|
+
});
|
18
|
+
});
|
19
|
+
|
20
|
+
describe("exportCoValue", () => {
|
21
|
+
test("exports a simple CoMap", async () => {
|
22
|
+
const Person = co.map({
|
23
|
+
name: z.string(),
|
24
|
+
age: z.number(),
|
25
|
+
});
|
26
|
+
|
27
|
+
const group = Group.create();
|
28
|
+
const person = Person.create({ name: "John", age: 30 }, group);
|
29
|
+
group.addMember("everyone", "reader");
|
30
|
+
|
31
|
+
const alice = await createJazzTestAccount();
|
32
|
+
|
33
|
+
const exported = await exportCoValue(Person, person.id, {
|
34
|
+
loadAs: alice,
|
35
|
+
});
|
36
|
+
|
37
|
+
expect(exported).not.toBeNull();
|
38
|
+
expect(exported).toBeInstanceOf(Array);
|
39
|
+
expect(exported!.length).toBeGreaterThan(0);
|
40
|
+
|
41
|
+
// Verify the exported content contains the person data
|
42
|
+
const hasPersonContent = exported!.some((piece) => piece.id === person.id);
|
43
|
+
expect(hasPersonContent).toBe(true);
|
44
|
+
});
|
45
|
+
|
46
|
+
test("exports a CoMap with nested references", async () => {
|
47
|
+
const Address = co.map({
|
48
|
+
street: z.string(),
|
49
|
+
city: z.string(),
|
50
|
+
});
|
51
|
+
|
52
|
+
const Person = co.map({
|
53
|
+
name: z.string(),
|
54
|
+
address: Address,
|
55
|
+
});
|
56
|
+
|
57
|
+
const group = Group.create();
|
58
|
+
const address = Address.create(
|
59
|
+
{ street: "123 Main St", city: "New York" },
|
60
|
+
group,
|
61
|
+
);
|
62
|
+
const person = Person.create({ name: "John", address }, group);
|
63
|
+
group.addMember("everyone", "reader");
|
64
|
+
|
65
|
+
const alice = await createJazzTestAccount();
|
66
|
+
|
67
|
+
const exported = await exportCoValue(Person, person.id, {
|
68
|
+
resolve: { address: true },
|
69
|
+
loadAs: alice,
|
70
|
+
});
|
71
|
+
|
72
|
+
expect(exported).not.toBeNull();
|
73
|
+
expect(exported).toBeInstanceOf(Array);
|
74
|
+
expect(exported!.length).toBeGreaterThan(0);
|
75
|
+
|
76
|
+
// Verify both person and address content are exported
|
77
|
+
const personContent = exported!.filter((piece) => piece.id === person.id);
|
78
|
+
const addressContent = exported!.filter((piece) => piece.id === address.id);
|
79
|
+
|
80
|
+
expect(personContent.length).toBeGreaterThan(0);
|
81
|
+
expect(addressContent.length).toBeGreaterThan(0);
|
82
|
+
});
|
83
|
+
|
84
|
+
test("exports a CoList", async () => {
|
85
|
+
const TodoList = co.list(z.string());
|
86
|
+
|
87
|
+
const group = Group.create();
|
88
|
+
const todos = TodoList.create([], group);
|
89
|
+
todos.push("Buy groceries");
|
90
|
+
todos.push("Walk the dog");
|
91
|
+
group.addMember("everyone", "reader");
|
92
|
+
|
93
|
+
const alice = await createJazzTestAccount();
|
94
|
+
|
95
|
+
const exported = await exportCoValue(TodoList, todos.id, {
|
96
|
+
loadAs: alice,
|
97
|
+
});
|
98
|
+
|
99
|
+
expect(exported).not.toBeNull();
|
100
|
+
expect(exported).toBeInstanceOf(Array);
|
101
|
+
expect(exported!.length).toBeGreaterThan(0);
|
102
|
+
|
103
|
+
const hasTodoContent = exported!.some((piece) => piece.id === todos.id);
|
104
|
+
expect(hasTodoContent).toBe(true);
|
105
|
+
});
|
106
|
+
|
107
|
+
test("exports a CoStream", async () => {
|
108
|
+
const ChatStream = co.feed(z.string());
|
109
|
+
|
110
|
+
const group = Group.create();
|
111
|
+
const chat = ChatStream.create([], group);
|
112
|
+
chat.push("Hello");
|
113
|
+
chat.push("World");
|
114
|
+
group.addMember("everyone", "reader");
|
115
|
+
|
116
|
+
const alice = await createJazzTestAccount();
|
117
|
+
|
118
|
+
const exported = await exportCoValue(ChatStream, chat.id, {
|
119
|
+
loadAs: alice,
|
120
|
+
});
|
121
|
+
|
122
|
+
expect(exported).not.toBeNull();
|
123
|
+
expect(exported).toBeInstanceOf(Array);
|
124
|
+
expect(exported!.length).toBeGreaterThan(0);
|
125
|
+
|
126
|
+
const hasChatContent = exported!.some((piece) => piece.id === chat.id);
|
127
|
+
expect(hasChatContent).toBe(true);
|
128
|
+
});
|
129
|
+
|
130
|
+
test("returns null for unauthorized CoValue", async () => {
|
131
|
+
const Person = co.map({
|
132
|
+
name: z.string(),
|
133
|
+
});
|
134
|
+
|
135
|
+
const group = Group.create();
|
136
|
+
const person = Person.create({ name: "John" }, group);
|
137
|
+
// Don't add any members, so it's private
|
138
|
+
|
139
|
+
const alice = await createJazzTestAccount();
|
140
|
+
|
141
|
+
const exported = await exportCoValue(Person, person.id, {
|
142
|
+
loadAs: alice,
|
143
|
+
});
|
144
|
+
|
145
|
+
expect(exported).toBeNull();
|
146
|
+
});
|
147
|
+
|
148
|
+
test("exports with custom resolve options", async () => {
|
149
|
+
const Address = co.map({
|
150
|
+
street: z.string(),
|
151
|
+
city: z.string(),
|
152
|
+
});
|
153
|
+
|
154
|
+
const Person = co.map({
|
155
|
+
name: z.string(),
|
156
|
+
address: Address,
|
157
|
+
});
|
158
|
+
|
159
|
+
const group = Group.create();
|
160
|
+
const address = Address.create(
|
161
|
+
{ street: "123 Main St", city: "New York" },
|
162
|
+
group,
|
163
|
+
);
|
164
|
+
const person = Person.create({ name: "John", address }, group);
|
165
|
+
group.addMember("everyone", "reader");
|
166
|
+
|
167
|
+
const alice = await createJazzTestAccount();
|
168
|
+
|
169
|
+
// Export without resolving nested references
|
170
|
+
const exportedWithoutResolve = await exportCoValue(Person, person.id, {
|
171
|
+
resolve: { address: false },
|
172
|
+
loadAs: alice,
|
173
|
+
});
|
174
|
+
|
175
|
+
// Export with resolving nested references
|
176
|
+
const exportedWithResolve = await exportCoValue(Person, person.id, {
|
177
|
+
resolve: { address: true },
|
178
|
+
loadAs: alice,
|
179
|
+
});
|
180
|
+
|
181
|
+
expect(exportedWithoutResolve).not.toBeNull();
|
182
|
+
expect(exportedWithResolve).not.toBeNull();
|
183
|
+
|
184
|
+
// The version with resolve should have more content pieces
|
185
|
+
expect(exportedWithResolve!.length).toBeGreaterThanOrEqual(
|
186
|
+
exportedWithoutResolve!.length,
|
187
|
+
);
|
188
|
+
});
|
189
|
+
|
190
|
+
test("exports should handle errors on child covalues gracefully", async () => {
|
191
|
+
const Address = co.map({
|
192
|
+
street: co.plainText(),
|
193
|
+
city: co.plainText(),
|
194
|
+
});
|
195
|
+
|
196
|
+
const Person = co.map({
|
197
|
+
name: z.string(),
|
198
|
+
address: Address,
|
199
|
+
});
|
200
|
+
|
201
|
+
const group = Group.create();
|
202
|
+
const address = Address.create(
|
203
|
+
{
|
204
|
+
street: CoPlainText.create("123 Main St"),
|
205
|
+
city: CoPlainText.create("New York"),
|
206
|
+
},
|
207
|
+
group,
|
208
|
+
);
|
209
|
+
const person = Person.create({ name: "John", address }, group);
|
210
|
+
|
211
|
+
// Only add the person to the group, not the address
|
212
|
+
// This makes the address unauthorized for other accounts
|
213
|
+
group.addMember("everyone", "reader");
|
214
|
+
|
215
|
+
const alice = await createJazzTestAccount();
|
216
|
+
|
217
|
+
// Export from alice's perspective with resolve: true
|
218
|
+
// This should attempt to resolve the address but handle the error gracefully
|
219
|
+
const exported = await exportCoValue(Person, person.id, {
|
220
|
+
resolve: { address: { street: true, city: true } },
|
221
|
+
loadAs: alice,
|
222
|
+
bestEffortResolution: true,
|
223
|
+
});
|
224
|
+
|
225
|
+
assert(exported);
|
226
|
+
|
227
|
+
// Verify the person content is exported
|
228
|
+
const personContent = exported.filter((piece) => piece.id === person.id);
|
229
|
+
expect(personContent.length).toBeGreaterThan(0);
|
230
|
+
|
231
|
+
const addressContent = exported.filter((piece) => piece.id === address.id);
|
232
|
+
expect(addressContent.length).toBeGreaterThan(0);
|
233
|
+
|
234
|
+
const streetContent = exported.filter(
|
235
|
+
(piece) => piece.id === address.street.id,
|
236
|
+
);
|
237
|
+
expect(streetContent).toHaveLength(0);
|
238
|
+
|
239
|
+
const cityContent = exported.filter(
|
240
|
+
(piece) => piece.id === address.city.id,
|
241
|
+
);
|
242
|
+
expect(cityContent).toHaveLength(0);
|
243
|
+
});
|
244
|
+
});
|
245
|
+
|
246
|
+
describe("importContentPieces", () => {
|
247
|
+
test("imports content pieces successfully", async () => {
|
248
|
+
const Person = co.map({
|
249
|
+
name: z.string(),
|
250
|
+
age: z.number(),
|
251
|
+
});
|
252
|
+
|
253
|
+
const group = Group.create();
|
254
|
+
const person = Person.create({ name: "John", age: 30 }, group);
|
255
|
+
group.addMember("everyone", "reader");
|
256
|
+
|
257
|
+
const alice = await createJazzTestAccount();
|
258
|
+
const bob = await createJazzTestAccount();
|
259
|
+
|
260
|
+
bob._raw.core.node.syncManager.getPeers().forEach((peer) => {
|
261
|
+
peer.gracefulShutdown();
|
262
|
+
});
|
263
|
+
|
264
|
+
// Export from alice's perspective
|
265
|
+
const exported = await exportCoValue(Person, person.id, {
|
266
|
+
loadAs: alice,
|
267
|
+
});
|
268
|
+
|
269
|
+
expect(exported).not.toBeNull();
|
270
|
+
|
271
|
+
// Import to bob's node
|
272
|
+
importContentPieces(exported!, bob);
|
273
|
+
|
274
|
+
// Verify bob can now access the person
|
275
|
+
const importedPerson = await Person.load(person.id, { loadAs: bob });
|
276
|
+
expect(importedPerson).not.toBeNull();
|
277
|
+
expect(importedPerson?.name).toBe("John");
|
278
|
+
expect(importedPerson?.age).toBe(30);
|
279
|
+
});
|
280
|
+
|
281
|
+
test("imports content pieces with nested references", async () => {
|
282
|
+
const Address = co.map({
|
283
|
+
street: z.string(),
|
284
|
+
city: z.string(),
|
285
|
+
});
|
286
|
+
|
287
|
+
const Person = co.map({
|
288
|
+
name: z.string(),
|
289
|
+
address: Address,
|
290
|
+
});
|
291
|
+
|
292
|
+
const group = Group.create();
|
293
|
+
const address = Address.create(
|
294
|
+
{ street: "123 Main St", city: "New York" },
|
295
|
+
group,
|
296
|
+
);
|
297
|
+
const person = Person.create({ name: "John", address }, group);
|
298
|
+
group.addMember("everyone", "reader");
|
299
|
+
|
300
|
+
const alice = await createJazzTestAccount();
|
301
|
+
const bob = await createJazzTestAccount();
|
302
|
+
|
303
|
+
bob._raw.core.node.syncManager.getPeers().forEach((peer) => {
|
304
|
+
peer.gracefulShutdown();
|
305
|
+
});
|
306
|
+
|
307
|
+
// Export with resolved references
|
308
|
+
const exported = await exportCoValue(Person, person.id, {
|
309
|
+
resolve: { address: true },
|
310
|
+
loadAs: alice,
|
311
|
+
});
|
312
|
+
|
313
|
+
expect(exported).not.toBeNull();
|
314
|
+
|
315
|
+
// Import to bob's node
|
316
|
+
importContentPieces(exported!, bob);
|
317
|
+
|
318
|
+
// Verify bob can access both person and address
|
319
|
+
const importedPerson = await Person.load(person.id, {
|
320
|
+
resolve: { address: true },
|
321
|
+
loadAs: bob,
|
322
|
+
});
|
323
|
+
|
324
|
+
expect(importedPerson).not.toBeNull();
|
325
|
+
expect(importedPerson?.name).toBe("John");
|
326
|
+
expect(importedPerson?.address).not.toBeNull();
|
327
|
+
expect(importedPerson?.address.street).toBe("123 Main St");
|
328
|
+
expect(importedPerson?.address.city).toBe("New York");
|
329
|
+
});
|
330
|
+
|
331
|
+
test("imports content pieces to anonymous agent", async () => {
|
332
|
+
const Person = co.map({
|
333
|
+
name: z.string(),
|
334
|
+
});
|
335
|
+
|
336
|
+
const group = Group.create();
|
337
|
+
const person = Person.create({ name: "John" }, group);
|
338
|
+
group.addMember("everyone", "reader");
|
339
|
+
|
340
|
+
const alice = await createJazzTestAccount();
|
341
|
+
const { guest } = await createJazzTestGuest();
|
342
|
+
|
343
|
+
guest.node.syncManager.getPeers().forEach((peer) => {
|
344
|
+
peer.gracefulShutdown();
|
345
|
+
});
|
346
|
+
|
347
|
+
// Export from alice's perspective
|
348
|
+
const exported = await exportCoValue(Person, person.id, {
|
349
|
+
loadAs: alice,
|
350
|
+
});
|
351
|
+
|
352
|
+
expect(exported).not.toBeNull();
|
353
|
+
|
354
|
+
// Import to anonymous agent
|
355
|
+
importContentPieces(exported!, guest);
|
356
|
+
|
357
|
+
// Verify anonymous agent can access the person
|
358
|
+
const importedPerson = await Person.load(person.id, { loadAs: guest });
|
359
|
+
expect(importedPerson).not.toBeNull();
|
360
|
+
expect(importedPerson?.name).toBe("John");
|
361
|
+
});
|
362
|
+
|
363
|
+
test("imports content pieces without specifying loadAs (uses current account)", async () => {
|
364
|
+
const Person = co.map({
|
365
|
+
name: z.string(),
|
366
|
+
});
|
367
|
+
|
368
|
+
const group = Group.create();
|
369
|
+
const person = Person.create({ name: "John" }, group);
|
370
|
+
group.addMember("everyone", "reader");
|
371
|
+
|
372
|
+
const alice = await createJazzTestAccount();
|
373
|
+
const bob = await createJazzTestAccount({
|
374
|
+
isCurrentActiveAccount: true,
|
375
|
+
});
|
376
|
+
|
377
|
+
bob._raw.core.node.syncManager.getPeers().forEach((peer) => {
|
378
|
+
peer.gracefulShutdown();
|
379
|
+
});
|
380
|
+
|
381
|
+
// Export from alice's perspective
|
382
|
+
const exported = await exportCoValue(Person, person.id, {
|
383
|
+
loadAs: alice,
|
384
|
+
});
|
385
|
+
|
386
|
+
expect(exported).not.toBeNull();
|
387
|
+
|
388
|
+
// Import without specifying loadAs (should use current account)
|
389
|
+
importContentPieces(exported!);
|
390
|
+
|
391
|
+
// Verify bob can access the person
|
392
|
+
const importedPerson = await Person.load(person.id, { loadAs: bob });
|
393
|
+
expect(importedPerson).not.toBeNull();
|
394
|
+
expect(importedPerson?.name).toBe("John");
|
395
|
+
});
|
396
|
+
|
397
|
+
test("handles empty content pieces array", async () => {
|
398
|
+
const alice = await createJazzTestAccount();
|
399
|
+
|
400
|
+
// Should not throw when importing empty array
|
401
|
+
expect(() => {
|
402
|
+
importContentPieces([], alice);
|
403
|
+
}).not.toThrow();
|
404
|
+
});
|
405
|
+
|
406
|
+
test("handles duplicate content pieces", async () => {
|
407
|
+
const Person = co.map({
|
408
|
+
name: z.string(),
|
409
|
+
});
|
410
|
+
|
411
|
+
const group = Group.create();
|
412
|
+
const person = Person.create({ name: "John" }, group);
|
413
|
+
group.addMember("everyone", "reader");
|
414
|
+
|
415
|
+
const alice = await createJazzTestAccount();
|
416
|
+
const bob = await createJazzTestAccount();
|
417
|
+
|
418
|
+
bob._raw.core.node.syncManager.getPeers().forEach((peer) => {
|
419
|
+
peer.gracefulShutdown();
|
420
|
+
});
|
421
|
+
|
422
|
+
// Export from alice's perspective
|
423
|
+
const exported = await exportCoValue(Person, person.id, {
|
424
|
+
loadAs: alice,
|
425
|
+
});
|
426
|
+
|
427
|
+
expect(exported).not.toBeNull();
|
428
|
+
|
429
|
+
// Import the same content pieces twice
|
430
|
+
importContentPieces(exported!, bob);
|
431
|
+
importContentPieces(exported!, bob);
|
432
|
+
|
433
|
+
// Should still work correctly
|
434
|
+
const importedPerson = await Person.load(person.id, { loadAs: bob });
|
435
|
+
expect(importedPerson).not.toBeNull();
|
436
|
+
expect(importedPerson?.name).toBe("John");
|
437
|
+
});
|
438
|
+
|
439
|
+
test("imports content pieces with complex nested structure", async () => {
|
440
|
+
const Comment = co.map({
|
441
|
+
text: z.string(),
|
442
|
+
author: z.string(),
|
443
|
+
});
|
444
|
+
|
445
|
+
const Post = co.map({
|
446
|
+
title: z.string(),
|
447
|
+
content: z.string(),
|
448
|
+
comments: co.list(Comment),
|
449
|
+
});
|
450
|
+
|
451
|
+
const Blog = co.map({
|
452
|
+
name: z.string(),
|
453
|
+
posts: co.list(Post),
|
454
|
+
});
|
455
|
+
|
456
|
+
const group = Group.create();
|
457
|
+
const comment1 = Comment.create(
|
458
|
+
{ text: "Great post!", author: "Alice" },
|
459
|
+
group,
|
460
|
+
);
|
461
|
+
const comment2 = Comment.create({ text: "Thanks!", author: "Bob" }, group);
|
462
|
+
|
463
|
+
const post = Post.create(
|
464
|
+
{
|
465
|
+
title: "My First Post",
|
466
|
+
content: "Hello World",
|
467
|
+
comments: Post.shape.comments.create([comment1, comment2], group),
|
468
|
+
},
|
469
|
+
group,
|
470
|
+
);
|
471
|
+
|
472
|
+
const blog = Blog.create(
|
473
|
+
{ name: "My Blog", posts: Blog.shape.posts.create([post], group) },
|
474
|
+
group,
|
475
|
+
);
|
476
|
+
|
477
|
+
group.addMember("everyone", "reader");
|
478
|
+
|
479
|
+
const alice = await createJazzTestAccount();
|
480
|
+
const bob = await createJazzTestAccount();
|
481
|
+
|
482
|
+
bob._raw.core.node.syncManager.getPeers().forEach((peer) => {
|
483
|
+
peer.gracefulShutdown();
|
484
|
+
});
|
485
|
+
|
486
|
+
// Export with all nested references resolved
|
487
|
+
const exported = await exportCoValue(Blog, blog.id, {
|
488
|
+
resolve: {
|
489
|
+
posts: {
|
490
|
+
$each: {
|
491
|
+
comments: true,
|
492
|
+
},
|
493
|
+
},
|
494
|
+
},
|
495
|
+
loadAs: alice,
|
496
|
+
});
|
497
|
+
|
498
|
+
expect(exported).not.toBeNull();
|
499
|
+
|
500
|
+
// Import to bob's node
|
501
|
+
importContentPieces(exported!, bob);
|
502
|
+
|
503
|
+
// Verify bob can access the entire structure
|
504
|
+
const importedBlog = await Blog.load(blog.id, {
|
505
|
+
resolve: {
|
506
|
+
posts: {
|
507
|
+
$each: {
|
508
|
+
comments: true,
|
509
|
+
},
|
510
|
+
},
|
511
|
+
},
|
512
|
+
loadAs: bob,
|
513
|
+
});
|
514
|
+
|
515
|
+
expect(importedBlog).not.toBeNull();
|
516
|
+
expect(importedBlog?.name).toBe("My Blog");
|
517
|
+
expect(importedBlog?.posts.length).toBe(1);
|
518
|
+
expect(importedBlog?.posts[0]?.title).toBe("My First Post");
|
519
|
+
expect(importedBlog?.posts[0]?.content).toBe("Hello World");
|
520
|
+
expect(importedBlog?.posts[0]?.comments.length).toBe(2);
|
521
|
+
expect(importedBlog?.posts[0]?.comments[0]?.text).toBe("Great post!");
|
522
|
+
expect(importedBlog?.posts[0]?.comments[0]?.author).toBe("Alice");
|
523
|
+
expect(importedBlog?.posts[0]?.comments[1]?.text).toBe("Thanks!");
|
524
|
+
expect(importedBlog?.posts[0]?.comments[1]?.author).toBe("Bob");
|
525
|
+
});
|
526
|
+
});
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
2
2
|
import { assert, beforeEach, describe, expect, test } from "vitest";
|
3
3
|
import { CoMap, Group, z } from "../exports.js";
|
4
|
-
import { Loaded, Ref, co
|
4
|
+
import { Loaded, Ref, co } from "../internal.js";
|
5
5
|
import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
|
6
6
|
import { setupTwoNodes, waitFor } from "./utils.js";
|
7
7
|
|
@@ -22,15 +22,16 @@ describe("Custom accounts and groups", async () => {
|
|
22
22
|
color: z.string(),
|
23
23
|
});
|
24
24
|
|
25
|
+
const Root = co.map({});
|
25
26
|
const CustomAccount = co
|
26
27
|
.account({
|
27
28
|
profile: CustomProfile,
|
28
|
-
root:
|
29
|
+
root: Root,
|
29
30
|
})
|
30
31
|
.withMigration((account, creationProps?: { name: string }) => {
|
31
32
|
// making sure that the inferred type of account.root & account.profile considers the root/profile not being loaded
|
32
33
|
type R = typeof account.root;
|
33
|
-
const _r: R = {} as Loaded<typeof
|
34
|
+
const _r: R = {} as Loaded<typeof Root> | null;
|
34
35
|
type P = typeof account.profile;
|
35
36
|
const _p: P = {} as Loaded<typeof CustomProfile> | null;
|
36
37
|
if (creationProps) {
|
@@ -47,7 +48,7 @@ describe("Custom accounts and groups", async () => {
|
|
47
48
|
const me = await createJazzTestAccount({
|
48
49
|
creationProps: { name: "Hermes Puggington" },
|
49
50
|
isCurrentActiveAccount: true,
|
50
|
-
AccountSchema:
|
51
|
+
AccountSchema: CustomAccount,
|
51
52
|
});
|
52
53
|
|
53
54
|
expect(me.profile).toBeDefined();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
2
2
|
import { Group, Inbox, InboxSender, z } from "../exports";
|
3
|
-
import { Loaded,
|
3
|
+
import { Loaded, co, coValueClassFromCoValueClassOrSchema } from "../internal";
|
4
4
|
import { setupTwoNodes, waitFor } from "./utils";
|
5
5
|
|
6
6
|
const Message = co.map({
|
@@ -18,7 +18,8 @@ describe("Inbox", () => {
|
|
18
18
|
|
19
19
|
const { clientAccount: sender, serverAccount: receiver } =
|
20
20
|
await setupTwoNodes({
|
21
|
-
ServerAccountSchema:
|
21
|
+
ServerAccountSchema:
|
22
|
+
coValueClassFromCoValueClassOrSchema(WorkerAccount),
|
22
23
|
});
|
23
24
|
|
24
25
|
await expect(() => InboxSender.load(receiver.id, sender)).rejects.toThrow(
|
@@ -69,33 +69,6 @@ test("load a missing optional value (co.optional)", async () => {
|
|
69
69
|
expect(john.dog).toBeUndefined();
|
70
70
|
});
|
71
71
|
|
72
|
-
test("load a missing optional value (z.optional)", async () => {
|
73
|
-
const Dog = co.map({
|
74
|
-
name: z.string(),
|
75
|
-
});
|
76
|
-
|
77
|
-
const Person = co.map({
|
78
|
-
name: z.string(),
|
79
|
-
dog: z.optional(Dog),
|
80
|
-
});
|
81
|
-
|
82
|
-
const group = Group.create();
|
83
|
-
const map = Person.create({ name: "John" }, group);
|
84
|
-
group.addMember("everyone", "reader");
|
85
|
-
|
86
|
-
const alice = await createJazzTestAccount();
|
87
|
-
|
88
|
-
const john = await Person.load(map.id, {
|
89
|
-
loadAs: alice,
|
90
|
-
resolve: { dog: true },
|
91
|
-
});
|
92
|
-
|
93
|
-
assert(john);
|
94
|
-
|
95
|
-
expect(john.name).toBe("John");
|
96
|
-
expect(john.dog).toBeUndefined();
|
97
|
-
});
|
98
|
-
|
99
72
|
test("load a missing optional value (Schema.optional)", async () => {
|
100
73
|
const Dog = co.map({
|
101
74
|
name: z.string(),
|
@@ -214,13 +187,14 @@ test("returns null if the value is unavailable after retries", async () => {
|
|
214
187
|
test("load a large coValue", async () => {
|
215
188
|
const syncServer = await setupJazzTestSync({ asyncPeers: true });
|
216
189
|
|
190
|
+
const Data = co.list(z.string());
|
217
191
|
const LargeDataset = co.map({
|
218
192
|
metadata: z.object({
|
219
193
|
name: z.string(),
|
220
194
|
description: z.string(),
|
221
195
|
createdAt: z.number(),
|
222
196
|
}),
|
223
|
-
data:
|
197
|
+
data: Data,
|
224
198
|
});
|
225
199
|
|
226
200
|
const group = Group.create(syncServer);
|
@@ -232,7 +206,7 @@ test("load a large coValue", async () => {
|
|
232
206
|
"A dataset with many entries for testing large coValue loading",
|
233
207
|
createdAt: Date.now(),
|
234
208
|
},
|
235
|
-
data:
|
209
|
+
data: Data.create([], group),
|
236
210
|
},
|
237
211
|
group,
|
238
212
|
);
|