jazz-tools 0.18.29 → 0.18.30

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 (107) hide show
  1. package/.svelte-kit/__package__/media/image.svelte +7 -4
  2. package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
  3. package/.svelte-kit/__package__/media/image.types.d.ts +1 -0
  4. package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -1
  5. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +63 -0
  6. package/.turbo/turbo-build.log +62 -62
  7. package/CHANGELOG.md +17 -0
  8. package/dist/better-auth/auth/client.d.ts +1 -1
  9. package/dist/better-auth/auth/server.d.ts +1 -1
  10. package/dist/better-auth/auth/server.d.ts.map +1 -1
  11. package/dist/better-auth/auth/server.js.map +1 -1
  12. package/dist/better-auth/database-adapter/index.d.ts +3 -3
  13. package/dist/better-auth/database-adapter/index.d.ts.map +1 -1
  14. package/dist/better-auth/database-adapter/index.js +6 -2
  15. package/dist/better-auth/database-adapter/index.js.map +1 -1
  16. package/dist/better-auth/database-adapter/utils.d.ts.map +1 -1
  17. package/dist/browser/index.d.ts +2 -1
  18. package/dist/browser/index.d.ts.map +1 -1
  19. package/dist/browser/index.js.map +1 -1
  20. package/dist/{chunk-F55R554M.js → chunk-6BIYT3KH.js} +51 -30
  21. package/dist/chunk-6BIYT3KH.js.map +1 -0
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/inspector/{custom-element-35MDW4SW.js → custom-element-RQTLPAPJ.js} +584 -298
  25. package/dist/inspector/custom-element-RQTLPAPJ.js.map +1 -0
  26. package/dist/inspector/index.js +570 -338
  27. package/dist/inspector/index.js.map +1 -1
  28. package/dist/inspector/register-custom-element.js +1 -1
  29. package/dist/inspector/ui/index.d.ts +6 -0
  30. package/dist/inspector/ui/index.d.ts.map +1 -0
  31. package/dist/inspector/viewer/group-view.d.ts +3 -2
  32. package/dist/inspector/viewer/group-view.d.ts.map +1 -1
  33. package/dist/inspector/viewer/page.d.ts.map +1 -1
  34. package/dist/react/index.js +2 -2
  35. package/dist/react/index.js.map +1 -1
  36. package/dist/react/media/image.d.ts +8 -0
  37. package/dist/react/media/image.d.ts.map +1 -1
  38. package/dist/react-native-core/index.js +3 -3
  39. package/dist/react-native-core/index.js.map +1 -1
  40. package/dist/react-native-core/media/image.d.ts +15 -0
  41. package/dist/react-native-core/media/image.d.ts.map +1 -1
  42. package/dist/svelte/media/image.svelte +7 -4
  43. package/dist/svelte/media/image.svelte.d.ts.map +1 -1
  44. package/dist/svelte/media/image.types.d.ts +1 -0
  45. package/dist/svelte/media/image.types.d.ts.map +1 -1
  46. package/dist/svelte/tests/media/image.svelte.test.js +63 -0
  47. package/dist/testing.js +8 -1
  48. package/dist/testing.js.map +1 -1
  49. package/dist/tools/coValues/account.d.ts +1 -0
  50. package/dist/tools/coValues/account.d.ts.map +1 -1
  51. package/dist/tools/coValues/group.d.ts +3 -3
  52. package/dist/tools/coValues/group.d.ts.map +1 -1
  53. package/dist/tools/implementation/invites.d.ts +2 -2
  54. package/dist/tools/implementation/invites.d.ts.map +1 -1
  55. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +1 -1
  56. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
  57. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  58. package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts +3 -1
  59. package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts.map +1 -1
  60. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  61. package/dist/tools/implementation/zodSchema/zodReExport.d.ts +1 -1
  62. package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
  63. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
  64. package/dist/tools/subscribe/SubscriptionScope.d.ts +0 -2
  65. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  66. package/dist/tools/testing.d.ts +1 -0
  67. package/dist/tools/testing.d.ts.map +1 -1
  68. package/dist/tools/tests/CoValueCoreSubscription.test.d.ts.map +1 -0
  69. package/package.json +4 -4
  70. package/src/better-auth/auth/server.ts +7 -2
  71. package/src/better-auth/auth/tests/server.test.ts +39 -17
  72. package/src/better-auth/database-adapter/index.ts +8 -5
  73. package/src/better-auth/database-adapter/utils.ts +4 -0
  74. package/src/browser/index.ts +2 -1
  75. package/src/inspector/ui/index.ts +5 -0
  76. package/src/inspector/viewer/group-view.tsx +304 -20
  77. package/src/inspector/viewer/new-app.tsx +4 -4
  78. package/src/inspector/viewer/page.tsx +16 -2
  79. package/src/react/media/image.tsx +11 -2
  80. package/src/react/tests/media/image.test.tsx +94 -0
  81. package/src/react-native-core/media/image.tsx +11 -3
  82. package/src/svelte/media/image.svelte +7 -4
  83. package/src/svelte/media/image.types.ts +1 -0
  84. package/src/svelte/tests/media/image.svelte.test.ts +85 -0
  85. package/src/tools/coValues/account.ts +30 -5
  86. package/src/tools/coValues/group.ts +13 -12
  87. package/src/tools/coValues/inbox.ts +5 -5
  88. package/src/tools/implementation/invites.ts +3 -8
  89. package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +5 -1
  90. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -0
  91. package/src/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.ts +63 -50
  92. package/src/tools/implementation/zodSchema/zodReExport.ts +2 -2
  93. package/src/tools/subscribe/CoValueCoreSubscription.ts +17 -0
  94. package/src/tools/subscribe/SubscriptionScope.ts +1 -27
  95. package/src/tools/testing.ts +7 -0
  96. package/src/tools/{subscribe → tests}/CoValueCoreSubscription.test.ts +233 -3
  97. package/src/tools/tests/coFeed.branch.test.ts +14 -5
  98. package/src/tools/tests/coMap.test.ts +139 -42
  99. package/src/tools/tests/coOptional.test.ts +9 -1
  100. package/src/tools/tests/groupsAndAccounts.test.ts +156 -1
  101. package/src/tools/tests/load.test.ts +198 -1
  102. package/src/tools/tests/zod.test-d.ts +0 -2
  103. package/src/tools/tests/zod.test.ts +43 -40
  104. package/dist/chunk-F55R554M.js.map +0 -1
  105. package/dist/inspector/custom-element-35MDW4SW.js.map +0 -1
  106. package/dist/tools/subscribe/CoValueCoreSubscription.test.d.ts.map +0 -1
  107. /package/dist/tools/{subscribe → tests}/CoValueCoreSubscription.test.d.ts +0 -0
