jazz-tools 0.14.19 → 0.14.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +19 -0
- package/dist/{chunk-AA3SCYKI.js → chunk-DAOCWHIV.js} +248 -125
- package/dist/chunk-DAOCWHIV.js.map +1 -0
- package/dist/coValues/CoValueBase.d.ts +14 -3
- package/dist/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/coValues/coMap.d.ts +27 -1
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/group.d.ts +8 -0
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/interfaces.d.ts +5 -0
- package/dist/coValues/interfaces.d.ts.map +1 -1
- package/dist/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +2 -1
- package/dist/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +2 -0
- package/dist/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +2 -1
- package/dist/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +1 -0
- package/dist/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +1 -0
- package/dist/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +1 -0
- package/dist/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/implementation/zodSchema/zodSchema.d.ts +1 -1
- package/dist/implementation/zodSchema/zodSchema.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/migration.d.ts +3 -0
- package/dist/lib/migration.d.ts.map +1 -0
- package/dist/subscribe/SubscriptionScope.d.ts +3 -1
- package/dist/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/package.json +2 -2
- package/src/coValues/CoValueBase.ts +31 -7
- package/src/coValues/coMap.ts +14 -1
- package/src/coValues/group.ts +12 -0
- package/src/coValues/interfaces.ts +5 -0
- package/src/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.ts +12 -15
- package/src/implementation/zodSchema/schemaTypes/AccountSchema.ts +3 -1
- package/src/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +2 -0
- package/src/implementation/zodSchema/schemaTypes/CoListSchema.ts +2 -0
- package/src/implementation/zodSchema/schemaTypes/CoMapSchema.ts +11 -0
- package/src/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +2 -1
- package/src/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +1 -0
- package/src/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +1 -0
- package/src/implementation/zodSchema/schemaTypes/RichTextSchema.ts +1 -0
- package/src/implementation/zodSchema/zodCo.ts +214 -246
- package/src/implementation/zodSchema/zodSchema.ts +1 -1
- package/src/lib/migration.ts +23 -0
- package/src/subscribe/SubscriptionScope.ts +48 -3
- package/src/tests/coMap.test.ts +280 -1
- package/src/tests/groupsAndAccounts.test.ts +12 -0
- package/src/tests/schemaUnion.test.ts +5 -5
- package/dist/chunk-AA3SCYKI.js.map +0 -1
package/src/tests/coMap.test.ts
CHANGED
@@ -11,7 +11,7 @@ import {
|
|
11
11
|
} from "vitest";
|
12
12
|
import { Group, co, subscribeToCoValue, z } from "../exports.js";
|
13
13
|
import { Account } from "../index.js";
|
14
|
-
import {
|
14
|
+
import { Loaded, zodSchemaToCoSchema } from "../internal.js";
|
15
15
|
import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
|
16
16
|
import { setupTwoNodes, waitFor } from "./utils.js";
|
17
17
|
|
@@ -1356,3 +1356,282 @@ describe("Creating and finding unique CoMaps", async () => {
|
|
1356
1356
|
}
|
1357
1357
|
});
|
1358
1358
|
});
|
1359
|
+
|
1360
|
+
describe("castAs", () => {
|
1361
|
+
test("should cast a co.map type", () => {
|
1362
|
+
const Person = co.map({
|
1363
|
+
name: z.string(),
|
1364
|
+
});
|
1365
|
+
|
1366
|
+
const PersonWithAge = co.map({
|
1367
|
+
name: z.string(),
|
1368
|
+
age: z.number().optional(),
|
1369
|
+
});
|
1370
|
+
|
1371
|
+
const person = Person.create({
|
1372
|
+
name: "Alice",
|
1373
|
+
});
|
1374
|
+
|
1375
|
+
const personWithAge = person.castAs(PersonWithAge);
|
1376
|
+
|
1377
|
+
personWithAge.age = 20;
|
1378
|
+
|
1379
|
+
expect(personWithAge.age).toEqual(20);
|
1380
|
+
});
|
1381
|
+
|
1382
|
+
test("should still be able to autoload in-memory deps", () => {
|
1383
|
+
const Dog = co.map({
|
1384
|
+
name: z.string(),
|
1385
|
+
});
|
1386
|
+
|
1387
|
+
const Person = co.map({
|
1388
|
+
name: z.string(),
|
1389
|
+
dog: Dog,
|
1390
|
+
});
|
1391
|
+
|
1392
|
+
const PersonWithAge = co.map({
|
1393
|
+
name: z.string(),
|
1394
|
+
age: z.number().optional(),
|
1395
|
+
dog: Dog,
|
1396
|
+
});
|
1397
|
+
|
1398
|
+
const person = Person.create({
|
1399
|
+
name: "Alice",
|
1400
|
+
dog: Dog.create({ name: "Rex" }),
|
1401
|
+
});
|
1402
|
+
|
1403
|
+
const personWithAge = person.castAs(PersonWithAge);
|
1404
|
+
|
1405
|
+
personWithAge.age = 20;
|
1406
|
+
|
1407
|
+
expect(personWithAge.age).toEqual(20);
|
1408
|
+
expect(personWithAge.dog?.name).toEqual("Rex");
|
1409
|
+
});
|
1410
|
+
});
|
1411
|
+
|
1412
|
+
describe("CoMap migration", () => {
|
1413
|
+
test("should run on load", async () => {
|
1414
|
+
const PersonV1 = co.map({
|
1415
|
+
name: z.string(),
|
1416
|
+
version: z.literal(1),
|
1417
|
+
});
|
1418
|
+
|
1419
|
+
const Person = co
|
1420
|
+
.map({
|
1421
|
+
name: z.string(),
|
1422
|
+
age: z.number(),
|
1423
|
+
version: z.literal([1, 2]),
|
1424
|
+
})
|
1425
|
+
.withMigration((person) => {
|
1426
|
+
if (person.version === 1) {
|
1427
|
+
person.age = 20;
|
1428
|
+
person.version = 2;
|
1429
|
+
}
|
1430
|
+
});
|
1431
|
+
|
1432
|
+
const person = PersonV1.create({
|
1433
|
+
name: "Bob",
|
1434
|
+
version: 1,
|
1435
|
+
});
|
1436
|
+
|
1437
|
+
expect(person?.name).toEqual("Bob");
|
1438
|
+
expect(person?.version).toEqual(1);
|
1439
|
+
|
1440
|
+
const loadedPerson = await Person.load(person.id);
|
1441
|
+
|
1442
|
+
expect(loadedPerson?.name).toEqual("Bob");
|
1443
|
+
expect(loadedPerson?.age).toEqual(20);
|
1444
|
+
expect(loadedPerson?.version).toEqual(2);
|
1445
|
+
});
|
1446
|
+
|
1447
|
+
test("should handle group updates", async () => {
|
1448
|
+
const Person = co
|
1449
|
+
.map({
|
1450
|
+
name: z.string(),
|
1451
|
+
version: z.literal([1, 2]),
|
1452
|
+
})
|
1453
|
+
.withMigration((person) => {
|
1454
|
+
if (person.version === 1) {
|
1455
|
+
person.version = 2;
|
1456
|
+
|
1457
|
+
person._owner.castAs(Group).addMember("everyone", "reader");
|
1458
|
+
}
|
1459
|
+
});
|
1460
|
+
|
1461
|
+
const person = Person.create({
|
1462
|
+
name: "Bob",
|
1463
|
+
version: 1,
|
1464
|
+
});
|
1465
|
+
|
1466
|
+
expect(person?.name).toEqual("Bob");
|
1467
|
+
expect(person?.version).toEqual(1);
|
1468
|
+
|
1469
|
+
const loadedPerson = await Person.load(person.id);
|
1470
|
+
|
1471
|
+
expect(loadedPerson?.name).toEqual("Bob");
|
1472
|
+
expect(loadedPerson?.version).toEqual(2);
|
1473
|
+
|
1474
|
+
const anotherAccount = await createJazzTestAccount();
|
1475
|
+
|
1476
|
+
const loadedPersonFromAnotherAccount = await Person.load(person.id, {
|
1477
|
+
loadAs: anotherAccount,
|
1478
|
+
});
|
1479
|
+
|
1480
|
+
expect(loadedPersonFromAnotherAccount?.name).toEqual("Bob");
|
1481
|
+
});
|
1482
|
+
|
1483
|
+
test("should throw an error if a migration is async", async () => {
|
1484
|
+
const Person = co
|
1485
|
+
.map({
|
1486
|
+
name: z.string(),
|
1487
|
+
version: z.number(),
|
1488
|
+
})
|
1489
|
+
// @ts-expect-error async function
|
1490
|
+
.withMigration(async () => {});
|
1491
|
+
|
1492
|
+
const person = Person.create({
|
1493
|
+
name: "Bob",
|
1494
|
+
version: 1,
|
1495
|
+
});
|
1496
|
+
|
1497
|
+
await expect(Person.load(person.id)).rejects.toThrow(
|
1498
|
+
"Migration function cannot be async",
|
1499
|
+
);
|
1500
|
+
});
|
1501
|
+
|
1502
|
+
test("should run only once", async () => {
|
1503
|
+
const spy = vi.fn();
|
1504
|
+
const Person = co
|
1505
|
+
.map({
|
1506
|
+
name: z.string(),
|
1507
|
+
version: z.number(),
|
1508
|
+
})
|
1509
|
+
.withMigration((person) => {
|
1510
|
+
spy(person);
|
1511
|
+
});
|
1512
|
+
|
1513
|
+
const person = Person.create({
|
1514
|
+
name: "Bob",
|
1515
|
+
version: 1,
|
1516
|
+
});
|
1517
|
+
|
1518
|
+
await Person.load(person.id);
|
1519
|
+
await Person.load(person.id);
|
1520
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
1521
|
+
});
|
1522
|
+
|
1523
|
+
test("should not break recursive schemas", async () => {
|
1524
|
+
const PersonV1 = co.map({
|
1525
|
+
name: z.string(),
|
1526
|
+
version: z.literal(1),
|
1527
|
+
get friend() {
|
1528
|
+
return PersonV1.optional();
|
1529
|
+
},
|
1530
|
+
});
|
1531
|
+
|
1532
|
+
const Person = co
|
1533
|
+
.map({
|
1534
|
+
name: z.string(),
|
1535
|
+
age: z.number(),
|
1536
|
+
get friend() {
|
1537
|
+
return Person.optional();
|
1538
|
+
},
|
1539
|
+
version: z.literal([1, 2]),
|
1540
|
+
})
|
1541
|
+
.withMigration((person) => {
|
1542
|
+
if (person.version === 1) {
|
1543
|
+
person.age = 20;
|
1544
|
+
person.version = 2;
|
1545
|
+
}
|
1546
|
+
});
|
1547
|
+
|
1548
|
+
const charlie = PersonV1.create({
|
1549
|
+
name: "Charlie",
|
1550
|
+
version: 1,
|
1551
|
+
});
|
1552
|
+
|
1553
|
+
const bob = PersonV1.create({
|
1554
|
+
name: "Bob",
|
1555
|
+
version: 1,
|
1556
|
+
friend: charlie,
|
1557
|
+
});
|
1558
|
+
|
1559
|
+
const loaded = await Person.load(bob.id, {
|
1560
|
+
resolve: {
|
1561
|
+
friend: true,
|
1562
|
+
},
|
1563
|
+
});
|
1564
|
+
|
1565
|
+
// Migration should run on both the person and their friend
|
1566
|
+
expect(loaded?.name).toEqual("Bob");
|
1567
|
+
expect(loaded?.age).toEqual(20);
|
1568
|
+
expect(loaded?.version).toEqual(2);
|
1569
|
+
expect(loaded?.friend?.name).toEqual("Charlie");
|
1570
|
+
expect(loaded?.friend?.version).toEqual(2);
|
1571
|
+
});
|
1572
|
+
describe("Time", () => {
|
1573
|
+
test("empty map created time", () => {
|
1574
|
+
const currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
1575
|
+
const emptyMap = co.map({}).create({});
|
1576
|
+
const createdAtInSeconds = Math.floor(emptyMap._createdAt / 1000);
|
1577
|
+
|
1578
|
+
expect(createdAtInSeconds).toEqual(currentTimestampInSeconds);
|
1579
|
+
expect(emptyMap._lastUpdatedAt).toEqual(emptyMap._createdAt);
|
1580
|
+
});
|
1581
|
+
|
1582
|
+
test("created time and last updated time", async () => {
|
1583
|
+
const Person = co.map({
|
1584
|
+
name: z.string(),
|
1585
|
+
});
|
1586
|
+
|
1587
|
+
let currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
1588
|
+
const person = Person.create({ name: "John" });
|
1589
|
+
|
1590
|
+
const createdAt = person._createdAt;
|
1591
|
+
const createdAtInSeconds = Math.floor(createdAt / 1000);
|
1592
|
+
expect(createdAtInSeconds).toEqual(currentTimestampInSeconds);
|
1593
|
+
expect(person._lastUpdatedAt).toEqual(createdAt);
|
1594
|
+
|
1595
|
+
await new Promise((r) => setTimeout(r, 1000));
|
1596
|
+
currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
1597
|
+
person.name = "Jane";
|
1598
|
+
|
1599
|
+
const lastUpdatedAtInSeconds = Math.floor(person._lastUpdatedAt / 1000);
|
1600
|
+
expect(lastUpdatedAtInSeconds).toEqual(currentTimestampInSeconds);
|
1601
|
+
expect(person._createdAt).toEqual(createdAt);
|
1602
|
+
expect(person._lastUpdatedAt).not.toEqual(createdAt);
|
1603
|
+
});
|
1604
|
+
|
1605
|
+
test("comap with custom uniqueness", () => {
|
1606
|
+
const Person = co.map({
|
1607
|
+
name: z.string(),
|
1608
|
+
});
|
1609
|
+
|
1610
|
+
let currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
1611
|
+
const person = Person.create(
|
1612
|
+
{ name: "John" },
|
1613
|
+
{ unique: "name", owner: Account.getMe() },
|
1614
|
+
);
|
1615
|
+
|
1616
|
+
const createdAt = person._createdAt;
|
1617
|
+
const createdAtInSeconds = Math.floor(createdAt / 1000);
|
1618
|
+
expect(createdAtInSeconds).toEqual(currentTimestampInSeconds);
|
1619
|
+
});
|
1620
|
+
|
1621
|
+
test("empty comap with custom uniqueness", () => {
|
1622
|
+
const Person = co.map({
|
1623
|
+
name: z.optional(z.string()),
|
1624
|
+
});
|
1625
|
+
|
1626
|
+
let currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
1627
|
+
const person = Person.create(
|
1628
|
+
{},
|
1629
|
+
{ unique: "name", owner: Account.getMe() },
|
1630
|
+
);
|
1631
|
+
|
1632
|
+
const createdAt = person._createdAt;
|
1633
|
+
const createdAtInSeconds = Math.floor(createdAt / 1000);
|
1634
|
+
expect(createdAtInSeconds).toEqual(currentTimestampInSeconds);
|
1635
|
+
});
|
1636
|
+
});
|
1637
|
+
});
|
@@ -242,6 +242,18 @@ describe("Group inheritance", () => {
|
|
242
242
|
expect(group.getRoleOf("everyone")).toBe("writeOnly");
|
243
243
|
});
|
244
244
|
|
245
|
+
test("makePublic should add everyone as a reader", () => {
|
246
|
+
const group = Group.create();
|
247
|
+
group.makePublic();
|
248
|
+
expect(group.getRoleOf("everyone")).toBe("reader");
|
249
|
+
});
|
250
|
+
|
251
|
+
test("makePublic should add everyone as a writer", () => {
|
252
|
+
const group = Group.create();
|
253
|
+
group.makePublic("writer");
|
254
|
+
expect(group.getRoleOf("everyone")).toBe("writer");
|
255
|
+
});
|
256
|
+
|
245
257
|
test("typescript should show an error when adding a member with a non-account role", async () => {
|
246
258
|
const account = await createJazzTestAccount({});
|
247
259
|
await account.waitForAllCoValuesSync();
|
@@ -4,11 +4,11 @@ import {
|
|
4
4
|
Account,
|
5
5
|
CryptoProvider,
|
6
6
|
Loaded,
|
7
|
+
anySchemaToCoSchema,
|
7
8
|
co,
|
8
9
|
loadCoValue,
|
9
10
|
subscribeToCoValue,
|
10
11
|
z,
|
11
|
-
zodSchemaToCoSchema,
|
12
12
|
} from "../exports.js";
|
13
13
|
|
14
14
|
const RedButtonWidget = co.map({
|
@@ -73,21 +73,21 @@ describe("SchemaUnion", () => {
|
|
73
73
|
);
|
74
74
|
|
75
75
|
const loadedButtonWidget = await loadCoValue(
|
76
|
-
|
76
|
+
anySchemaToCoSchema(WidgetUnion),
|
77
77
|
buttonWidget.id,
|
78
78
|
{
|
79
79
|
loadAs: me,
|
80
80
|
},
|
81
81
|
);
|
82
82
|
const loadedSliderWidget = await loadCoValue(
|
83
|
-
|
83
|
+
anySchemaToCoSchema(WidgetUnion),
|
84
84
|
sliderWidget.id,
|
85
85
|
{
|
86
86
|
loadAs: me,
|
87
87
|
},
|
88
88
|
);
|
89
89
|
const loadedCheckboxWidget = await loadCoValue(
|
90
|
-
|
90
|
+
anySchemaToCoSchema(WidgetUnion),
|
91
91
|
checkboxWidget.id,
|
92
92
|
{ loadAs: me },
|
93
93
|
);
|
@@ -104,7 +104,7 @@ describe("SchemaUnion", () => {
|
|
104
104
|
);
|
105
105
|
let currentValue = "Submit";
|
106
106
|
const unsubscribe = subscribeToCoValue(
|
107
|
-
|
107
|
+
anySchemaToCoSchema(WidgetUnion),
|
108
108
|
buttonWidget.id,
|
109
109
|
{ loadAs: me, syncResolution: true },
|
110
110
|
(value: Loaded<typeof WidgetUnion>) => {
|