jazz-tools 0.13.30 → 0.14.0
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 +8 -8
- package/CHANGELOG.md +23 -3
- package/dist/auth/DemoAuth.d.ts.map +1 -1
- package/dist/auth/PassphraseAuth.d.ts +1 -3
- package/dist/auth/PassphraseAuth.d.ts.map +1 -1
- package/dist/{chunk-LMV6J7GN.js → chunk-2ASOGEYA.js} +3531 -3269
- package/dist/chunk-2ASOGEYA.js.map +1 -0
- package/dist/coValues/CoValueBase.d.ts +22 -0
- package/dist/coValues/CoValueBase.d.ts.map +1 -0
- package/dist/coValues/account.d.ts +12 -12
- package/dist/coValues/account.d.ts.map +1 -1
- package/dist/coValues/coFeed.d.ts +24 -25
- package/dist/coValues/coFeed.d.ts.map +1 -1
- package/dist/coValues/coList.d.ts +10 -13
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coMap.d.ts +32 -35
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/deepLoading.d.ts +28 -22
- package/dist/coValues/deepLoading.d.ts.map +1 -1
- package/dist/coValues/extensions/imageDef.d.ts +12 -11
- package/dist/coValues/extensions/imageDef.d.ts.map +1 -1
- package/dist/coValues/group.d.ts +5 -9
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/inbox.d.ts +2 -3
- package/dist/coValues/inbox.d.ts.map +1 -1
- package/dist/coValues/interfaces.d.ts +8 -34
- package/dist/coValues/interfaces.d.ts.map +1 -1
- package/dist/coValues/profile.d.ts +4 -14
- package/dist/coValues/profile.d.ts.map +1 -1
- package/dist/coValues/registeredSchemas.d.ts +1 -3
- package/dist/coValues/registeredSchemas.d.ts.map +1 -1
- package/dist/coValues/schemaUnion.d.ts +6 -6
- package/dist/exports.d.ts +12 -16
- package/dist/exports.d.ts.map +1 -1
- package/dist/implementation/ContextManager.d.ts +1 -1
- package/dist/implementation/ContextManager.d.ts.map +1 -1
- package/dist/implementation/activeAccountContext.d.ts +1 -1
- package/dist/implementation/activeAccountContext.d.ts.map +1 -1
- package/dist/implementation/createContext.d.ts +10 -10
- package/dist/implementation/createContext.d.ts.map +1 -1
- package/dist/implementation/invites.d.ts +6 -6
- package/dist/implementation/invites.d.ts.map +1 -1
- package/dist/implementation/refs.d.ts +2 -2
- package/dist/implementation/refs.d.ts.map +1 -1
- package/dist/implementation/schema.d.ts +21 -28
- package/dist/implementation/schema.d.ts.map +1 -1
- package/dist/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts +9 -0
- package/dist/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.d.ts.map +1 -0
- package/dist/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts +28 -0
- package/dist/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +65 -0
- package/dist/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +28 -0
- package/dist/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +24 -0
- package/dist/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +41 -0
- package/dist/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +35 -0
- package/dist/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +9 -0
- package/dist/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +20 -0
- package/dist/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +18 -0
- package/dist/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +24 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +21 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts +29 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts.map +1 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts +29 -0
- package/dist/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts.map +1 -0
- package/dist/implementation/zodSchema/unionUtils.d.ts +6 -0
- package/dist/implementation/zodSchema/unionUtils.d.ts.map +1 -0
- package/dist/implementation/zodSchema/zodCo.d.ts +35 -0
- package/dist/implementation/zodSchema/zodCo.d.ts.map +1 -0
- package/dist/implementation/zodSchema/zodSchema.d.ts +38 -0
- package/dist/implementation/zodSchema/zodSchema.d.ts.map +1 -0
- package/dist/index.js +295 -10
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +34 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/subscribe/SubscriptionScope.d.ts +2 -2
- package/dist/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/subscribe/utils.d.ts +2 -2
- package/dist/subscribe/utils.d.ts.map +1 -1
- package/dist/testing.d.ts +10 -8
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/tests/utils.d.ts +6 -2
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/types.d.ts +1 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/auth/DemoAuth.ts +1 -2
- package/src/auth/PassphraseAuth.ts +1 -1
- package/src/coValues/CoValueBase.ts +83 -0
- package/src/coValues/account.ts +53 -43
- package/src/coValues/coFeed.ts +65 -83
- package/src/coValues/coList.ts +28 -21
- package/src/coValues/coMap.ts +54 -38
- package/src/coValues/coPlainText.ts +4 -1
- package/src/coValues/deepLoading.ts +46 -36
- package/src/coValues/extensions/imageDef.ts +21 -19
- package/src/coValues/group.ts +37 -38
- package/src/coValues/inbox.ts +24 -11
- package/src/coValues/interfaces.ts +29 -93
- package/src/coValues/profile.ts +12 -13
- package/src/coValues/registeredSchemas.ts +1 -3
- package/src/coValues/schemaUnion.ts +6 -6
- package/src/exports.ts +47 -25
- package/src/implementation/activeAccountContext.ts +1 -1
- package/src/implementation/createContext.ts +39 -24
- package/src/implementation/invites.ts +15 -12
- package/src/implementation/refs.ts +6 -4
- package/src/implementation/schema.ts +22 -34
- package/src/implementation/zodSchema/runtimeConverters/zodFieldToCoFieldDef.ts +101 -0
- package/src/implementation/zodSchema/runtimeConverters/zodSchemaToCoSchema.ts +191 -0
- package/src/implementation/zodSchema/schemaTypes/AccountSchema.ts +102 -0
- package/src/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +70 -0
- package/src/implementation/zodSchema/schemaTypes/CoListSchema.ts +59 -0
- package/src/implementation/zodSchema/schemaTypes/CoMapSchema.ts +126 -0
- package/src/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +98 -0
- package/src/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +9 -0
- package/src/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +27 -0
- package/src/implementation/zodSchema/schemaTypes/RichTextSchema.ts +25 -0
- package/src/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +61 -0
- package/src/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +77 -0
- package/src/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.ts +90 -0
- package/src/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.ts +103 -0
- package/src/implementation/zodSchema/unionUtils.ts +139 -0
- package/src/implementation/zodSchema/zodCo.ts +409 -0
- package/src/implementation/zodSchema/zodSchema.ts +116 -0
- package/src/internal.ts +38 -0
- package/src/subscribe/SubscriptionScope.ts +30 -3
- package/src/subscribe/utils.ts +7 -2
- package/src/testing.ts +14 -16
- package/src/tests/ContextManager.test.ts +73 -47
- package/src/tests/DemoAuth.test.ts +1 -1
- package/src/tests/account.test.ts +6 -9
- package/src/tests/coFeed.test.ts +102 -63
- package/src/tests/coList.test.ts +82 -95
- package/src/tests/coMap.record.test.ts +53 -87
- package/src/tests/coMap.test.ts +297 -312
- package/src/tests/coPlainText.test.ts +19 -39
- package/src/tests/createContext.test.ts +33 -15
- package/src/tests/deepLoading.test.ts +397 -131
- package/src/tests/groupsAndAccounts.test.ts +81 -72
- package/src/tests/imageDef.test.ts +22 -13
- package/src/tests/inbox.test.ts +36 -29
- package/src/tests/load.test.ts +10 -10
- package/src/tests/patterns/requestToJoin.test.ts +31 -31
- package/src/tests/schema.test.ts +37 -38
- package/src/tests/schemaUnion.test.ts +54 -64
- package/src/tests/subscribe.test.ts +118 -116
- package/src/tests/testing.test.ts +33 -33
- package/src/tests/utils.ts +3 -2
- package/src/types.ts +1 -8
- package/dist/chunk-LMV6J7GN.js.map +0 -1
@@ -1,42 +1,43 @@
|
|
1
|
-
import { cojsonInternals } from "cojson";
|
1
|
+
import { Profile, cojsonInternals } from "cojson";
|
2
2
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
3
3
|
import { assert, describe, expect, expectTypeOf, test, vi } from "vitest";
|
4
4
|
import {
|
5
|
-
Account,
|
6
|
-
CoFeed,
|
7
|
-
CoList,
|
8
|
-
CoMap,
|
9
5
|
Group,
|
10
6
|
ID,
|
11
|
-
Profile,
|
12
7
|
SessionID,
|
13
|
-
co,
|
14
8
|
createJazzContextFromExistingCredentials,
|
15
9
|
isControlledAccount,
|
10
|
+
z,
|
16
11
|
} from "../index.js";
|
17
|
-
import {
|
12
|
+
import {
|
13
|
+
Account,
|
14
|
+
CoListSchema,
|
15
|
+
Loaded,
|
16
|
+
co,
|
17
|
+
randomSessionProvider,
|
18
|
+
} from "../internal.js";
|
18
19
|
import { createJazzTestAccount, linkAccounts } from "../testing.js";
|
19
20
|
import { waitFor } from "./utils.js";
|
20
21
|
|
21
22
|
const Crypto = await WasmCrypto.create();
|
22
23
|
const { connectedPeers } = cojsonInternals;
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
25
|
+
const InnermostMap = co.map({
|
26
|
+
value: z.string(),
|
27
|
+
});
|
28
28
|
|
29
|
-
|
29
|
+
const TestFeed = co.feed(InnermostMap);
|
30
30
|
|
31
|
-
|
32
|
-
stream
|
33
|
-
}
|
31
|
+
const InnerMap = co.map({
|
32
|
+
stream: TestFeed,
|
33
|
+
});
|
34
34
|
|
35
|
-
|
35
|
+
const TestList = co.list(InnerMap);
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
const TestMap = co.map({
|
38
|
+
list: TestList,
|
39
|
+
optionalRef: z.optional(InnermostMap),
|
40
|
+
});
|
40
41
|
|
41
42
|
describe("Deep loading with depth arg", async () => {
|
42
43
|
const me = await Account.create({
|
@@ -71,7 +72,7 @@ describe("Deep loading with depth arg", async () => {
|
|
71
72
|
[
|
72
73
|
InnerMap.create(
|
73
74
|
{
|
74
|
-
stream:
|
75
|
+
stream: TestFeed.create(
|
75
76
|
[InnermostMap.create({ value: "hello" }, ownership)],
|
76
77
|
ownership,
|
77
78
|
),
|
@@ -87,7 +88,7 @@ describe("Deep loading with depth arg", async () => {
|
|
87
88
|
|
88
89
|
test("load without resolve", async () => {
|
89
90
|
const map1 = await TestMap.load(map.id, { loadAs: meOnSecondPeer });
|
90
|
-
expectTypeOf(map1).toEqualTypeOf<TestMap | null>();
|
91
|
+
expectTypeOf(map1).branded.toEqualTypeOf<Loaded<typeof TestMap> | null>();
|
91
92
|
|
92
93
|
assert(map1, "map1 is null");
|
93
94
|
|
@@ -99,9 +100,9 @@ describe("Deep loading with depth arg", async () => {
|
|
99
100
|
loadAs: meOnSecondPeer,
|
100
101
|
resolve: { list: true },
|
101
102
|
});
|
102
|
-
expectTypeOf(map2).toEqualTypeOf<
|
103
|
-
| (TestMap & {
|
104
|
-
list: TestList
|
103
|
+
expectTypeOf(map2).branded.toEqualTypeOf<
|
104
|
+
| (Loaded<typeof TestMap> & {
|
105
|
+
list: Loaded<typeof TestList>;
|
105
106
|
})
|
106
107
|
| null
|
107
108
|
>();
|
@@ -115,9 +116,9 @@ describe("Deep loading with depth arg", async () => {
|
|
115
116
|
loadAs: meOnSecondPeer,
|
116
117
|
resolve: { list: { $each: true } },
|
117
118
|
});
|
118
|
-
expectTypeOf(map3).toEqualTypeOf<
|
119
|
-
| (TestMap & {
|
120
|
-
list: TestList & InnerMap[];
|
119
|
+
expectTypeOf(map3).branded.toEqualTypeOf<
|
120
|
+
| (Loaded<typeof TestMap> & {
|
121
|
+
list: Loaded<typeof TestList> & Loaded<typeof InnerMap>[];
|
121
122
|
})
|
122
123
|
| null
|
123
124
|
>();
|
@@ -131,9 +132,9 @@ describe("Deep loading with depth arg", async () => {
|
|
131
132
|
loadAs: meOnSecondPeer,
|
132
133
|
resolve: { optionalRef: true } as const,
|
133
134
|
});
|
134
|
-
expectTypeOf(map3a).toEqualTypeOf<
|
135
|
-
| (TestMap & {
|
136
|
-
optionalRef: InnermostMap | undefined;
|
135
|
+
expectTypeOf(map3a).branded.toEqualTypeOf<
|
136
|
+
| (Loaded<typeof TestMap> & {
|
137
|
+
optionalRef: Loaded<typeof InnermostMap> | undefined;
|
137
138
|
})
|
138
139
|
| null
|
139
140
|
>();
|
@@ -146,15 +147,16 @@ describe("Deep loading with depth arg", async () => {
|
|
146
147
|
loadAs: meOnSecondPeer,
|
147
148
|
resolve: { list: { $each: { stream: true } } },
|
148
149
|
});
|
149
|
-
expectTypeOf(map4).toEqualTypeOf<
|
150
|
-
| (TestMap & {
|
151
|
-
list: TestList &
|
150
|
+
expectTypeOf(map4).branded.toEqualTypeOf<
|
151
|
+
| (Loaded<typeof TestMap> & {
|
152
|
+
list: Loaded<typeof TestList> &
|
153
|
+
(Loaded<typeof InnerMap> & { stream: Loaded<typeof TestFeed> })[];
|
152
154
|
})
|
153
155
|
| null
|
154
156
|
>();
|
155
157
|
assert(map4, "map4 is null");
|
156
158
|
expect(map4.list[0]?.stream).toBeTruthy();
|
157
|
-
expect(map4.list[0]?.stream?.[me.id]).toBeTruthy();
|
159
|
+
expect(map4.list[0]?.stream?.perAccount[me.id]).toBeTruthy();
|
158
160
|
expect(map4.list[0]?.stream?.byMe?.value).toBe(null);
|
159
161
|
});
|
160
162
|
|
@@ -164,73 +166,76 @@ describe("Deep loading with depth arg", async () => {
|
|
164
166
|
resolve: { list: { $each: { stream: { $each: true } } } },
|
165
167
|
});
|
166
168
|
type ExpectedMap5 =
|
167
|
-
| (TestMap & {
|
168
|
-
list: TestList &
|
169
|
-
(InnerMap & {
|
170
|
-
stream:
|
171
|
-
byMe?: { value: InnermostMap };
|
172
|
-
inCurrentSession?: { value: InnermostMap };
|
169
|
+
| (Loaded<typeof TestMap> & {
|
170
|
+
list: Loaded<typeof TestList> &
|
171
|
+
(Loaded<typeof InnerMap> & {
|
172
|
+
stream: Loaded<typeof TestFeed> & {
|
173
|
+
byMe?: { value: Loaded<typeof InnermostMap> };
|
174
|
+
inCurrentSession?: { value: Loaded<typeof InnermostMap> };
|
173
175
|
perSession: {
|
174
176
|
[sessionID: SessionID]: {
|
175
|
-
value: InnermostMap
|
177
|
+
value: Loaded<typeof InnermostMap>;
|
176
178
|
};
|
177
179
|
};
|
178
180
|
} & {
|
179
|
-
[key: ID<Account>]: { value: InnermostMap };
|
181
|
+
[key: ID<Account>]: { value: Loaded<typeof InnermostMap> };
|
180
182
|
};
|
181
183
|
})[];
|
182
184
|
})
|
183
185
|
| null;
|
184
|
-
expectTypeOf(map5).toEqualTypeOf<ExpectedMap5>();
|
186
|
+
expectTypeOf(map5).branded.toEqualTypeOf<ExpectedMap5>();
|
185
187
|
assert(map5, "map5 is null");
|
186
188
|
|
187
|
-
expect(map5.list[0]?.stream?.[me.id]?.value).toBeTruthy();
|
189
|
+
expect(map5.list[0]?.stream?.perAccount[me.id]?.value).toBeTruthy();
|
188
190
|
expect(map5.list[0]?.stream?.byMe?.value).toBeTruthy();
|
189
191
|
});
|
190
192
|
});
|
191
193
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
class CustomAccount extends Account {
|
197
|
-
profile = co.ref(CustomProfile);
|
198
|
-
root = co.ref(TestMap);
|
194
|
+
const CustomProfile = co.profile({
|
195
|
+
name: z.string(),
|
196
|
+
stream: TestFeed,
|
197
|
+
});
|
199
198
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
199
|
+
const CustomAccount = co
|
200
|
+
.account({
|
201
|
+
profile: CustomProfile,
|
202
|
+
root: TestMap,
|
203
|
+
})
|
204
|
+
.withMigration(async (account, creationProps) => {
|
204
205
|
if (creationProps) {
|
205
|
-
const profileGroup = Group.create(
|
206
|
-
|
206
|
+
const profileGroup = Group.create(account);
|
207
|
+
account.profile = CustomProfile.create(
|
207
208
|
{
|
208
209
|
name: creationProps.name,
|
209
|
-
stream:
|
210
|
+
stream: TestFeed.create([], account),
|
210
211
|
},
|
211
212
|
profileGroup,
|
212
213
|
);
|
213
|
-
|
214
|
+
account.root = TestMap.create(
|
215
|
+
{ list: TestList.create([], account) },
|
216
|
+
account,
|
217
|
+
);
|
214
218
|
}
|
215
219
|
|
216
|
-
const
|
220
|
+
const accountLoaded = await account.ensureLoaded({
|
217
221
|
resolve: {
|
218
222
|
profile: { stream: true },
|
219
223
|
root: { list: true },
|
220
224
|
},
|
221
225
|
});
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
226
|
+
|
227
|
+
// using assignment to check type compatibility
|
228
|
+
const _T:
|
229
|
+
| (Loaded<typeof CustomAccount> & {
|
230
|
+
profile: Loaded<typeof CustomProfile> & {
|
231
|
+
stream: Loaded<typeof TestFeed>;
|
232
|
+
};
|
233
|
+
root: Loaded<typeof TestMap> & {
|
234
|
+
list: Loaded<typeof TestList>;
|
235
|
+
};
|
236
|
+
})
|
237
|
+
| null = accountLoaded;
|
238
|
+
});
|
234
239
|
|
235
240
|
test("Deep loading within account", async () => {
|
236
241
|
const me = await CustomAccount.create({
|
@@ -244,22 +249,24 @@ test("Deep loading within account", async () => {
|
|
244
249
|
root: { list: true },
|
245
250
|
},
|
246
251
|
});
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
252
|
+
|
253
|
+
// using assignment to check type compatibility
|
254
|
+
const _T:
|
255
|
+
| (Loaded<typeof CustomAccount> & {
|
256
|
+
profile: Loaded<typeof CustomProfile> & {
|
257
|
+
stream: Loaded<typeof TestFeed>;
|
258
|
+
};
|
259
|
+
root: Loaded<typeof TestMap> & {
|
260
|
+
list: Loaded<typeof TestList>;
|
261
|
+
};
|
262
|
+
})
|
263
|
+
| null = meLoaded;
|
257
264
|
|
258
265
|
expect(meLoaded.profile.stream).toBeTruthy();
|
259
266
|
expect(meLoaded.root.list).toBeTruthy();
|
260
267
|
});
|
261
268
|
|
262
|
-
|
269
|
+
const RecordLike = co.record(z.string(), TestMap);
|
263
270
|
|
264
271
|
test("Deep loading a record-like coMap", async () => {
|
265
272
|
const me = await Account.create({
|
@@ -309,9 +316,9 @@ test("Deep loading a record-like coMap", async () => {
|
|
309
316
|
},
|
310
317
|
});
|
311
318
|
expectTypeOf(recordLoaded).toEqualTypeOf<
|
312
|
-
| (RecordLike & {
|
313
|
-
[key: string]: TestMap & {
|
314
|
-
list: TestList & InnerMap[];
|
319
|
+
| (Loaded<typeof RecordLike> & {
|
320
|
+
[key: string]: Loaded<typeof TestMap> & {
|
321
|
+
list: Loaded<typeof TestList> & Loaded<typeof InnerMap>[];
|
315
322
|
};
|
316
323
|
})
|
317
324
|
| null
|
@@ -356,18 +363,19 @@ test("The resolve type doesn't accept extra keys", async () => {
|
|
356
363
|
},
|
357
364
|
});
|
358
365
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
366
|
+
// using assignment to check type compatibility
|
367
|
+
const _T:
|
368
|
+
| (Loaded<typeof CustomAccount> & {
|
369
|
+
profile: Loaded<typeof CustomProfile> & {
|
370
|
+
stream: Loaded<typeof TestFeed>;
|
371
|
+
extraKey: never;
|
372
|
+
};
|
373
|
+
root: Loaded<typeof TestMap> & {
|
374
|
+
list: Loaded<typeof TestList>;
|
375
|
+
extraKey: never;
|
376
|
+
};
|
377
|
+
})
|
378
|
+
| null = meLoaded;
|
371
379
|
} catch (e) {
|
372
380
|
expect(e).toBeInstanceOf(Error);
|
373
381
|
}
|
@@ -438,7 +446,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
438
446
|
[
|
439
447
|
InnerMap.create(
|
440
448
|
{
|
441
|
-
stream:
|
449
|
+
stream: TestFeed.create([], group),
|
442
450
|
},
|
443
451
|
onlyBob,
|
444
452
|
),
|
@@ -524,7 +532,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
524
532
|
[
|
525
533
|
InnerMap.create(
|
526
534
|
{
|
527
|
-
stream:
|
535
|
+
stream: TestFeed.create([], onlyBob),
|
528
536
|
},
|
529
537
|
group,
|
530
538
|
),
|
@@ -560,7 +568,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
560
568
|
[
|
561
569
|
InnerMap.create(
|
562
570
|
{
|
563
|
-
stream:
|
571
|
+
stream: TestFeed.create([value], group),
|
564
572
|
},
|
565
573
|
group,
|
566
574
|
),
|
@@ -585,25 +593,25 @@ describe("Deep loading with unauthorized account", async () => {
|
|
585
593
|
errorSpy.mockReset();
|
586
594
|
});
|
587
595
|
|
588
|
-
test("setting
|
589
|
-
|
590
|
-
|
591
|
-
}
|
596
|
+
test("setting undefined via proxy", async () => {
|
597
|
+
const Lv3 = co.map({
|
598
|
+
string: z.string(),
|
599
|
+
});
|
592
600
|
|
593
|
-
|
594
|
-
lv3
|
595
|
-
}
|
601
|
+
const Lv2 = co.map({
|
602
|
+
lv3: z.optional(Lv3),
|
603
|
+
});
|
596
604
|
|
597
|
-
|
598
|
-
|
599
|
-
}
|
605
|
+
const Lv1 = co.map({
|
606
|
+
lv2: Lv2,
|
607
|
+
});
|
600
608
|
|
601
609
|
const map = Lv1.create(
|
602
610
|
{ lv2: Lv2.create({ lv3: Lv3.create({ string: "hello" }, bob) }, bob) },
|
603
611
|
bob,
|
604
612
|
);
|
605
613
|
|
606
|
-
map.lv2!.lv3 =
|
614
|
+
map.lv2!.lv3 = undefined;
|
607
615
|
|
608
616
|
const loadedMap = await Lv1.load(map.id, {
|
609
617
|
resolve: { lv2: { lv3: true } },
|
@@ -612,18 +620,273 @@ describe("Deep loading with unauthorized account", async () => {
|
|
612
620
|
|
613
621
|
expect(loadedMap?.id).toBe(map.id);
|
614
622
|
});
|
623
|
+
|
624
|
+
test("unaccessible record element with $onError", async () => {
|
625
|
+
const Person = co.map({
|
626
|
+
name: z.string(),
|
627
|
+
});
|
628
|
+
const Friends = co.record(z.string(), Person);
|
629
|
+
|
630
|
+
const map = Friends.create(
|
631
|
+
{
|
632
|
+
jane: Person.create({ name: "Jane" }, onlyBob),
|
633
|
+
alice: Person.create({ name: "Alice" }, group),
|
634
|
+
},
|
635
|
+
group,
|
636
|
+
);
|
637
|
+
|
638
|
+
const friendsOnAlice = await Friends.load(map.id, {
|
639
|
+
resolve: { $each: { $onError: null } },
|
640
|
+
loadAs: alice,
|
641
|
+
});
|
642
|
+
|
643
|
+
assert(friendsOnAlice, "friendsOnAlice is null");
|
644
|
+
|
645
|
+
expect(friendsOnAlice.jane).toBeNull();
|
646
|
+
expect(friendsOnAlice.alice).not.toBeNull();
|
647
|
+
});
|
648
|
+
|
649
|
+
test("unaccessible nested record element with $onError", async () => {
|
650
|
+
const Person = co.map({
|
651
|
+
name: z.string(),
|
652
|
+
});
|
653
|
+
const Friends = co.record(z.string(), Person);
|
654
|
+
|
655
|
+
const User = co.map({
|
656
|
+
name: z.string(),
|
657
|
+
friends: Friends,
|
658
|
+
});
|
659
|
+
|
660
|
+
const map = User.create(
|
661
|
+
{
|
662
|
+
name: "John",
|
663
|
+
friends: Friends.create(
|
664
|
+
{
|
665
|
+
jane: Person.create({ name: "Jane" }, onlyBob),
|
666
|
+
alice: Person.create({ name: "Alice" }, group),
|
667
|
+
},
|
668
|
+
group,
|
669
|
+
),
|
670
|
+
},
|
671
|
+
group,
|
672
|
+
);
|
673
|
+
|
674
|
+
const user = await User.load(map.id, {
|
675
|
+
resolve: { friends: { $each: { $onError: null } } },
|
676
|
+
loadAs: alice,
|
677
|
+
});
|
678
|
+
|
679
|
+
assert(user, "user is null");
|
680
|
+
|
681
|
+
expect(user.friends.jane).toBeNull();
|
682
|
+
expect(user.friends.alice).not.toBeNull();
|
683
|
+
});
|
684
|
+
|
685
|
+
test("unaccessible element down the chain with $onError on a record", async () => {
|
686
|
+
const Dog = co.map({
|
687
|
+
name: z.string(),
|
688
|
+
});
|
689
|
+
|
690
|
+
const Person = co.map({
|
691
|
+
name: z.string(),
|
692
|
+
dog: Dog,
|
693
|
+
});
|
694
|
+
|
695
|
+
const Friends = co.record(z.string(), Person);
|
696
|
+
|
697
|
+
const User = co.map({
|
698
|
+
name: z.string(),
|
699
|
+
friends: Friends,
|
700
|
+
});
|
701
|
+
|
702
|
+
const map = User.create(
|
703
|
+
{
|
704
|
+
name: "John",
|
705
|
+
friends: Friends.create(
|
706
|
+
{
|
707
|
+
jane: Person.create(
|
708
|
+
{
|
709
|
+
name: "Jane",
|
710
|
+
dog: Dog.create({ name: "Rex" }, onlyBob), // Jane dog is inaccessible
|
711
|
+
},
|
712
|
+
group,
|
713
|
+
),
|
714
|
+
alice: Person.create(
|
715
|
+
{ name: "Alice", dog: Dog.create({ name: "Giggino" }, group) },
|
716
|
+
group,
|
717
|
+
),
|
718
|
+
},
|
719
|
+
group,
|
720
|
+
),
|
721
|
+
},
|
722
|
+
group,
|
723
|
+
);
|
724
|
+
|
725
|
+
const user = await User.load(map.id, {
|
726
|
+
resolve: { friends: { $each: { dog: true, $onError: null } } },
|
727
|
+
loadAs: alice,
|
728
|
+
});
|
729
|
+
|
730
|
+
assert(user);
|
731
|
+
|
732
|
+
expect(user.friends.jane).toBeNull(); // jane is null because her dog is inaccessible
|
733
|
+
expect(user.friends.alice?.dog).not.toBeNull(); // alice is not null because we have read access to her and her dog
|
734
|
+
});
|
735
|
+
|
736
|
+
test("unaccessible list element with $onError and $each with depth", async () => {
|
737
|
+
const Person = co.map({
|
738
|
+
name: z.string(),
|
739
|
+
get friends(): z.ZodOptional<typeof Friends> {
|
740
|
+
return z.optional(Friends);
|
741
|
+
},
|
742
|
+
});
|
743
|
+
const Friends: CoListSchema<typeof Person> = co.list(Person); // TODO: annoying that we have to annotate
|
744
|
+
|
745
|
+
const list = Friends.create(
|
746
|
+
[
|
747
|
+
Person.create(
|
748
|
+
{
|
749
|
+
name: "Jane",
|
750
|
+
friends: Friends.create(
|
751
|
+
[Person.create({ name: "Bob" }, onlyBob)],
|
752
|
+
group,
|
753
|
+
),
|
754
|
+
},
|
755
|
+
group,
|
756
|
+
),
|
757
|
+
Person.create(
|
758
|
+
{
|
759
|
+
name: "Alice",
|
760
|
+
friends: Friends.create(
|
761
|
+
[Person.create({ name: "Bob" }, group)],
|
762
|
+
group,
|
763
|
+
),
|
764
|
+
},
|
765
|
+
group,
|
766
|
+
),
|
767
|
+
],
|
768
|
+
group,
|
769
|
+
);
|
770
|
+
|
771
|
+
// The error List -> Jane -> Bob should be propagated to the list element Jane
|
772
|
+
// and we should have [null, Alice]
|
773
|
+
const listOnAlice = await Friends.load(list.id, {
|
774
|
+
resolve: { $each: { friends: { $each: true }, $onError: null } },
|
775
|
+
loadAs: alice,
|
776
|
+
});
|
777
|
+
|
778
|
+
assert(listOnAlice, "listOnAlice is null");
|
779
|
+
|
780
|
+
expect(listOnAlice[0]).toBeNull();
|
781
|
+
expect(listOnAlice[1]).not.toBeNull();
|
782
|
+
expect(listOnAlice[1]?.name).toBe("Alice");
|
783
|
+
expect(listOnAlice[1]?.friends).not.toBeNull();
|
784
|
+
expect(listOnAlice[1]?.friends?.[0]?.name).toBe("Bob");
|
785
|
+
expect(listOnAlice).toHaveLength(2);
|
786
|
+
});
|
787
|
+
|
788
|
+
test("unaccessible record element with $onError", async () => {
|
789
|
+
const Person = co.map({
|
790
|
+
name: z.string(),
|
791
|
+
});
|
792
|
+
const Friend = co.record(z.string(), Person);
|
793
|
+
|
794
|
+
const map = Friend.create(
|
795
|
+
{
|
796
|
+
jane: Person.create({ name: "Jane" }, onlyBob),
|
797
|
+
alice: Person.create({ name: "Alice" }, group),
|
798
|
+
},
|
799
|
+
group,
|
800
|
+
);
|
801
|
+
|
802
|
+
const friendsOnAlice = await Friend.load(map.id, {
|
803
|
+
resolve: { $each: { $onError: null } },
|
804
|
+
loadAs: alice,
|
805
|
+
});
|
806
|
+
|
807
|
+
assert(friendsOnAlice, "friendsOnAlice is null");
|
808
|
+
|
809
|
+
expect(friendsOnAlice.jane).toBeNull();
|
810
|
+
expect(friendsOnAlice.alice).not.toBeNull();
|
811
|
+
});
|
812
|
+
|
813
|
+
test("unaccessible ref catched with $onError", async () => {
|
814
|
+
const Dog = co.map({
|
815
|
+
name: z.string(),
|
816
|
+
});
|
817
|
+
|
818
|
+
const Person = co.map({
|
819
|
+
name: z.string(),
|
820
|
+
dog: Dog,
|
821
|
+
});
|
822
|
+
|
823
|
+
const Friends = co.record(z.string(), Person);
|
824
|
+
|
825
|
+
const User = co.map({
|
826
|
+
name: z.string(),
|
827
|
+
friends: Friends,
|
828
|
+
});
|
829
|
+
|
830
|
+
const map = User.create(
|
831
|
+
{
|
832
|
+
name: "John",
|
833
|
+
friends: Friends.create(
|
834
|
+
{
|
835
|
+
jane: Person.create(
|
836
|
+
{
|
837
|
+
name: "Jane",
|
838
|
+
dog: Dog.create({ name: "Rex" }, onlyBob), // Jane dog is inaccessible
|
839
|
+
},
|
840
|
+
group,
|
841
|
+
),
|
842
|
+
alice: Person.create(
|
843
|
+
{ name: "Alice", dog: Dog.create({ name: "Giggino" }, group) },
|
844
|
+
group,
|
845
|
+
),
|
846
|
+
},
|
847
|
+
group,
|
848
|
+
),
|
849
|
+
},
|
850
|
+
group,
|
851
|
+
);
|
852
|
+
|
853
|
+
const user = await User.load(map.id, {
|
854
|
+
resolve: { friends: { $each: { dog: { $onError: null } } } },
|
855
|
+
loadAs: alice,
|
856
|
+
});
|
857
|
+
|
858
|
+
assert(user);
|
859
|
+
|
860
|
+
expect(user.friends.jane?.dog).toBeNull(); // jane is null because her dog is inaccessible
|
861
|
+
expect(user.friends.alice?.dog?.name).toBe("Giggino"); // alice is not null because we have read access to her and her dog
|
862
|
+
});
|
863
|
+
|
864
|
+
test("using $onError on the resolve root", async () => {
|
865
|
+
const Person = co.map({
|
866
|
+
name: z.string(),
|
867
|
+
});
|
868
|
+
|
869
|
+
const map = Person.create({ name: "John" }, onlyBob);
|
870
|
+
const user = await Person.load(map.id, {
|
871
|
+
resolve: { $onError: null },
|
872
|
+
loadAs: alice,
|
873
|
+
});
|
874
|
+
|
875
|
+
expect(user).toBeNull();
|
876
|
+
});
|
615
877
|
});
|
616
878
|
|
617
879
|
test("doesn't break on Map.Record key deletion when the key is referenced in the depth", async () => {
|
618
|
-
|
619
|
-
|
620
|
-
|
880
|
+
const JazzProfile = co.map({
|
881
|
+
name: z.string(),
|
882
|
+
firstName: z.string(),
|
883
|
+
});
|
621
884
|
|
622
|
-
|
885
|
+
const JazzySnapStore = co.record(z.string(), JazzProfile);
|
623
886
|
|
624
887
|
const snapStore = JazzySnapStore.create({
|
625
|
-
profile1: JazzProfile.create({ firstName: "John" }),
|
626
|
-
profile2: JazzProfile.create({ firstName: "John" }),
|
888
|
+
profile1: JazzProfile.create({ name: "John", firstName: "John" }),
|
889
|
+
profile2: JazzProfile.create({ name: "John", firstName: "John" }),
|
627
890
|
});
|
628
891
|
|
629
892
|
const spy = vi.fn();
|
@@ -651,13 +914,14 @@ test("doesn't break on Map.Record key deletion when the key is referenced in the
|
|
651
914
|
});
|
652
915
|
|
653
916
|
test("throw when calling ensureLoaded on a ref that's required but missing", async () => {
|
654
|
-
|
655
|
-
|
656
|
-
|
917
|
+
const JazzProfile = co.map({
|
918
|
+
name: z.string(),
|
919
|
+
firstName: z.string(),
|
920
|
+
});
|
657
921
|
|
658
|
-
|
659
|
-
profile
|
660
|
-
}
|
922
|
+
const JazzRoot = co.map({
|
923
|
+
profile: JazzProfile,
|
924
|
+
});
|
661
925
|
|
662
926
|
const me = await Account.create({
|
663
927
|
creationProps: { name: "Tester McTesterson" },
|
@@ -678,7 +942,7 @@ test("throw when calling ensureLoaded on a ref that's required but missing", asy
|
|
678
942
|
});
|
679
943
|
|
680
944
|
test("throw when calling ensureLoaded on a ref that is not defined in the schema", async () => {
|
681
|
-
|
945
|
+
const JazzRoot = co.map({});
|
682
946
|
|
683
947
|
const me = await Account.create({
|
684
948
|
creationProps: { name: "Tester McTesterson" },
|
@@ -689,17 +953,19 @@ test("throw when calling ensureLoaded on a ref that is not defined in the schema
|
|
689
953
|
|
690
954
|
await expect(
|
691
955
|
root.ensureLoaded({
|
956
|
+
// @ts-expect-error missing required ref
|
692
957
|
resolve: { profile: true },
|
693
958
|
}),
|
694
959
|
).rejects.toThrow("Failed to deeply load CoValue " + root.id);
|
695
960
|
});
|
696
961
|
|
697
962
|
test("should not throw when calling ensureLoaded a record with a deleted ref", async () => {
|
698
|
-
|
699
|
-
|
700
|
-
|
963
|
+
const JazzProfile = co.map({
|
964
|
+
name: z.string(),
|
965
|
+
firstName: z.string(),
|
966
|
+
});
|
701
967
|
|
702
|
-
|
968
|
+
const JazzySnapStore = co.record(z.string(), JazzProfile);
|
703
969
|
|
704
970
|
const me = await Account.create({
|
705
971
|
creationProps: { name: "Tester McTesterson" },
|
@@ -708,7 +974,7 @@ test("should not throw when calling ensureLoaded a record with a deleted ref", a
|
|
708
974
|
|
709
975
|
const root = JazzySnapStore.create(
|
710
976
|
{
|
711
|
-
profile: JazzProfile.create({ firstName: "John" }, me),
|
977
|
+
profile: JazzProfile.create({ name: "John", firstName: "John" }, me),
|
712
978
|
},
|
713
979
|
me,
|
714
980
|
);
|