jazz-tools 0.20.0 → 0.20.1

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 (39) hide show
  1. package/.turbo/turbo-build.log +38 -38
  2. package/CHANGELOG.md +11 -0
  3. package/dist/{chunk-3CAPPS2F.js → chunk-2OPP7KWV.js} +149 -74
  4. package/dist/chunk-2OPP7KWV.js.map +1 -0
  5. package/dist/chunk-ZQWSQH6L.js +20 -0
  6. package/dist/index.js +2 -2
  7. package/dist/testing.js +2 -2
  8. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  9. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +2 -1
  10. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  11. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +2 -1
  12. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  13. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +2 -1
  14. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  15. package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts +3 -1
  16. package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts.map +1 -1
  17. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +3 -1
  18. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
  19. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +2 -1
  20. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
  21. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +6 -1
  22. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
  23. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  24. package/dist/tools/ssr.js +1 -1
  25. package/package.json +4 -4
  26. package/src/tools/coValues/coList.ts +73 -37
  27. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +0 -2
  28. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +5 -2
  29. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +5 -2
  30. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +5 -2
  31. package/src/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.ts +6 -2
  32. package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +6 -2
  33. package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +5 -2
  34. package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +9 -2
  35. package/src/tools/tests/coList.test.ts +262 -0
  36. package/src/tools/tests/schema.withPermissions.test.ts +27 -4
  37. package/dist/chunk-3CAPPS2F.js.map +0 -1
  38. package/dist/chunk-PZ5AY32C.js +0 -10
  39. /package/dist/{chunk-PZ5AY32C.js.map → chunk-ZQWSQH6L.js.map} +0 -0
@@ -59,11 +59,14 @@ export class CoMapSchema<
59
59
  */
60
60
  resolveQuery: DefaultResolveQuery = true as DefaultResolveQuery;
61
61
 
62
+ #permissions: SchemaPermissions | null = null;
62
63
  /**
63
64
  * Permissions to be used when creating or composing CoValues
64
65
  * @internal
65
66
  */
66
- permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
67
+ get permissions(): SchemaPermissions {
68
+ return this.#permissions ?? DEFAULT_SCHEMA_PERMISSIONS;
69
+ }
67
70
 
68
71
  constructor(
69
72
  coreSchema: CoreCoMapSchema<Shape, CatchAll>,
@@ -406,7 +409,7 @@ export class CoMapSchema<
406
409
  copy.coValueClass.prototype.migrate = this.coValueClass.prototype.migrate;
407
410
  // @ts-expect-error TS cannot infer that the resolveQuery type is valid
408
411
  copy.resolveQuery = resolveQuery ?? this.resolveQuery;
409
- copy.permissions = permissions ?? this.permissions;
412
+ copy.#permissions = permissions ?? this.#permissions;
410
413
  return copy;
411
414
  }
412
415
  }
