jazz-tools 0.8.45 → 0.8.49

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/package.json CHANGED
@@ -19,9 +19,9 @@
19
19
  },
20
20
  "type": "module",
21
21
  "license": "MIT",
22
- "version": "0.8.45",
22
+ "version": "0.8.49",
23
23
  "dependencies": {
24
- "cojson": "0.8.45"
24
+ "cojson": "0.8.49"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsup": "8.3.5",
@@ -185,7 +185,7 @@ export class Account extends CoValueBase implements CoValue {
185
185
  fromRaw: rawAccount,
186
186
  }) as A;
187
187
 
188
- await account.migrate?.(creationProps);
188
+ await account.applyMigration?.(creationProps);
189
189
  },
190
190
  });
191
191
 
@@ -236,7 +236,7 @@ export class Account extends CoValueBase implements CoValue {
236
236
  return this.toJSON();
237
237
  }
238
238
 
239
- migrate(this: Account, creationProps?: { name: string }) {
239
+ async applyMigration(creationProps?: { name: string }) {
240
240
  if (creationProps) {
241
241
  const profileGroup = RegisteredSchemas["Group"].create({ owner: this });
242
242
  profileGroup.addMember("everyone", "reader");
@@ -256,6 +256,13 @@ export class Account extends CoValueBase implements CoValue {
256
256
  profile.set("inbox", inboxRoot.id);
257
257
  profile.set("inboxInvite", inboxRoot.inviteLink);
258
258
  }
259
+
260
+ await this.migrate(creationProps);
261
+ }
262
+
263
+ // Placeholder method for subclasses to override
264
+ migrate(creationProps?: { name: string }) {
265
+ creationProps; // To avoid unused parameter warning
259
266
  }
260
267
 
261
268
  /** @category Subscription & Loading */
@@ -617,8 +617,14 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
617
617
  } else if (key in target) {
618
618
  return Reflect.get(target, key, receiver);
619
619
  } else {
620
- const descriptor = (target._schema[key as keyof CoMap["_schema"]] ||
621
- target._schema[ItemsSym]) as Schema;
620
+ const schema = target._schema;
621
+
622
+ if (!schema) {
623
+ return undefined;
624
+ }
625
+
626
+ const descriptor = (schema[key as keyof CoMap["_schema"]] ||
627
+ schema[ItemsSym]) as Schema;
622
628
  if (descriptor && typeof key === "string") {
623
629
  const raw = target._raw.get(key);
624
630
 
@@ -169,7 +169,7 @@ export async function createJazzContext<Acc extends Account>(
169
169
  fromRaw: rawAccount,
170
170
  }) as Acc;
171
171
 
172
- await account.migrate?.(creationProps);
172
+ await account.applyMigration(creationProps);
173
173
  },
174
174
  });
175
175
 
@@ -218,7 +218,7 @@ export async function createJazzContext<Acc extends Account>(
218
218
  fromRaw: rawAccount,
219
219
  }) as Acc;
220
220
 
221
- await account.migrate?.(creationProps);
221
+ await account.applyMigration(creationProps);
222
222
  },
223
223
  });
224
224
 
@@ -38,8 +38,6 @@ describe("Simple CoMap operations", async () => {
38
38
  crypto: Crypto,
39
39
  });
40
40
 
41
- console.log("TestMap schema", TestMap.prototype._schema);
42
-
43
41
  const birthday = new Date();
44
42
 