@@ -1,8 +1,9 @@
1
- import { beforeEach, describe, expect, test, vi } from "vitest";
2
- import { Group, co, z } from "../exports.js";
3
- import { CoValueCoreSubscription } from "./CoValueCoreSubscription.js";
1
+ import { assert, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { Group, co, exportCoValue, z } from "../exports.js";
3
+ import { CoValueCoreSubscription } from "../subscribe/CoValueCoreSubscription.js";
4
4
  import {
5
5
  createJazzTestAccount,
6
+ disableJazzTestSync,
6
7
  getPeerConnectedToTestSyncServer,
7
8
  setupJazzTestSync,
8
9
  } from "../testing.js";
@@ -1100,4 +1101,233 @@ describe("CoValueCoreSubscription", async () => {
1100
1101
  subscription.unsubscribe();
1101
1102
  });
1102
1103
  });
1104
+
1105
+ test("should wait for the full streaming", async () => {
1106
+ disableJazzTestSync();
1107
+
1108
+ const alice = await createJazzTestAccount({
1109
+ isCurrentActiveAccount: true,
1110
+ creationProps: { name: "Hermes Puggington" },
1111
+ });
1112
+
1113
+ const Person = co.map({
1114
+ name: z.string(),
1115
+ update: z.number(),
1116
+ });
1117
+
1118
+ const group = Group.create();
1119
+
1120
+ const person = Person.create(
1121
+ {
1122
+ name: "Bob",
1123
+ update: 1,
1124
+ },
1125
+ group,
1126
+ );
1127
+
1128
+ for (let i = 0; i <= 100; i++) {
1129
+ person.$jazz.applyDiff({
1130
+ name: "1".repeat(1024),
1131
+ update: i,
1132
+ });
1133
+ }
1134
+
1135
+ const bob = await createJazzTestAccount({
1136
+ isCurrentActiveAccount: true,
1137
+ });
1138
+
1139
+ const personContent = await exportCoValue(Person, person.$jazz.id, {
1140
+ loadAs: alice,
1141
+ });
1142
+ assert(personContent);
1143
+
1144
+ const lastPiece = personContent.pop();
1145
+ assert(lastPiece);
1146
+
1147
+ for (const content of personContent) {
1148
+ bob.$jazz.localNode.syncManager.handleNewContent(content, "import");
1149
+ }
1150
+
1151
+ // Simulate the streaming delay on the last piece of the group
1152
+ setTimeout(() => {
1153
+ bob.$jazz.localNode.syncManager.handleNewContent(lastPiece, "import");
1154
+ }, 10);
1155
+
1156
+ // Load the value and expect the migration to run only once
1157
+ // Subscribe to the person
1158
+ let lastResult: any = null;
1159
+ const listener = vi.fn();
1160
+ const subscription = new CoValueCoreSubscription(
1161
+ person.$jazz.localNode,
1162
+ person.$jazz.id,
1163
+ (result) => {
1164
+ lastResult = result;
1165
+ listener(result);
1166
+ },
1167
+ );
1168
+
1169
+ await waitFor(() => expect(listener).toHaveBeenCalled());
1170
+
1171
+ expect(lastResult.core.isCompletelyDownloaded()).toBe(true);
1172
+
1173
+ subscription.unsubscribe();
1174
+ });
1175
+
1176
+ test("should wait for the full streaming of the group", async () => {
1177
+ disableJazzTestSync();
1178
+
1179
+ const alice = await createJazzTestAccount({
1180
+ isCurrentActiveAccount: true,
1181
+ creationProps: { name: "Hermes Puggington" },
1182
+ });
1183
+
1184
+ const Person = co.map({
1185
+ name: z.string(),
1186
+ update: z.number(),
1187
+ });
1188
+
1189
+ const group = Group.create();
1190
+
1191
+ const person = Person.create(
1192
+ {
1193
+ name: "Bob",
1194
+ update: 1,
1195
+ },
1196
+ group,
1197
+ );
1198
+
1199
+ // Make the group to grow big enough to trigger the streaming
1200
+ for (let i = 0; i <= 300; i++) {
1201
+ group.$jazz.raw.rotateReadKey();
1202
+ }
1203
+
1204
+ group.addMember("everyone", "reader");
1205
+
1206
+ const bob = await createJazzTestAccount({
1207
+ isCurrentActiveAccount: true,
1208
+ });
1209
+
1210
+ const personContent = await exportCoValue(Person, person.$jazz.id, {
1211
+ loadAs: alice,
1212
+ });
1213
+ assert(personContent);
1214
+
1215
+ const lastGroupPiece = personContent.findLast(
1216
+ (content) => content.id === group.$jazz.id,
1217
+ );
1218
+ assert(lastGroupPiece);
1219
+
1220
+ for (const content of personContent.filter(
1221
+ (content) => content !== lastGroupPiece,
1222
+ )) {
1223
+ bob.$jazz.localNode.syncManager.handleNewContent(content, "import");
1224
+ }
1225
+
1226
+ // Simulate the streaming delay on the last piece of the group
1227
+ setTimeout(() => {
1228
+ bob.$jazz.localNode.syncManager.handleNewContent(
1229
+ lastGroupPiece,
1230
+ "import",
1231
+ );
1232
+ }, 10);
1233
+
1234
+ // Load the value and expect the migration to run only once
1235
+ // Subscribe to the person
1236
+ let lastResult: any = null;
1237
+ const listener = vi.fn();
1238
+ const subscription = new CoValueCoreSubscription(
1239
+ person.$jazz.localNode,
1240
+ person.$jazz.id,
1241
+ (result) => {
1242
+ lastResult = result;
1243
+ listener(result);
1244
+ },
1245
+ );
1246
+
1247
+ await waitFor(() => expect(listener).toHaveBeenCalled());
1248
+
1249
+ expect(lastResult.core.isCompletelyDownloaded()).toBe(true);
1250
+
1251
+ subscription.unsubscribe();
1252
+ });
1253
+
1254
+ test.skip("should wait for the full streaming of the parent group", async () => {
1255
+ disableJazzTestSync();
1256
+
1257
+ const alice = await createJazzTestAccount({
1258
+ isCurrentActiveAccount: true,
1259
+ creationProps: { name: "Hermes Puggington" },
1260
+ });
1261
+
1262
+ const Person = co.map({
1263
+ name: z.string(),
1264
+ update: z.number(),
1265
+ });
1266
+
1267
+ const group = Group.create();
1268
+ const parentGroup = Group.create();
1269
+
1270
+ const person = Person.create(
1271
+ {
1272
+ name: "Bob",
1273
+ update: 1,
1274
+ },
1275
+ group,
1276
+ );
1277
+
1278
+ // Make the parent group to grow big enough to trigger the streaming
1279
+ for (let i = 0; i <= 300; i++) {
1280
+ parentGroup.$jazz.raw.rotateReadKey();
1281
+ }
1282
+
1283
+ group.addMember(parentGroup);
1284
+ parentGroup.addMember("everyone", "reader");
1285
+
1286
+ const bob = await createJazzTestAccount({
1287
+ isCurrentActiveAccount: true,
1288
+ });
1289
+
1290
+ const personContent = await exportCoValue(Person, person.$jazz.id, {
1291
+ loadAs: alice,
1292
+ });
1293
+ assert(personContent);
1294
+
1295
+ const lastGroupPiece = personContent.findLast(
1296
+ (content) => content.id === parentGroup.$jazz.id,
1297
+ );
1298
+ assert(lastGroupPiece);
1299
+
1300
+ for (const content of personContent.filter(
1301
+ (content) => content !== lastGroupPiece,
1302
+ )) {
1303
+ bob.$jazz.localNode.syncManager.handleNewContent(content, "import");
1304
+ }
1305
+
1306
+ // Simulate the streaming delay on the last piece of the group
1307
+ setTimeout(() => {
1308
+ bob.$jazz.localNode.syncManager.handleNewContent(
1309
+ lastGroupPiece,
1310
+ "import",
1311
+ );
1312
+ }, 10);
1313
+
1314
+ // Load the value and expect the migration to run only once
1315
+ // Subscribe to the person
1316
+ let lastResult: any = null;
1317
+ const listener = vi.fn();
1318
+ const subscription = new CoValueCoreSubscription(
1319
+ person.$jazz.localNode,
1320
+ person.$jazz.id,
1321
+ (result) => {
1322
+ lastResult = result;
1323
+ listener(result);
1324
+ },
1325
+ );
1326
+
1327
+ await waitFor(() => expect(listener).toHaveBeenCalled());
1328
+
1329
+ expect(lastResult.core.isCompletelyDownloaded()).toBe(true);
1330
+
1331
+ subscription.unsubscribe();
1332
+ });
1103
1333
  });