@@ -36,10 +36,14 @@ export class CoVectorSchema implements CoreCoVectorSchema {
36
36
  readonly builtin = "CoVector" as const;
37
37
  readonly resolveQuery = true as const;
38
38
 
39
+ #permissions: SchemaPermissions | null = null;
39
40
  /**
40
41
  * Permissions to be used when creating or composing CoValues
42
+ * @internal
41
43
  */
42
- permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
44
+ get permissions(): SchemaPermissions {
45
+ return this.#permissions ?? DEFAULT_SCHEMA_PERMISSIONS;
46
+ }
43
47
 
44
48
  constructor(
45
49
  public dimensions: number,
@@ -119,7 +123,7 @@ export class CoVectorSchema implements CoreCoVectorSchema {
119
123
  */
120
124
  withPermissions(permissions: SchemaPermissions): CoVectorSchema {
121
125
  const copy = new CoVectorSchema(this.dimensions, this.coValueClass);
122
- copy.permissions = permissions;
126
+ copy.#permissions = permissions;
123
127
  return copy;
124
128
  }
125
129
  }
@@ -32,10 +32,14 @@ export class FileStreamSchema implements CoreFileStreamSchema {
32
32
  readonly builtin = "FileStream" as const;
33
33
  readonly resolveQuery = true as const;
34
34
 
35
+ #permissions: SchemaPermissions | null = null;
35
36
  /**
36
37
  * Permissions to be used when creating or composing CoValues
38
+ * @internal
37
39
  */
38
- permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
40
+ get permissions(): SchemaPermissions {
41
+ return this.#permissions ?? DEFAULT_SCHEMA_PERMISSIONS;
42
+ }
39
43
 
40
44
  constructor(private coValueClass: typeof FileStream) {}
41
45
 
@@ -159,7 +163,7 @@ export class FileStreamSchema implements CoreFileStreamSchema {
159
163
  permissions: Omit<SchemaPermissions, "onInlineCreate">,
160
164
  ): FileStreamSchema {
161
165
  const copy = new FileStreamSchema(this.coValueClass);
162
- copy.permissions = permissions;
166
+ copy.#permissions = permissions;
163
167
  return copy;
164
168
  }
165
169
  }
@@ -34,11 +34,14 @@ export class PlainTextSchema implements CorePlainTextSchema {
34
34
  readonly builtin = "CoPlainText" as const;
35
35
  readonly resolveQuery = true as const;
36
36
 
37
+ #permissions: SchemaPermissions | null = null;
37
38
  /**
38
39
  * Permissions to be used when creating or composing CoValues
39
40
  * @internal
40
41
  */
41
- permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
42
+ get permissions(): SchemaPermissions {
43
+ return this.#permissions ?? DEFAULT_SCHEMA_PERMISSIONS;
44
+ }
42
45
 
43
46
  constructor(private coValueClass: typeof CoPlainText) {}
44
47
 
@@ -111,7 +114,7 @@ export class PlainTextSchema implements CorePlainTextSchema {
111
114
  */
112
115
  withPermissions(permissions: SchemaPermissions): PlainTextSchema {
113
116
  const copy = new PlainTextSchema(this.coValueClass);
114
- copy.permissions = permissions;
117
+ copy.#permissions = permissions;
115
118
  return copy;
116
119
  }
117
120
  }
@@ -33,7 +33,14 @@ export class RichTextSchema implements CoreRichTextSchema {
33
33
  readonly builtin = "CoRichText" as const;
34
34
  readonly resolveQuery = true as const;
35
35
 
36
- permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
36
+ #permissions: SchemaPermissions | null = null;
37
+ /**
38
+ * Permissions to be used when creating or composing CoValues
39
+ * @internal
40
+ */
41
+ get permissions(): SchemaPermissions {
42
+ return this.#permissions ?? DEFAULT_SCHEMA_PERMISSIONS;
43
+ }
37
44
 
38
45
  constructor(private coValueClass: typeof CoRichText) {}
39
46
 
@@ -102,7 +109,7 @@ export class RichTextSchema implements CoreRichTextSchema {
102
109
  */
103
110
  withPermissions(permissions: SchemaPermissions): RichTextSchema {
104
111
  const copy = new RichTextSchema(this.coValueClass);
105
- copy.permissions = permissions;
112
+ copy.#permissions = permissions;
106
113
  return copy;
107
114
  }
108
115
  }
@@ -1225,3 +1225,265 @@ describe("lastUpdatedAt", () => {
1225
1225
  expect(list.$jazz.lastUpdatedAt).not.toEqual(updatedAt);
1226
1226
  });
1227
1227
  });
1228
+
1229
+ describe("CoList proxy traps", () => {
1230
+ test(".values() returns the same values as Object.values()", () => {
1231
+ const TestList = co.list(z.string());
1232
+ const list = TestList.create([]);
1233
+ list.$jazz.push("bread");
1234
+ list.$jazz.push("butter");
1235
+ list.$jazz.push("onion");
1236
+
1237
+ const valuesFromMethod = [...list.values()];
1238
+ const valuesFromObject = Object.values(list);
1239
+ expect(valuesFromMethod).toEqual(valuesFromObject);
1240
+ expect(valuesFromMethod).toEqual(["bread", "butter", "onion"]);
1241
+ });
1242
+
1243
+ test(".values().map() returns the same values as .map()", () => {
1244
+ const TestList = co.list(z.string());
1245
+ const list = TestList.create([]);
1246
+ list.$jazz.push("bread");
1247
+ list.$jazz.push("butter");
1248
+ list.$jazz.push("onion");
1249
+
1250
+ const valuesFromMethod = [...list.values().map((v) => v.toUpperCase())];
1251
+ const valuesFromObject = list.map((v) => v.toUpperCase());
1252
+
1253
+ expect(valuesFromMethod).toEqual(valuesFromObject);
1254
+ expect(valuesFromMethod).toEqual(["BREAD", "BUTTER", "ONION"]);
1255
+ });
1256
+
1257
+ test(".keys() returns numeric indices", () => {
1258
+ const TestList = co.list(z.string());
1259
+ const list = TestList.create(["bread", "butter", "onion"]);
1260
+
1261
+ const keys = [...list.keys()];
1262
+
1263
+ expect(keys).toEqual([0, 1, 2]);
1264
+ });
1265
+
1266
+ test(".entries() returns index-value pairs", () => {
1267
+ const TestList = co.list(z.string());
1268
+ const list = TestList.create(["bread", "butter", "onion"]);
1269
+
1270
+ const entries = [...list.entries()];
1271
+
1272
+ expect(entries).toEqual([
1273
+ [0, "bread"],
1274
+ [1, "butter"],
1275
+ [2, "onion"],
1276
+ ]);
1277
+ });
1278
+
1279
+ test("for...of iteration works correctly", () => {
1280
+ const TestList = co.list(z.string());
1281
+ const list = TestList.create(["bread", "butter", "onion"]);
1282
+
1283
+ const items: string[] = [];
1284
+ for (const item of list) {
1285
+ items.push(item);
1286
+ }
1287
+
1288
+ expect(items).toEqual(["bread", "butter", "onion"]);
1289
+ });
1290
+
1291
+ test("spread operator works correctly", () => {
1292
+ const TestList = co.list(z.string());
1293
+ const list = TestList.create(["bread", "butter", "onion"]);
1294
+
1295
+ const items = [...list];
1296
+
1297
+ expect(items).toEqual(["bread", "butter", "onion"]);
1298
+ });
1299
+
1300
+ test("Array.from works correctly", () => {
1301
+ const TestList = co.list(z.string());
1302
+ const list = TestList.create(["bread", "butter", "onion"]);
1303
+
1304
+ const items = Array.from(list);
1305
+
1306
+ expect(items).toEqual(["bread", "butter", "onion"]);
1307
+ });
1308
+
1309
+ test(".values() works with CoValue references", () => {
1310
+ const Dog = co.map({
1311
+ name: z.string(),
1312
+ });
1313
+ const DogList = co.list(Dog);
1314
+
1315
+ const list = DogList.create([
1316
+ { name: "Rex" },
1317
+ { name: "Fido" },
1318
+ { name: "Buddy" },
1319
+ ]);
1320
+
1321
+ const valuesFromMethod = [...list.values()];
1322
+ const valuesFromObject = Object.values(list);
1323
+
1324
+ expect(valuesFromMethod.length).toBe(3);
1325
+ expect(valuesFromMethod.map((d) => d?.name)).toEqual([
1326
+ "Rex",
1327
+ "Fido",
1328
+ "Buddy",
1329
+ ]);
1330
+ expect(valuesFromMethod).toEqual(valuesFromObject);
1331
+ });
1332
+
1333
+ test(".values() works after ensureLoaded", async () => {
1334
+ const Task = co.map({
1335
+ title: z.string(),
1336
+ });
1337
+ const TaskList = co.list(Task);
1338
+
1339
+ const list = TaskList.create([
1340
+ { title: "Task 1" },
1341
+ { title: "Task 2" },
1342
+ { title: "Task 3" },
1343
+ ]);
1344
+
1345
+ const loadedList = await list.$jazz.ensureLoaded({
1346
+ resolve: { $each: true },
1347
+ });
1348
+
1349
+ const valuesFromMethod = [...loadedList.values()];
1350
+ const valuesFromObject = Object.values(loadedList);
1351
+
1352
+ expect(valuesFromMethod.length).toBe(3);
1353
+ expect(valuesFromMethod.map((t) => t.title)).toEqual([
1354
+ "Task 1",
1355
+ "Task 2",
1356
+ "Task 3",
1357
+ ]);
1358
+ expect(valuesFromMethod.map((t) => t.$jazz.id)).toEqual(
1359
+ valuesFromObject.map((t) => t.$jazz.id),
1360
+ );
1361
+ });
1362
+
1363
+ test(".values() works on remotely loaded list", async () => {
1364
+ const Task = co.map({
1365
+ title: z.string(),
1366
+ });
1367
+ const TaskList = co.list(Task);
1368
+
1369
+ const group = Group.create();
1370
+ group.addMember("everyone", "writer");
1371
+
1372
+ const list = TaskList.create(
1373
+ [{ title: "Task 1" }, { title: "Task 2" }, { title: "Task 3" }],
1374
+ group,
1375
+ );
1376
+
1377
+ const userB = await createJazzTestAccount();
1378
+
1379
+ const loadedList = await TaskList.load(list.$jazz.id, {
1380
+ resolve: { $each: true },
1381
+ loadAs: userB,
1382
+ });
1383
+
1384
+ assertLoaded(loadedList);
1385
+
1386
+ const valuesFromMethod = [...loadedList.values()];
1387
+ const valuesFromObject = Object.values(loadedList);
1388
+
1389
+ expect(valuesFromMethod.length).toBe(3);
1390
+ expect(valuesFromMethod.map((t) => t.title)).toEqual([
1391
+ "Task 1",
1392
+ "Task 2",
1393
+ "Task 3",
1394
+ ]);
1395
+ expect(valuesFromMethod.map((t) => t.$jazz.id)).toEqual(
1396
+ valuesFromObject.map((t) => t.$jazz.id),
1397
+ );
1398
+ });
1399
+
1400
+ test("iterator methods work on empty list", () => {
1401
+ const TestList = co.list(z.string());
1402
+ const list = TestList.create([]);
1403
+
1404
+ expect([...list.values()]).toEqual([]);
1405
+ expect([...list.keys()]).toEqual([]);
1406
+ expect([...list.entries()]).toEqual([]);
1407
+ expect([...list]).toEqual([]);
1408
+ });
1409
+
1410
+ test("Object.getOwnPropertyDescriptors returns correct descriptors", () => {
1411
+ const TestList = co.list(z.string());
1412
+ const list = TestList.create(["a", "b", "c"]);
1413
+
1414
+ const descriptors = Object.getOwnPropertyDescriptors(list);
1415
+
1416
+ // Check numeric index descriptors
1417
+ expect(descriptors["0"]).toEqual({
1418
+ enumerable: true,
1419
+ configurable: true,
1420
+ writable: false,
1421
+ value: "a",
1422
+ });
1423
+ expect(descriptors["1"]).toEqual({
1424
+ enumerable: true,
1425
+ configurable: true,
1426
+ writable: false,
1427
+ value: "b",
1428
+ });
1429
+ expect(descriptors["2"]).toEqual({
1430
+ enumerable: true,
1431
+ configurable: true,
1432
+ writable: false,
1433
+ value: "c",
1434
+ });
1435
+
1436
+ // Check length descriptor
1437
+ expect(descriptors["length"]).toEqual({
1438
+ enumerable: false,
1439
+ configurable: false,
1440
+ writable: true,
1441
+ value: 3,
1442
+ });
1443
+
1444
+ // Verify only expected enumerable keys
1445
+ const enumerableKeys = Object.keys(descriptors).filter(
1446
+ (key) => descriptors[key]?.enumerable,
1447
+ );
1448
+ expect(enumerableKeys.sort()).toEqual(["0", "1", "2"]);
1449
+ });
1450
+
1451
+ test("Object.getOwnPropertyDescriptors returns the resolved references", () => {
1452
+ const TestList = co.list(co.map({ name: z.string() }));
1453
+ const list = TestList.create([{ name: "a" }, { name: "b" }, { name: "c" }]);
1454
+
1455
+ const descriptors = Object.getOwnPropertyDescriptors(list);
1456
+
1457
+ // Check numeric index descriptors
1458
+ expect(descriptors["0"]).toEqual({
1459
+ enumerable: true,
1460
+ configurable: true,
1461
+ writable: false,
1462
+ value: list[0],
1463
+ });
1464
+ expect(descriptors["1"]).toEqual({
1465
+ enumerable: true,
1466
+ configurable: true,
1467
+ writable: false,
1468
+ value: list[1],
1469
+ });
1470
+ expect(descriptors["2"]).toEqual({
1471
+ enumerable: true,
1472
+ configurable: true,
1473
+ writable: false,
1474
+ value: list[2],
1475
+ });
1476
+ });
1477
+
1478
+ test("setting the lenght to 0 has no effect", () => {
1479
+ const TestList = co.list(z.string());
1480
+ const list = TestList.create(["a", "b", "c"]);
1481
+
1482
+ list.length = 0;
1483
+
1484
+ expect(list.length).toBe(3);
1485
+ expect(list[0]).toBe("a");
1486
+ expect(list[1]).toBe("b");
1487
+ expect(list[2]).toBe("c");
1488
+ });
1489
+ });
@@ -843,7 +843,7 @@ describe("setDefaultSchemaPermissions", () => {
843
843
  expect(childOwner.getRoleOf(anotherAccount.$jazz.id)).toEqual("reader");
844
844
  });
845
845
 
846
- test("does not modify permissions for existing schemas", () => {
846
+ test("modifies default permissions for existing schemas", () => {
847
847
  const ExistingMap = co.map({
848
848
  name: co.plainText(),
849
849
  });
@@ -852,8 +852,31 @@ describe("setDefaultSchemaPermissions", () => {
852
852
  });
853
853
 
854
854
  const map = ExistingMap.create({ name: "Hello" });
855
- expect(
856
- map.name.$jazz.owner.getParentGroups().map((group) => group.$jazz.id),
857
- ).toContain(map.$jazz.owner.$jazz.id);
855
+ expect(map.name.$jazz.owner.$jazz.id).toContain(map.$jazz.owner.$jazz.id);
856
+ });
857
+
858
+ test("modifies default permissions for copied schemas", async () => {
859
+ const anotherAccount = await createJazzTestAccount();
860
+
861
+ const ExistingMap = co.map({
862
+ name: co.plainText(),
863
+ });
864
+ setDefaultSchemaPermissions({
865
+ onCreate() {
866
+ // Do nothing
867
+ },
868
+ });
869
+ const CopiedMap = ExistingMap.resolved({ name: true });
870
+ setDefaultSchemaPermissions({
871
+ onCreate(newGroup) {
872
+ newGroup.addMember(anotherAccount, "reader");
873
+ },
874
+ });
875
+
876
+ const map = CopiedMap.create({ name: "Hello" });
877
+ await map.$jazz.waitForSync();
878
+
879
+ const mapOwner = map.$jazz.owner;
880
+ expect(mapOwner.getRoleOf(anotherAccount.$jazz.id)).toEqual("reader");
858
881
  });
859
882
  });