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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +6 -0
- package/dist/{chunk-ITSHLDQB.js → chunk-4HBHY4I7.js} +18 -12
- package/dist/chunk-4HBHY4I7.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/subscribe/SubscriptionScope.d.ts +1 -0
- package/dist/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/package.json +1 -1
- package/src/subscribe/SubscriptionScope.ts +26 -13
- package/src/tests/subscribe.test.ts +257 -0
- package/dist/chunk-ITSHLDQB.js.map +0 -1
package/dist/index.js
CHANGED
@@ -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;
|
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;IAqBrC,IAAI,EAAE,SAAS;IAEf,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACT,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAvB9B,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,cAAc,cAAqB;IACnC,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;IAkClB,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;IAuC1B,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;IAyBd,OAAO;CAKR"}
|
package/dist/testing.js
CHANGED
package/package.json
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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", () => {
|