jazz-tools 0.13.18 → 0.13.19

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/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  parseInviteLink,
35
35
  randomSessionProvider,
36
36
  subscribeToCoValue
37
- } from "./chunk-ITSHLDQB.js";
37
+ } from "./chunk-4HBHY4I7.js";
38
38
 
39
39
  // src/index.ts
40
40
  import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals } from "cojson";
@@ -19,6 +19,7 @@ export declare class SubscriptionScope<D extends CoValue> {
19
19
  resolve: RefsToResolve<any>;
20
20
  idsSubscribed: Set<string>;
21
21
  autoloaded: Set<string>;
22
+ autoloadedKeys: Set<string>;
22
23
  totalValidTransactions: number;
23
24
  silenceUpdates: boolean;
24
25
  constructor(node: LocalNode, resolve: RefsToResolve<D>, id: ID<D>, schema: RefEncoded<D>);
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionScope.d.ts","sourceRoot":"","sources":["../../src/subscribe/SubscriptionScope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAU,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,EAAE,EACP,KAAK,UAAU,EACf,KAAK,aAAa,EAEnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG9D,qBAAa,iBAAiB,CAAC,CAAC,SAAS,OAAO;IAoBrC,IAAI,EAAE,SAAS;IAEf,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACT,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAtB9B,UAAU,0CAAiD;IAC3D,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,CAG5D;IACJ,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC;IAC5C,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAa;IAChD,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAa;IACrD,iBAAiB,EAAE,SAAS,GAAG,SAAS,CAAC;IACzC,YAAY,EAAE,uBAAuB,CAAC;IACtC,KAAK,UAAS;IACd,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,aAAa,cAAqB;IAClC,UAAU,cAAqB;IAC/B,sBAAsB,SAAK;IAE3B,cAAc,UAAS;gBAGd,IAAI,EAAE,SAAS,EACtB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAClB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EACT,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAS9B,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC;IAO5C,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa;IA0E/C,kBAAkB;IAyBlB,iBAAiB,OACX,MAAM,SACH,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,QAAQ,QACvC,MAAM,UA6BZ;IAEF,iBAAiB;IAiBjB,aAAa;IAkBb,WAAW,cAAmB,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,EAAI;IACpE,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI;IAQ9D,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI;IAKhE,cAAc,CAAC,GAAG,EAAE,MAAM;IA4C1B,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC;IA2BrD,YAAY;IA6GZ,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IA2CvE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAsC1E,aAAa,CACX,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,EAC3B,GAAG,CAAC,EAAE,MAAM;IAiBd,OAAO;CAKR"}
1
+ {"version":3,"file":"SubscriptionScope.d.ts","sourceRoot":"","sources":["../../src/subscribe/SubscriptionScope.ts"],"names":[],"mappings":"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"}
package/dist/testing.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  createAnonymousJazzContext,
6
6
  createJazzContext,
7
7
  randomSessionProvider
8
- } from "./chunk-ITSHLDQB.js";
8
+ } from "./chunk-4HBHY4I7.js";
9
9
 
10
10
  // src/testing.ts
11
11
  import { LocalNode } from "cojson";
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "type": "module",
19
19
  "license": "MIT",