45
43
  const map = TestMap.create(
@@ -82,6 +80,13 @@ describe("Simple CoMap operations", async () => {
82
80
  expect(mapWithExtra.color).toEqual("red");
83
81
  });
84
82
 
83
+ test("Empty schema", () => {
84
+ const emptyMap = CoMap.create({}, { owner: me });
85
+
86
+ // @ts-expect-error
87
+ expect(emptyMap.color).toEqual(undefined);
88
+ });
89
+
85
90
  describe("Mutation", () => {
86
91
  test("assignment & deletion", () => {
87
92
  map.color = "blue";
@@ -468,10 +473,8 @@ describe("CoMap resolution", async () => {
468
473
  const queue = new cojsonInternals.Channel<TestMap>();
469
474
 
470
475
  TestMap.subscribe(map.id, meOnSecondPeer, {}, (subscribedMap) => {
471
- console.log(
472
- "subscribedMap.nested?.twiceNested?.taste",
473
- subscribedMap.nested?.twiceNested?.taste,
474
- );
476
+ // Read to property to trigger loading
477
+ subscribedMap.nested?.twiceNested?.taste;
475
478
  void queue.push(subscribedMap);
476
479
  });
477
480
 
@@ -166,68 +166,6 @@ describe("Group inheritance", () => {
166
166
  expect(mapAsReaderAfterUpdate?.title).toBe("In Grand Child");
167
167
  });
168
168
 
169
- test("Group inheritance should fail if the current account doesn't have admin role in both groups", async () => {
170
- const me = await Account.create({
171
- creationProps: { name: "Hermes Puggington" },
172
- crypto: Crypto,
173
- });
174
-
175
- const other = await Account.createAs(me, {
176
- creationProps: { name: "Another user" },
177
- });
178
-
179
- const parentGroup = Group.create({ owner: me });
180
- parentGroup.addMember(other, "writer");
181
- const group = Group.create({ owner: me });
182
- group.addMember(other, "admin");
183
-
184
- const parentGroupOnTheOtherSide = await Group.load(
185
- parentGroup.id,
186
- other,
187
- {},
188
- );
189
- const groupOnTheOtherSide = await Group.load(group.id, other, {});
190
-
191
- if (!groupOnTheOtherSide || !parentGroupOnTheOtherSide) {
192
- throw new Error("CoValue not available");
193
- }
194
-
195
- expect(() => groupOnTheOtherSide.extend(parentGroupOnTheOtherSide)).toThrow(
196
- "To extend a group, the current account must have admin role in both groups",
197
- );
198
- });
199
-
200
- test("Group inheritance should work if the current account has admin role in both groups", async () => {
201
- const me = await Account.create({
202
- creationProps: { name: "Hermes Puggington" },
203
- crypto: Crypto,
204
- });
205
-
206
- const other = await Account.createAs(me, {
207
- creationProps: { name: "Another user" },
208
- });
209
-
210
- const parentGroup = Group.create({ owner: me });
211
- parentGroup.addMember(other, "admin");
212
- const group = Group.create({ owner: me });
213
- group.addMember(other, "admin");
214
-
215
- const parentGroupOnTheOtherSide = await Group.load(
216
- parentGroup.id,
217
- other,
218
- {},
219
- );
220
- const groupOnTheOtherSide = await Group.load(group.id, other, {});
221
-
222
- if (!groupOnTheOtherSide || !parentGroupOnTheOtherSide) {
223
- throw new Error("CoValue not available");
224
- }
225
-
226
- expect(() =>
227
- groupOnTheOtherSide.extend(parentGroupOnTheOtherSide),
228
- ).not.toThrow();
229
- });
230
-
231
169
  test("waitForSync should resolve when the value is uploaded", async () => {
232
170
  const { clientNode, serverNode, clientAccount } = await setupTwoNodes();
233
171
 
@@ -51,6 +51,49 @@ describe("Inbox", () => {
51
51
  unsubscribe();
52
52
  });
53
53
 
54
+ it("should work with empty CoMaps", async () => {
55
+ const { clientAccount: sender, serverAccount: receiver } =
56
+ await setupTwoNodes();
57
+
58
+ class EmptyMessage extends CoMap {}
59
+
60
+ const receiverInbox = await Inbox.load(receiver);
61
+
62
+ // Create a message from sender
63
+ const message = EmptyMessage.create(
64
+ {},
65
+ {
66
+ owner: Group.create({ owner: sender }),
67
+ },
68
+ );
69
+
70
+ // Setup inbox sender
71
+ const inboxSender = await InboxSender.load(receiver.id, sender);
72
+ inboxSender.sendMessage(message);
73
+
74
+ // Track received messages
75
+ const receivedMessages: EmptyMessage[] = [];
76
+ let senderAccountID: unknown = undefined;
77
+
78
+ // Subscribe to inbox messages
79
+ const unsubscribe = receiverInbox.subscribe(
80
+ EmptyMessage,
81
+ async (message, id) => {
82
+ senderAccountID = id;
83
+ receivedMessages.push(message);
84
+ },
85
+ );
86
+
87
+ // Wait for message to be received
88
+ await waitFor(() => receivedMessages.length === 1);
89
+
90
+ expect(receivedMessages.length).toBe(1);
91
+ expect(receivedMessages[0]?.id).toBe(message.id);
92
+ expect(senderAccountID).toBe(sender.id);
93
+
94
+ unsubscribe();
95
+ });
96
+
54
97
  it("should return the result of the message", async () => {
55
98
  const { clientAccount: sender, serverAccount: receiver } =
56
99
  await setupTwoNodes();
@@ -59,7 +59,7 @@ export async function setupTwoNodes() {
59
59
  fromRaw: rawAccount,
60
60
  });
61
61
 
62
- await account.migrate?.(creationProps);
62
+ await account.applyMigration(creationProps);
63
63
  },
64
64
  });
65
65
 
@@ -72,7 +72,7 @@ export async function setupTwoNodes() {
72
72
  fromRaw: rawAccount,
73
73
  });
74
74
 
75
- await account.migrate?.(creationProps);
75
+ await account.applyMigration(creationProps);
76
76
  },
77
77
  });
78
78