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.
Files changed (217) hide show
  1. package/.svelte-kit/__package__/jazz.class.svelte.d.ts +2 -2
  2. package/.svelte-kit/__package__/jazz.class.svelte.d.ts.map +1 -1
  3. package/.svelte-kit/__package__/jazz.class.svelte.js +5 -5
  4. package/.svelte-kit/__package__/jazz.svelte.d.ts +2 -2
  5. package/.svelte-kit/__package__/jazz.svelte.d.ts.map +1 -1
  6. package/.turbo/turbo-build.log +46 -50
  7. package/CHANGELOG.md +35 -0
  8. package/dist/browser/index.d.ts +2 -2
  9. package/dist/browser/index.d.ts.map +1 -1
  10. package/dist/browser/index.js.map +1 -1
  11. package/dist/browser-media-images/index.d.ts +3 -1
  12. package/dist/browser-media-images/index.d.ts.map +1 -1
  13. package/dist/browser-media-images/index.js.map +1 -1
  14. package/dist/{chunk-4CFNXQE7.js → chunk-MLCNE3TL.js} +791 -698
  15. package/dist/chunk-MLCNE3TL.js.map +1 -0
  16. package/dist/index.js +363 -11
  17. package/dist/index.js.map +1 -1
  18. package/dist/react/hooks.d.ts +2 -2
  19. package/dist/react/hooks.d.ts.map +1 -1
  20. package/dist/react/index.js +2 -0
  21. package/dist/react/index.js.map +1 -1
  22. package/dist/react/testing.js +3 -1
  23. package/dist/react/testing.js.map +1 -1
  24. package/dist/react-core/hooks.d.ts +2 -2
  25. package/dist/react-core/hooks.d.ts.map +1 -1
  26. package/dist/react-core/index.js +3 -3
  27. package/dist/react-core/index.js.map +1 -1
  28. package/dist/react-native-core/hooks.d.ts +2 -2
  29. package/dist/react-native-core/hooks.d.ts.map +1 -1
  30. package/dist/react-native-core/index.js.map +1 -1
  31. package/dist/svelte/jazz.class.svelte.d.ts +2 -2
  32. package/dist/svelte/jazz.class.svelte.d.ts.map +1 -1
  33. package/dist/svelte/jazz.class.svelte.js +5 -5
  34. package/dist/svelte/jazz.svelte.d.ts +2 -2
  35. package/dist/svelte/jazz.svelte.d.ts.map +1 -1
  36. package/dist/testing.js +3 -3
  37. package/dist/testing.js.map +1 -1
  38. package/dist/tools/coValues/CoValueBase.d.ts +3 -13
  39. package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
  40. package/dist/tools/coValues/account.d.ts +2 -2
  41. package/dist/tools/coValues/account.d.ts.map +1 -1
  42. package/dist/tools/coValues/coFeed.d.ts.map +1 -1
  43. package/dist/tools/coValues/coList.d.ts.map +1 -1
  44. package/dist/tools/coValues/coMap.d.ts +5 -18
  45. package/dist/tools/coValues/coMap.d.ts.map +1 -1
  46. package/dist/tools/coValues/deepLoading.d.ts +4 -1
  47. package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
  48. package/dist/tools/coValues/extensions/imageDef.d.ts +4 -7
  49. package/dist/tools/coValues/extensions/imageDef.d.ts.map +1 -1
  50. package/dist/tools/coValues/group.d.ts +1 -0
  51. package/dist/tools/coValues/group.d.ts.map +1 -1
  52. package/dist/tools/coValues/inbox.d.ts +2 -2
  53. package/dist/tools/coValues/inbox.d.ts.map +1 -1
  54. package/dist/tools/coValues/interfaces.d.ts +58 -17
  55. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  56. package/dist/tools/coValues/request.d.ts +82 -0
  57. package/dist/tools/coValues/request.d.ts.map +1 -0
  58. package/dist/tools/coValues/schemaUnion.d.ts +5 -1
  59. package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
  60. package/dist/tools/exports.d.ts +4 -3
  61. package/dist/tools/exports.d.ts.map +1 -1
  62. package/dist/tools/implementation/createContext.d.ts +4 -4
  63. package/dist/tools/implementation/createContext.d.ts.map +1 -1
  64. package/dist/tools/implementation/invites.d.ts +2 -2
  65. package/dist/tools/implementation/invites.d.ts.map +1 -1
  66. package/dist/tools/implementation/schemaUtils.d.ts +8 -0
  67. package/dist/tools/implementation/schemaUtils.d.ts.map +1 -0
  68. package/dist/tools/implementation/zodSchema/coExport.d.ts +11 -1
  69. package/dist/tools/implementation/zodSchema/coExport.d.ts.map +1 -1
  70. package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts +22 -0
  71. package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts.map +1 -0
  72. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +10 -0
  73. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -0
  74. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +11 -11
  75. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  76. package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +34 -24
  77. package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
  78. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +16 -14
  79. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  80. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +23 -17
  81. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  82. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +24 -16
  83. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  84. package/dist/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.d.ts +20 -9
  85. package/dist/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.d.ts.map +1 -1
  86. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +18 -12
  87. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
  88. package/dist/tools/implementation/zodSchema/schemaTypes/CoValueSchema.d.ts +18 -0
  89. package/dist/tools/implementation/zodSchema/schemaTypes/CoValueSchema.d.ts.map +1 -0
  90. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +14 -9
  91. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
  92. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +14 -9
  93. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
  94. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +14 -9
  95. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
  96. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +15 -13
  97. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
  98. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +12 -15
  99. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
  100. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts +17 -20
  101. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts.map +1 -1
  102. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts +17 -20
  103. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts.map +1 -1
  104. package/dist/tools/implementation/zodSchema/unionUtils.d.ts +3 -5
  105. package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
  106. package/dist/tools/implementation/zodSchema/zodCo.d.ts +10 -8
  107. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  108. package/dist/tools/implementation/zodSchema/zodReExport.d.ts +4 -8
  109. package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
  110. package/dist/tools/implementation/zodSchema/zodSchema.d.ts +21 -30
  111. package/dist/tools/implementation/zodSchema/zodSchema.d.ts.map +1 -1
  112. package/dist/tools/internal.d.ts +3 -2
  113. package/dist/tools/internal.d.ts.map +1 -1
  114. package/dist/tools/lib/id.d.ts +2 -0
  115. package/dist/tools/lib/id.d.ts.map +1 -0
  116. package/dist/tools/lib/utilityTypes.d.ts +10 -0
  117. package/dist/tools/lib/utilityTypes.d.ts.map +1 -0
  118. package/dist/tools/subscribe/SubscriptionScope.d.ts +3 -2
  119. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  120. package/dist/tools/subscribe/utils.d.ts.map +1 -1
  121. package/dist/tools/testing.d.ts +2 -2
  122. package/dist/tools/testing.d.ts.map +1 -1
  123. package/dist/tools/tests/exportImport.test.d.ts +2 -0
  124. package/dist/tools/tests/exportImport.test.d.ts.map +1 -0
  125. package/dist/tools/tests/request.test.d.ts +2 -0
  126. package/dist/tools/tests/request.test.d.ts.map +1 -0
  127. package/dist/worker/index.d.ts.map +1 -1
  128. package/dist/worker/index.js +2 -2
  129. package/dist/worker/index.js.map +1 -1
  130. package/package.json +7 -6
  131. package/src/browser/index.ts +2 -4
  132. package/src/browser-media-images/index.ts +1 -1
  133. package/src/react/hooks.tsx +2 -2
  134. package/src/react-core/hooks.ts +6 -6
  135. package/src/react-core/tests/useAccount.test.ts +2 -2
  136. package/src/react-core/tests/useCoState.test.ts +3 -2
  137. package/src/react-native-core/hooks.tsx +2 -2
  138. package/src/svelte/jazz.class.svelte.ts +10 -7
  139. package/src/svelte/jazz.svelte.ts +2 -2
  140. package/src/tools/coValues/CoValueBase.ts +8 -20
  141. package/src/tools/coValues/account.ts +18 -14
  142. package/src/tools/coValues/coFeed.ts +0 -4
  143. package/src/tools/coValues/coList.ts +7 -9
  144. package/src/tools/coValues/coMap.ts +1 -6
  145. package/src/tools/coValues/coPlainText.ts +4 -4
  146. package/src/tools/coValues/deepLoading.ts +4 -1
  147. package/src/tools/coValues/extensions/imageDef.ts +3 -3
  148. package/src/tools/coValues/group.ts +1 -0
  149. package/src/tools/coValues/inbox.ts +8 -7
  150. package/src/tools/coValues/interfaces.ts +177 -69
  151. package/src/tools/coValues/request.ts +633 -0
  152. package/src/tools/coValues/schemaUnion.ts +8 -4
  153. package/src/tools/exports.ts +11 -14
  154. package/src/tools/implementation/createContext.ts +9 -9
  155. package/src/tools/implementation/invites.ts +2 -2
  156. package/src/tools/implementation/schemaUtils.ts +18 -0
  157. package/src/tools/implementation/zodSchema/coExport.ts +14 -0
  158. package/src/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.ts +156 -0
  159. package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +133 -0
  160. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +36 -17
  161. package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +101 -52
  162. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +54 -50
  163. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +54 -46
  164. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +187 -137
  165. package/src/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.ts +29 -27
  166. package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +28 -18
  167. package/src/tools/implementation/zodSchema/schemaTypes/CoValueSchema.ts +18 -0
  168. package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +45 -36
  169. package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +47 -35
  170. package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +43 -30
  171. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +28 -23
  172. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +28 -25
  173. package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.ts +86 -78
  174. package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.ts +91 -82
  175. package/src/tools/implementation/zodSchema/unionUtils.ts +47 -51
  176. package/src/tools/implementation/zodSchema/zodCo.ts +42 -75
  177. package/src/tools/implementation/zodSchema/zodReExport.ts +44 -24
  178. package/src/tools/implementation/zodSchema/zodSchema.ts +64 -102
  179. package/src/tools/internal.ts +3 -2
  180. package/src/tools/lib/id.ts +3 -0
  181. package/src/tools/lib/utilityTypes.ts +7 -0
  182. package/src/tools/subscribe/SubscriptionScope.ts +10 -1
  183. package/src/tools/subscribe/utils.ts +4 -2
  184. package/src/tools/testing.ts +4 -4
  185. package/src/tools/tests/ContextManager.test.ts +8 -9
  186. package/src/tools/tests/account.test.ts +65 -3
  187. package/src/tools/tests/coDiscriminatedUnion.test-d.ts +38 -0
  188. package/src/tools/tests/coDiscriminatedUnion.test.ts +219 -1
  189. package/src/tools/tests/coFeed.test-d.ts +4 -3
  190. package/src/tools/tests/coList.test-d.ts +32 -3
  191. package/src/tools/tests/coList.test.ts +20 -2
  192. package/src/tools/tests/coMap.record.test-d.ts +31 -3
  193. package/src/tools/tests/coMap.record.test.ts +9 -9
  194. package/src/tools/tests/coMap.test-d.ts +8 -8
  195. package/src/tools/tests/coMap.test.ts +19 -5
  196. package/src/tools/tests/coOptional.test.ts +63 -1
  197. package/src/tools/tests/createContext.test.ts +7 -9
  198. package/src/tools/tests/deepLoading.test.ts +4 -10
  199. package/src/tools/tests/exportImport.test.ts +526 -0
  200. package/src/tools/tests/groupsAndAccounts.test.ts +5 -4
  201. package/src/tools/tests/inbox.test.ts +3 -2
  202. package/src/tools/tests/load.test.ts +3 -29
  203. package/src/tools/tests/request.test.ts +951 -0
  204. package/src/tools/tests/schemaUnion.test.ts +2 -2
  205. package/src/tools/tests/subscribe.test.ts +22 -114
  206. package/src/tools/tests/testing.test.ts +6 -6
  207. package/src/tools/tests/zod.test-d.ts +27 -0
  208. package/src/tools/tests/zod.test.ts +50 -45
  209. package/src/worker/index.ts +0 -1
  210. package/tsup.config.ts +0 -2
  211. package/dist/chunk-4CFNXQE7.js.map +0 -1
  212. package/dist/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts +0 -12
  213. package/dist/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts.map +0 -1
  214. package/dist/tools/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts +0 -9
  215. package/dist/tools/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts.map +0 -1
  216. package/src/tools/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.ts +0 -172
  217. 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, zodSchemaToCoSchema } from "../internal.js";
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: co.map({}),
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 CustomAccount.def.shape.root> | null;
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: zodSchemaToCoSchema(CustomAccount),
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, anySchemaToCoSchema, co } from "../internal";
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: anySchemaToCoSchema(WorkerAccount),
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: co.list(z.string()),
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: LargeDataset.def.shape.data.create([], group),
209
+ data: Data.create([], group),
236
210
  },
237
211
  group,
238
212
  );