20
- "version": "0.13.18",
20
+ "version": "0.13.19",
21
21
  "dependencies": {
22
22
  "@scure/bip39": "^1.3.0",
23
23
  "fast-myers-diff": "^3.2.0",
@@ -27,6 +27,7 @@ export class SubscriptionScope<D extends CoValue> {
27
27
  resolve: RefsToResolve<any>;
28
28
  idsSubscribed = new Set<string>();
29
29
  autoloaded = new Set<string>();
30
+ autoloadedKeys = new Set<string>();
30
31
  totalValidTransactions = 0;
31
32
 
32
33
  silenceUpdates = false;
@@ -133,7 +134,12 @@ export class SubscriptionScope<D extends CoValue> {
133
134
  return undefined;
134
135
  }
135
136
 
136
- for (const value of this.childErrors.values()) {
137
+ for (const [key, value] of this.childErrors.entries()) {
138
+ // We don't want to block updates if the error is on an autoloaded value
139
+ if (this.autoloaded.has(key)) {
140
+ continue;
141
+ }
142
+
137
143
  errorType = value.type;
138
144
  if (value.issues) {
139
145
  issues.push(...value.issues);
@@ -147,7 +153,11 @@ export class SubscriptionScope<D extends CoValue> {
147
153
  }
148
154
  }
149
155
 
150
- return new JazzError(this.id, errorType, issues);
156
+ if (issues.length) {
157
+ return new JazzError(this.id, errorType, issues);
158
+ }
159
+
160
+ return undefined;
151
161
  }
152
162
 
153
163
  handleChildUpdate = (
@@ -242,7 +252,10 @@ export class SubscriptionScope<D extends CoValue> {
242
252
  return;
243
253
  }
244
254
 
255
+ // Adding the key to the resolve object to resolve the key when calling loadChildren
245
256
  this.resolve[key as keyof typeof this.resolve] = true;
257
+ // Track the keys that are autoloaded to flag any id on that key as autoloaded
258
+ this.autoloadedKeys.add(key);
246
259
 
247
260
  if (this.value.type !== "loaded") {
248
261
  return;
@@ -259,19 +272,11 @@ export class SubscriptionScope<D extends CoValue> {
259
272
  if (value._type === "CoMap" || value._type === "Account") {
260
273
  const map = value as CoMap;
261
274
 
262
- const id = this.loadCoMapKey(map, key, true);
263
-
264
- if (id) {
265
- this.autoloaded.add(id);
266
- }
275
+ this.loadCoMapKey(map, key, true);
267
276
  } else if (value._type === "CoList") {
268
277
  const list = value as CoList;
269
278
 
270
- const id = this.loadCoListKey(list, key, true);
271
-
272
- if (id) {
273
- this.autoloaded.add(id);
274
- }
279
+ this.loadCoListKey(list, key, true);
275
280
  }
276
281
 
277
282
  this.silenceUpdates = false;
@@ -504,10 +509,18 @@ export class SubscriptionScope<D extends CoValue> {
504
509
  return;
505
510
  }
506
511
 
512
+ if (key && this.autoloadedKeys.has(key)) {
513
+ this.autoloaded.add(id);
514
+ }
515
+
516
+ // Cloning the resolve objects to avoid mutating the original object when tracking autoloaded values
517
+ const resolve =
518
+ typeof query === "object" && query !== null ? { ...query } : query;
519
+
507
520
  this.childValues.set(id, { type: "unloaded", id });
508
521
  const child = new SubscriptionScope(
509
522
  this.node,
510
- query,
523
+ resolve,
511
524
  id as ID<any>,
512
525
  descriptor,
513
526
  );
@@ -937,6 +937,263 @@ describe("subscribeToCoValue", () => {
937
937
  expect(value?.name).toBe("writer2");
938
938
  expect(value?._raw.totalValidTransactions).toBe(2);
939
939
  });
940
+
941
+ it("errors on autoloaded values shouldn't block updates", async () => {
942
+ class TestMap extends CoMap {
943
+ value = co.string;
944
+ }
945
+
946
+ class TestList extends CoList.Of(co.ref(TestMap)) {}
947
+
948
+ const reader = await createJazzTestAccount({
949
+ isCurrentActiveAccount: true,
950
+ });
951
+
952
+ const creator = await createJazzTestAccount({
953
+ isCurrentActiveAccount: true,
954
+ });
955
+
956
+ const everyone = Group.create(creator);
957
+ everyone.addMember("everyone", "reader");
958
+
959
+ const group = Group.create(creator);
960
+
961
+ const list = TestList.create(
962
+ [
963
+ TestMap.create({ value: "1" }, group),
964
+ TestMap.create({ value: "2" }, everyone),
965
+ TestMap.create({ value: "3" }, everyone),
966
+ TestMap.create({ value: "4" }, everyone),
967
+ TestMap.create({ value: "5" }, everyone),
968
+ ],
969
+ everyone,
970
+ );
971
+
972
+ let result = null as Resolved<TestList, { $each: true }> | null;
973
+
974
+ const updateFn = vi.fn().mockImplementation((value) => {
975
+ result = value;
976
+ });
977
+ const onUnauthorized = vi.fn();
978
+ const onUnavailable = vi.fn();
979
+
980
+ const unsubscribe = subscribeToCoValue(
981
+ TestList,
982
+ list.id,
983
+ {
984
+ loadAs: reader,
985
+ resolve: true,
986
+ onUnauthorized,
987
+ onUnavailable,
988
+ },
989
+ updateFn,
990
+ );
991
+
992
+ onTestFinished(unsubscribe);
993
+
994
+ await waitFor(() => {
995
+ expect(updateFn).toHaveBeenCalled();
996
+ });
997
+
998
+ await waitFor(() => {
999
+ assert(result);
1000
+ expect(result[1]?.value).toBe("2");
1001
+ });
1002
+
1003
+ assert(result);
1004
+ expect(result[0]).toBe(null);
1005
+
1006
+ updateFn.mockClear();
1007
+
1008
+ list[1] = TestMap.create({ value: "updated" }, everyone);
1009
+
1010
+ await waitFor(() => {
1011
+ expect(result?.[1]?.value).toBe("updated");
1012
+ });
1013
+
1014
+ expect(onUnavailable).not.toHaveBeenCalled();
1015
+ expect(onUnauthorized).not.toHaveBeenCalled();
1016
+ });
1017
+
1018
+ it("errors on autoloaded values shouldn't block updates, even when the error comes from a new ref", async () => {
1019
+ class Dog extends CoMap {
1020
+ name = co.string;
1021
+ }
1022
+
1023
+ class Person extends CoMap {
1024
+ name = co.string;
1025
+ dog = co.ref(Dog);
1026
+ }
1027
+
1028
+ class PersonList extends CoList.Of(co.ref(Person)) {}
1029
+
1030
+ const reader = await createJazzTestAccount({
1031
+ isCurrentActiveAccount: true,
1032
+ });
1033
+
1034
+ const creator = await createJazzTestAccount({
1035
+ isCurrentActiveAccount: true,
1036
+ });
1037
+
1038
+ const everyone = Group.create(creator);
1039
+ everyone.addMember("everyone", "reader");
1040
+
1041
+ const list = PersonList.create(
1042
+ [
1043
+ Person.create(
1044
+ { name: "Guido", dog: Dog.create({ name: "Giggino" }, everyone) },
1045
+ everyone,
1046
+ ),
1047
+ Person.create(
1048
+ { name: "John", dog: Dog.create({ name: "Rex" }, everyone) },
1049
+ everyone,
1050
+ ),
1051
+ Person.create(
1052
+ { name: "Jane", dog: Dog.create({ name: "Bella" }, everyone) },
1053
+ everyone,
1054
+ ),
1055
+ ],
1056
+ everyone,
1057
+ );
1058
+
1059
+ let result = null as Resolved<PersonList, { $each: true }> | null;
1060
+
1061
+ const updateFn = vi.fn().mockImplementation((value) => {
1062
+ result = value;
1063
+ });
1064
+ const onUnauthorized = vi.fn();
1065
+ const onUnavailable = vi.fn();
1066
+
1067
+ const unsubscribe = subscribeToCoValue(
1068
+ PersonList,
1069
+ list.id,
1070
+ {
1071
+ loadAs: reader,
1072
+ resolve: {
1073
+ $each: true,
1074
+ },
1075
+ onUnauthorized,
1076
+ onUnavailable,
1077
+ },
1078
+ updateFn,
1079
+ );
1080
+
1081
+ onTestFinished(unsubscribe);
1082
+
1083
+ await waitFor(() => {
1084
+ expect(result?.[0]?.name).toBe("Guido");
1085
+ expect(result?.[0]?.dog?.name).toBe("Giggino");
1086
+ });
1087
+
1088
+ await waitFor(() => {
1089
+ expect(result?.[1]?.name).toBe("John");
1090
+ expect(result?.[1]?.dog?.name).toBe("Rex");
1091
+ });
1092
+
1093
+ await waitFor(() => {
1094
+ expect(result?.[2]?.name).toBe("Jane");
1095
+ expect(result?.[2]?.dog?.name).toBe("Bella");
1096
+ });
1097
+
1098
+ list[0]!.dog = Dog.create({ name: "Ninja" });
1099
+
1100
+ await waitFor(() => {
1101
+ expect(result?.[0]?.dog).toBe(null);
1102
+ });
1103
+
1104
+ list[1]!.dog = Dog.create({ name: "Pinkie" }, everyone);
1105
+
1106
+ await waitFor(() => {
1107
+ expect(result?.[1]?.dog?.name).toBe("Pinkie");
1108
+ });
1109
+
1110
+ expect(onUnavailable).not.toHaveBeenCalled();
1111
+ expect(onUnauthorized).not.toHaveBeenCalled();
1112
+ });
1113
+
1114
+ it("autoload on $each resolve should work on all items", async () => {
1115
+ class Dog extends CoMap {
1116
+ name = co.string;
1117
+ }
1118
+
1119
+ class Person extends CoMap {
1120
+ name = co.string;
1121
+ dog = co.ref(Dog);
1122
+ }
1123
+
1124
+ class PersonList extends CoList.Of(co.ref(Person)) {}
1125
+
1126
+ const reader = await createJazzTestAccount({
1127
+ isCurrentActiveAccount: true,
1128
+ });
1129
+
1130
+ const creator = await createJazzTestAccount({
1131
+ isCurrentActiveAccount: true,
1132
+ });
1133
+
1134
+ const everyone = Group.create(creator);
1135
+ everyone.addMember("everyone", "reader");
1136
+
1137
+ const list = PersonList.create(
1138
+ [
1139
+ Person.create(
1140
+ { name: "Guido", dog: Dog.create({ name: "Giggino" }, everyone) },
1141
+ everyone,
1142
+ ),
1143
+ Person.create(
1144
+ { name: "John", dog: Dog.create({ name: "Rex" }, everyone) },
1145
+ everyone,
1146
+ ),
1147
+ Person.create(
1148
+ { name: "Jane", dog: Dog.create({ name: "Bella" }, everyone) },
1149
+ everyone,
1150
+ ),
1151
+ ],
1152
+ everyone,
1153
+ );
1154
+
1155
+ let result = null as Resolved<PersonList, { $each: true }> | null;
1156
+
1157
+ const updateFn = vi.fn().mockImplementation((value) => {
1158
+ result = value;
1159
+ });
1160
+ const onUnauthorized = vi.fn();
1161
+ const onUnavailable = vi.fn();
1162
+
1163
+ const unsubscribe = subscribeToCoValue(
1164
+ PersonList,
1165
+ list.id,
1166
+ {
1167
+ loadAs: reader,
1168
+ resolve: {
1169
+ $each: true,
1170
+ },
1171
+ onUnauthorized,
1172
+ onUnavailable,
1173
+ },
1174
+ updateFn,
1175
+ );
1176
+
1177
+ onTestFinished(unsubscribe);
1178
+
1179
+ await waitFor(() => {
1180
+ expect(result?.[0]?.name).toBe("Guido");
1181
+ expect(result?.[0]?.dog?.name).toBe("Giggino");
1182
+ });
1183
+
1184
+ await waitFor(() => {
1185
+ expect(result?.[1]?.name).toBe("John");
1186
+ expect(result?.[1]?.dog?.name).toBe("Rex");
1187
+ });
1188
+
1189
+ await waitFor(() => {
1190
+ expect(result?.[2]?.name).toBe("Jane");
1191
+ expect(result?.[2]?.dog?.name).toBe("Bella");
1192
+ });
1193
+
1194
+ expect(onUnavailable).not.toHaveBeenCalled();
1195
+ expect(onUnauthorized).not.toHaveBeenCalled();
1196
+ });
940
1197
  });
941
1198
 
942
1199
  describe("createCoValueObservable", () => {