@@ -247,6 +247,8 @@ describe("CoFeed Branching", async () => {
247
247
  Group.create(me).makePublic("writer"),
248
248
  );
249
249
 
250
+ await new Promise((resolve) => setTimeout(resolve, 5));
251
+
250
252
  const branch = await TestStream.load(originalFeed.$jazz.id, {
251
253
  unstable_branch: { name: "double-merge-branch" },
252
254
  });
@@ -258,7 +260,16 @@ describe("CoFeed Branching", async () => {
258
260
  // First merge
259
261
  branch.$jazz.unstable_merge();
260
262
 
261
- expect(originalFeed.perAccount[me.$jazz.id]?.value).toEqual("jam");
263
+ const feed = await TestStream.load(originalFeed.$jazz.id);
264
+ assert(feed);
265
+
266
+ if (feed.perAccount[me.$jazz.id]?.value !== "jam") {
267
+ console.log(feed.$jazz.raw.items, feed.perAccount[me.$jazz.id]?.value);
268
+ }
269
+
270
+ expect(feed.perAccount[me.$jazz.id]?.value).toEqual("jam");
271
+
272
+ await new Promise((resolve) => setTimeout(resolve, 5));
262
273
 
263
274
  // Make more changes to the branch
264
275
  branch.$jazz.push("cheese");
@@ -267,10 +278,8 @@ describe("CoFeed Branching", async () => {
267
278
  branch.$jazz.unstable_merge();
268
279
 
269
280
  // Verify all changes are applied
270
- expect(originalFeed.perAccount[me.$jazz.id]?.value).toEqual("cheese");
271
- expect(originalFeed.perSession[me.$jazz.sessionID]?.value).toEqual(
272
- "cheese",
273
- );
281
+ expect(feed.perAccount[me.$jazz.id]?.value).toEqual("cheese");
282
+ expect(feed.perSession[me.$jazz.sessionID]?.value).toEqual("cheese");
274
283
  });
275
284
 
276
285
  test("two users merge different branches with different edits", async () => {
@@ -17,9 +17,11 @@ import {
17
17
  TypeSym,
18
18
  activeAccountContext,
19
19
  coValueClassFromCoValueClassOrSchema,
20
+ exportCoValue,
20
21
  } from "../internal.js";
21
22
  import {
22
23
  createJazzTestAccount,
24
+ disableJazzTestSync,
23
25
  getPeerConnectedToTestSyncServer,
24
26
  runWithoutActiveAccount,
25
27
  setupJazzTestSync,
@@ -2101,48 +2103,6 @@ describe("CoMap migration", () => {
2101
2103
  expect(spy).toHaveBeenCalledTimes(1);
2102
2104
  });
2103
2105
 
2104
- test("should run only when the value is fully loaded", async () => {
2105
- await setupJazzTestSync({
2106
- asyncPeers: true,
2107
- });
2108
- await createJazzTestAccount({
2109
- isCurrentActiveAccount: true,
2110
- creationProps: { name: "Hermes Puggington" },
2111
- });
2112
-
2113
- const migration = vi.fn();
2114
- const Person = co
2115
- .map({
2116
- name: z.string(),
2117
- update: z.number(),
2118
- })
2119
- .withMigration((person) => {
2120
- migration(person.update);
2121
- });
2122
-
2123
- const person = Person.create({
2124
- name: "Bob",
2125
- update: 1,
2126
- });
2127
-
2128
- // Pump the value to reach streaming
2129
- for (let i = 0; i <= 300; i++) {
2130
- person.$jazz.raw.assign({
2131
- name: "1".repeat(1024),
2132
- update: i,
2133
- });
2134
- }
2135
-
2136
- // Upload and unmount, to force the streaming download
2137
- await person.$jazz.waitForSync();
2138
- person.$jazz.raw.core.unmount();
2139
-
2140
- // Load the value and expect the migration to run only once
2141
- await Person.load(person.$jazz.id);
2142
- expect(migration).toHaveBeenCalledTimes(1);
2143
- expect(migration).toHaveBeenCalledWith(300);
2144
- });
2145
-
2146
2106
  test("should not break recursive schemas", async () => {
2147
2107
  const PersonV1 = co.map({
2148
2108
  name: z.string(),
@@ -2192,6 +2152,143 @@ describe("CoMap migration", () => {
2192
2152
  expect(loaded?.friend?.name).toEqual("Charlie");
2193
2153
  expect(loaded?.friend?.version).toEqual(2);
2194
2154
  });
2155
+
2156
+ test("should wait for the full streaming before running the migration", async () => {
2157
+ disableJazzTestSync();
2158
+ const alice = await createJazzTestAccount({
2159
+ isCurrentActiveAccount: true,
2160
+ creationProps: { name: "Hermes Puggington" },
2161
+ });
2162
+
2163
+ const migration = vi.fn();
2164
+ const Person = co
2165
+ .map({
2166
+ name: z.string(),
2167
+ update: z.number(),
2168
+ })
2169
+ .withMigration((person) => {
2170
+ migration(person.update);
2171
+ });
2172
+
2173
+ const person = Person.create({
2174
+ name: "Bob",
2175
+ update: 1,
2176
+ });
2177
+
2178
+ person.$jazz.owner.addMember("everyone", "reader");
2179
+
2180
+ // Pump the value to reach streaming
2181
+ for (let i = 0; i <= 300; i++) {
2182
+ person.$jazz.raw.assign({
2183
+ name: "1".repeat(1024),
2184
+ update: i,
2185
+ });
2186
+ }
2187
+
2188
+ const bob = await createJazzTestAccount({
2189
+ isCurrentActiveAccount: true,
2190
+ });
2191
+
2192
+ const personContent = await exportCoValue(Person, person.$jazz.id, {
2193
+ loadAs: alice,
2194
+ });
2195
+ assert(personContent);
2196
+
2197
+ migration.mockClear();
2198
+
2199
+ const lastPiece = personContent.pop();
2200
+ assert(lastPiece);
2201
+
2202
+ for (const content of personContent) {
2203
+ bob.$jazz.localNode.syncManager.handleNewContent(content, "storage");
2204
+ }
2205
+
2206
+ // Simulate the streaming delay on the last piece
2207
+ setTimeout(() => {
2208
+ bob.$jazz.localNode.syncManager.handleNewContent(lastPiece, "storage");
2209
+ }, 10);
2210
+
2211
+ // Load the value and expect the migration to run only once
2212
+ const loadedPerson = await Person.load(person.$jazz.id, { loadAs: bob });
2213
+ assert(loadedPerson);
2214
+ expect(migration).toHaveBeenCalledTimes(1);
2215
+ expect(migration).toHaveBeenCalledWith(300);
2216
+ });
2217
+
2218
+ test("should run only when the group is fully loaded", async () => {
2219
+ disableJazzTestSync();
2220
+
2221
+ const alice = await createJazzTestAccount({
2222
+ isCurrentActiveAccount: true,
2223
+ creationProps: { name: "Hermes Puggington" },
2224
+ });
2225
+ const migration = vi.fn();
2226
+
2227
+ const Person = co
2228
+ .map({
2229
+ name: z.string(),
2230
+ update: z.number(),
2231
+ })
2232
+ .withMigration((person) => {
2233
+ migration({
2234
+ groupStreaming:
2235
+ person.$jazz.owner.$jazz.raw.core.verified.isStreaming(),
2236
+ });
2237
+ });
2238
+
2239
+ const group = Group.create();
2240
+
2241
+ const person = Person.create(
2242
+ {
2243
+ name: "Bob",
2244
+ update: 1,
2245
+ },
2246
+ group,
2247
+ );
2248
+
2249
+ for (let i = 0; i <= 300; i++) {
2250
+ group.$jazz.raw.rotateReadKey();
2251
+ }
2252
+
2253
+ group.addMember("everyone", "reader");
2254
+
2255
+ const bob = await createJazzTestAccount({
2256
+ isCurrentActiveAccount: true,
2257
+ });
2258
+
2259
+ const personContent = await exportCoValue(Person, person.$jazz.id, {
2260
+ loadAs: alice,
2261
+ });
2262
+ assert(personContent);
2263
+
2264
+ // Upload and unmount, to force the streaming download
2265
+ migration.mockClear();
2266
+
2267
+ const lastGroupPiece = personContent.findLast(
2268
+ (content) => content.id === group.$jazz.id,
2269
+ );
2270
+ assert(lastGroupPiece);
2271
+
2272
+ for (const content of personContent.filter(
2273
+ (content) => content !== lastGroupPiece,
2274
+ )) {
2275
+ bob.$jazz.localNode.syncManager.handleNewContent(content, "import");
2276
+ }
2277
+
2278
+ // Simulate the streaming delay on the last piece of the group
2279
+ setTimeout(() => {
2280
+ bob.$jazz.localNode.syncManager.handleNewContent(
2281
+ lastGroupPiece,
2282
+ "import",
2283
+ );
2284
+ }, 10);
2285
+
2286
+ // Load the value and expect the migration to run only once
2287
+ const loadedPerson = await Person.load(person.$jazz.id, { loadAs: bob });
2288
+ assert(loadedPerson);
2289
+ expect(migration).toHaveBeenCalledTimes(1);
2290
+ expect(migration).toHaveBeenCalledWith({ groupStreaming: false });
2291
+ });
2195
2292
  });
2196
2293
 
2197
2294
  describe("createdAt & lastUpdatedAt", () => {
@@ -37,7 +37,7 @@ describe("co.optional", () => {
37
37
  });
38
38
  });
39
39
 
40
- test("can use schem.optional() on all CoValue schemas but co.optional()", () => {
40
+ test("can use schema.optional() on all CoValue schemas but co.optional()", async () => {
41
41
  const Option1 = co.map({ type: z.literal("1") });
42
42
  const Option2 = co.map({ type: z.literal("2") });
43
43
  const Schema = co.map({
@@ -49,6 +49,7 @@ describe("co.optional", () => {
49
49
  map: co.map({ field: z.string() }).optional(),
50
50
  list: co.list(z.string()).optional(),
51
51
  feed: co.feed(z.string()).optional(),
52
+ account: co.account().optional(),
52
53
  union: co.discriminatedUnion("type", [Option1, Option2]).optional(),
53
54
  });
54
55
 
@@ -62,6 +63,7 @@ describe("co.optional", () => {
62
63
  expect(schema.map).toBeUndefined();
63
64
  expect(schema.list).toBeUndefined();
64
65
  expect(schema.feed).toBeUndefined();
66
+ expect(schema.account).toBeUndefined();
65
67
  expect(schema.union).toBeUndefined();
66
68
 
67
69
  schema.$jazz.set(
@@ -91,6 +93,11 @@ describe("co.optional", () => {
91
93
  );
92
94
  schema.$jazz.set("list", Schema.shape.list.innerType.create([]));
93
95
  schema.$jazz.set("feed", Schema.shape.feed.innerType.create([]));
96
+ const loadedAccount = await co
97
+ .account()
98
+ .getMe()
99
+ .$jazz.ensureLoaded({ resolve: { profile: true, root: true } });
100
+ schema.$jazz.set("account", loadedAccount);
94
101
  schema.$jazz.set("union", Option1.create({ type: "1" }));
95
102
 
96
103
  expect(schema.plainText?.toString()).toEqual("Hello");
@@ -101,6 +108,7 @@ describe("co.optional", () => {
101
108
  expect(schema.map?.field).toEqual("hello");
102
109
  expect(schema.list).toEqual([]);
103
110
  expect(schema.feed).not.toBeUndefined();
111
+ expect(schema.account?.profile.name).toEqual("Hermes Puggington");
104
112
  expect(schema.union?.type).toEqual("1");
105
113
  });
106
114