jazz-tools 0.19.11 → 0.19.13
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 +51 -51
- package/CHANGELOG.md +22 -0
- package/dist/browser/createBrowserContext.d.ts +1 -5
- package/dist/browser/createBrowserContext.d.ts.map +1 -1
- package/dist/browser/index.js +124 -47
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/provideBrowserLockSession/BrowserSessionProvider.d.ts +12 -0
- package/dist/browser/provideBrowserLockSession/BrowserSessionProvider.d.ts.map +1 -0
- package/dist/browser/provideBrowserLockSession/BrowserSessionProvider.test.d.ts +2 -0
- package/dist/browser/provideBrowserLockSession/BrowserSessionProvider.test.d.ts.map +1 -0
- package/dist/browser/provideBrowserLockSession/SessionIDStorage.d.ts +6 -0
- package/dist/browser/provideBrowserLockSession/SessionIDStorage.d.ts.map +1 -0
- package/dist/browser/provideBrowserLockSession/index.d.ts +4 -0
- package/dist/browser/provideBrowserLockSession/index.d.ts.map +1 -0
- package/dist/{chunk-HX5S6W5E.js → chunk-GAPMDNJY.js} +492 -108
- package/dist/chunk-GAPMDNJY.js.map +1 -0
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector/{chunk-C6BJPHBQ.js → chunk-YQNK5Y7B.js} +47 -35
- package/dist/inspector/chunk-YQNK5Y7B.js.map +1 -0
- package/dist/inspector/{custom-element-GJVBPZES.js → custom-element-KYV64IOC.js} +47 -35
- package/dist/inspector/{custom-element-GJVBPZES.js.map → custom-element-KYV64IOC.js.map} +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/standalone.js +1 -1
- package/dist/inspector/tests/utils/transactions-changes.test.d.ts +2 -0
- package/dist/inspector/tests/utils/transactions-changes.test.d.ts.map +1 -0
- package/dist/inspector/utils/transactions-changes.d.ts +13 -13
- package/dist/inspector/utils/transactions-changes.d.ts.map +1 -1
- package/dist/react/index.js +4 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/provider.d.ts.map +1 -1
- package/dist/react-core/index.js +2 -2
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native/index.js +45 -13
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native-core/ReactNativeSessionProvider.d.ts +11 -0
- package/dist/react-native-core/ReactNativeSessionProvider.d.ts.map +1 -0
- package/dist/react-native-core/index.js +45 -13
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/react-native-core/platform.d.ts +2 -8
- package/dist/react-native-core/platform.d.ts.map +1 -1
- package/dist/react-native-core/provider.d.ts.map +1 -1
- package/dist/react-native-core/tests/ReactNativeSessionProvider.test.d.ts +2 -0
- package/dist/react-native-core/tests/ReactNativeSessionProvider.test.d.ts.map +1 -0
- package/dist/testing.js +4 -3
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coFeed.d.ts +2 -2
- package/dist/tools/coValues/coFeed.d.ts.map +1 -1
- package/dist/tools/coValues/coList.d.ts +1 -2
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/coVector.d.ts.map +1 -1
- package/dist/tools/coValues/group.d.ts +5 -1
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +2 -1
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +2 -2
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
- package/dist/tools/implementation/createContext.d.ts +21 -11
- package/dist/tools/implementation/createContext.d.ts.map +1 -1
- package/dist/tools/implementation/schema.d.ts +14 -6
- package/dist/tools/implementation/schema.d.ts.map +1 -1
- package/dist/tools/implementation/schemaUtils.d.ts +1 -1
- package/dist/tools/implementation/schemaUtils.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaPermissions.d.ts +99 -0
- package/dist/tools/implementation/zodSchema/schemaPermissions.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +11 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +11 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +15 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +10 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts +9 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +13 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +10 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +6 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts +12 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +1 -0
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +3 -6
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/schema.withPermissions.test.d.ts +2 -0
- package/dist/tools/tests/schema.withPermissions.test.d.ts.map +1 -0
- package/dist/worker/index.js +2 -2
- package/dist/worker/index.js.map +1 -1
- package/package.json +4 -4
- package/src/browser/createBrowserContext.ts +3 -62
- package/src/browser/provideBrowserLockSession/BrowserSessionProvider.test.ts +406 -0
- package/src/browser/provideBrowserLockSession/BrowserSessionProvider.ts +132 -0
- package/src/browser/provideBrowserLockSession/SessionIDStorage.ts +33 -0
- package/src/browser/provideBrowserLockSession/index.ts +11 -0
- package/src/inspector/tests/utils/transactions-changes.test.ts +102 -0
- package/src/inspector/ui/icons/add-icon.tsx +3 -3
- package/src/inspector/utils/history.ts +6 -6
- package/src/inspector/utils/transactions-changes.ts +37 -3
- package/src/inspector/viewer/history-view.tsx +13 -13
- package/src/react/provider.tsx +6 -1
- package/src/react-core/hooks.ts +2 -2
- package/src/react-core/tests/useSuspenseCoState.test.tsx +47 -0
- package/src/react-native-core/ReactNativeSessionProvider.ts +52 -0
- package/src/react-native-core/platform.ts +5 -30
- package/src/react-native-core/provider.tsx +6 -1
- package/src/react-native-core/tests/ReactNativeSessionProvider.test.ts +124 -0
- package/src/tools/coValues/account.ts +4 -0
- package/src/tools/coValues/coFeed.ts +8 -3
- package/src/tools/coValues/coList.ts +6 -3
- package/src/tools/coValues/coMap.ts +10 -0
- package/src/tools/coValues/coVector.ts +2 -1
- package/src/tools/coValues/group.ts +6 -4
- package/src/tools/coValues/interfaces.ts +19 -7
- package/src/tools/exports.ts +3 -1
- package/src/tools/implementation/ContextManager.ts +10 -0
- package/src/tools/implementation/createContext.ts +43 -15
- package/src/tools/implementation/schema.ts +23 -13
- package/src/tools/implementation/schemaUtils.ts +1 -1
- package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +105 -4
- package/src/tools/implementation/zodSchema/schemaPermissions.ts +188 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +46 -3
- package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +46 -3
- package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +50 -13
- package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +14 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.ts +24 -1
- package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +51 -4
- package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +25 -1
- package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +21 -1
- package/src/tools/implementation/zodSchema/unionUtils.ts +72 -20
- package/src/tools/internal.ts +1 -0
- package/src/tools/subscribe/SubscriptionScope.ts +61 -39
- package/src/tools/testing.ts +3 -1
- package/src/tools/tests/ContextManager.test.ts +2 -1
- package/src/tools/tests/coPlainText.test.ts +2 -2
- package/src/tools/tests/createContext.test.ts +79 -1
- package/src/tools/tests/deepLoading.test.ts +25 -2
- package/src/tools/tests/schema.resolved.test.ts +10 -0
- package/src/tools/tests/schema.withPermissions.test.ts +859 -0
- package/src/tools/tests/utils.ts +2 -2
- package/src/worker/index.ts +2 -2
- package/dist/chunk-HX5S6W5E.js.map +0 -1
- package/dist/inspector/chunk-C6BJPHBQ.js.map +0 -1
|
@@ -7,10 +7,15 @@ import {
|
|
|
7
7
|
Settled,
|
|
8
8
|
coOptionalDefiner,
|
|
9
9
|
unstable_mergeBranchWithResolve,
|
|
10
|
+
withSchemaPermissions,
|
|
10
11
|
} from "../../../internal.js";
|
|
11
12
|
import { AnonymousJazzAgent } from "../../anonymousJazzAgent.js";
|
|
12
13
|
import { CoOptionalSchema } from "./CoOptionalSchema.js";
|
|
13
14
|
import { CoreCoValueSchema } from "./CoValueSchema.js";
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_SCHEMA_PERMISSIONS,
|
|
17
|
+
SchemaPermissions,
|
|
18
|
+
} from "../schemaPermissions.js";
|
|
14
19
|
|
|
15
20
|
export interface CorePlainTextSchema extends CoreCoValueSchema {
|
|
16
21
|
builtin: "CoPlainText";
|
|
@@ -29,6 +34,12 @@ export class PlainTextSchema implements CorePlainTextSchema {
|
|
|
29
34
|
readonly builtin = "CoPlainText" as const;
|
|
30
35
|
readonly resolveQuery = true as const;
|
|
31
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Permissions to be used when creating or composing CoValues
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
|
|
42
|
+
|
|
32
43
|
constructor(private coValueClass: typeof CoPlainText) {}
|
|
33
44
|
|
|
34
45
|
create(text: string, options?: { owner: Group } | Group): CoPlainText;
|
|
@@ -41,7 +52,11 @@ export class PlainTextSchema implements CorePlainTextSchema {
|
|
|
41
52
|
text: string,
|
|
42
53
|
options?: { owner: Account | Group } | Account | Group,
|
|
43
54
|
): CoPlainText {
|
|
44
|
-
|
|
55
|
+
const optionsWithPermissions = withSchemaPermissions(
|
|
56
|
+
options,
|
|
57
|
+
this.permissions,
|
|
58
|
+
);
|
|
59
|
+
return this.coValueClass.create(text, optionsWithPermissions);
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
load(
|
|
@@ -90,4 +105,13 @@ export class PlainTextSchema implements CorePlainTextSchema {
|
|
|
90
105
|
optional(): CoOptionalSchema<this> {
|
|
91
106
|
return coOptionalDefiner(this);
|
|
92
107
|
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Configure permissions to be used when creating or composing CoValues
|
|
111
|
+
*/
|
|
112
|
+
withPermissions(permissions: SchemaPermissions): PlainTextSchema {
|
|
113
|
+
const copy = new PlainTextSchema(this.coValueClass);
|
|
114
|
+
copy.permissions = permissions;
|
|
115
|
+
return copy;
|
|
116
|
+
}
|
|
93
117
|
}
|
|
@@ -6,10 +6,15 @@ import {
|
|
|
6
6
|
Settled,
|
|
7
7
|
coOptionalDefiner,
|
|
8
8
|
unstable_mergeBranchWithResolve,
|
|
9
|
+
withSchemaPermissions,
|
|
9
10
|
} from "../../../internal.js";
|
|
10
11
|
import { AnonymousJazzAgent } from "../../anonymousJazzAgent.js";
|
|
11
12
|
import { CoOptionalSchema } from "./CoOptionalSchema.js";
|
|
12
13
|
import { CoreCoValueSchema } from "./CoValueSchema.js";
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_SCHEMA_PERMISSIONS,
|
|
16
|
+
SchemaPermissions,
|
|
17
|
+
} from "../schemaPermissions.js";
|
|
13
18
|
|
|
14
19
|
export interface CoreRichTextSchema extends CoreCoValueSchema {
|
|
15
20
|
builtin: "CoRichText";
|
|
@@ -28,6 +33,8 @@ export class RichTextSchema implements CoreRichTextSchema {
|
|
|
28
33
|
readonly builtin = "CoRichText" as const;
|
|
29
34
|
readonly resolveQuery = true as const;
|
|
30
35
|
|
|
36
|
+
permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
|
|
37
|
+
|
|
31
38
|
constructor(private coValueClass: typeof CoRichText) {}
|
|
32
39
|
|
|
33
40
|
create(text: string, options?: { owner: Group } | Group): CoRichText;
|
|
@@ -40,7 +47,11 @@ export class RichTextSchema implements CoreRichTextSchema {
|
|
|
40
47
|
text: string,
|
|
41
48
|
options?: { owner: Account | Group } | Account | Group,
|
|
42
49
|
): CoRichText {
|
|
43
|
-
|
|
50
|
+
const optionsWithPermissions = withSchemaPermissions(
|
|
51
|
+
options,
|
|
52
|
+
this.permissions,
|
|
53
|
+
);
|
|
54
|
+
return this.coValueClass.create(text, optionsWithPermissions);
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
load(
|
|
@@ -85,4 +96,13 @@ export class RichTextSchema implements CoreRichTextSchema {
|
|
|
85
96
|
optional(): CoOptionalSchema<this> {
|
|
86
97
|
return coOptionalDefiner(this);
|
|
87
98
|
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Configure permissions to be used when creating or composing CoValues
|
|
102
|
+
*/
|
|
103
|
+
withPermissions(permissions: SchemaPermissions): RichTextSchema {
|
|
104
|
+
const copy = new RichTextSchema(this.coValueClass);
|
|
105
|
+
copy.permissions = permissions;
|
|
106
|
+
return copy;
|
|
107
|
+
}
|
|
88
108
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonValue, RawCoMap } from "cojson";
|
|
1
2
|
import {
|
|
2
3
|
AnyZodOrCoValueSchema,
|
|
3
4
|
CoDiscriminatedUnionSchema,
|
|
@@ -37,25 +38,7 @@ export function schemaUnionDiscriminatorFor(
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
const availableOptions
|
|
41
|
-
|
|
42
|
-
for (const option of options) {
|
|
43
|
-
if (option.builtin === "CoMap") {
|
|
44
|
-
availableOptions.push(option);
|
|
45
|
-
} else if (option.builtin === "CoDiscriminatedUnion") {
|
|
46
|
-
for (const subOption of (
|
|
47
|
-
option as CoDiscriminatedUnionSchema<any>
|
|
48
|
-
).getDefinition().options) {
|
|
49
|
-
if (!options.includes(subOption)) {
|
|
50
|
-
options.push(subOption);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
throw new Error(
|
|
55
|
-
"Unsupported zod type in co.discriminatedUnion() of collaborative types",
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
41
|
+
const availableOptions = getFlattenedUnionOptions(schema);
|
|
59
42
|
|
|
60
43
|
const determineSchema: SchemaUnionDiscriminator<CoMap> = (
|
|
61
44
|
discriminable,
|
|
@@ -77,7 +60,10 @@ export function schemaUnionDiscriminatorFor(
|
|
|
77
60
|
|
|
78
61
|
for (const key of Object.keys(discriminatorMap)) {
|
|
79
62
|
const discriminatorDef = optionDef.shape[key];
|
|
80
|
-
const discriminatorValue =
|
|
63
|
+
const discriminatorValue = resolveDiscriminantValue(
|
|
64
|
+
discriminable,
|
|
65
|
+
key,
|
|
66
|
+
);
|
|
81
67
|
|
|
82
68
|
if (discriminatorValue && typeof discriminatorValue === "object") {
|
|
83
69
|
throw new Error("Discriminator must be a primitive value");
|
|
@@ -175,3 +161,69 @@ function isCoDiscriminatedUnion(
|
|
|
175
161
|
): def is CoreCoDiscriminatedUnionSchema<any> {
|
|
176
162
|
return def.builtin === "CoDiscriminatedUnion";
|
|
177
163
|
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Flattens all options from a discriminated union schema, including nested unions.
|
|
167
|
+
* Returns all options in a flat array.
|
|
168
|
+
*/
|
|
169
|
+
export function getFlattenedUnionOptions(
|
|
170
|
+
schema: CoreCoDiscriminatedUnionSchema<DiscriminableCoValueSchemas>,
|
|
171
|
+
): DiscriminableCoreCoValueSchema[] {
|
|
172
|
+
const definition = schema.getDefinition();
|
|
173
|
+
const options = definition.options;
|
|
174
|
+
const availableOptions: DiscriminableCoreCoValueSchema[] = [];
|
|
175
|
+
|
|
176
|
+
for (const option of options) {
|
|
177
|
+
if (option.builtin === "CoMap") {
|
|
178
|
+
availableOptions.push(option);
|
|
179
|
+
} else if (option.builtin === "CoDiscriminatedUnion") {
|
|
180
|
+
const nestedOptions = getFlattenedUnionOptions(
|
|
181
|
+
option as CoreCoDiscriminatedUnionSchema<DiscriminableCoValueSchemas>,
|
|
182
|
+
);
|
|
183
|
+
for (const subOption of nestedOptions) {
|
|
184
|
+
if (!availableOptions.includes(subOption)) {
|
|
185
|
+
availableOptions.push(subOption);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
throw new Error(
|
|
190
|
+
"Unsupported zod type in co.discriminatedUnion() of collaborative types",
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return availableOptions;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Gets the discriminator values for a given option and discriminator key
|
|
200
|
+
*/
|
|
201
|
+
export function getDiscriminatorValuesForOption(
|
|
202
|
+
option: DiscriminableCoreCoValueSchema,
|
|
203
|
+
discriminatorKey: string,
|
|
204
|
+
): Set<unknown> | undefined {
|
|
205
|
+
const optionDefinition = option.getDefinition();
|
|
206
|
+
return optionDefinition.discriminatorMap?.[discriminatorKey];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function resolveDiscriminantValue(
|
|
210
|
+
init: unknown,
|
|
211
|
+
discriminatorKey: string,
|
|
212
|
+
): JsonValue | undefined {
|
|
213
|
+
if (init == null) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (init instanceof Map || init instanceof RawCoMap) {
|
|
218
|
+
return init.get(discriminatorKey);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (typeof init === "object") {
|
|
222
|
+
const record = init as Record<string, JsonValue>;
|
|
223
|
+
if (discriminatorKey in record) {
|
|
224
|
+
return record[discriminatorKey];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
package/src/tools/internal.ts
CHANGED
|
@@ -53,6 +53,7 @@ export * from "./implementation/zodSchema/typeConverters/InstanceOfSchemaCoValue
|
|
|
53
53
|
export * from "./implementation/zodSchema/typeConverters/CoFieldSchemaInit.js";
|
|
54
54
|
export * from "./implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.js";
|
|
55
55
|
export * from "./implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.js";
|
|
56
|
+
export * from "./implementation/zodSchema/schemaPermissions.js";
|
|
56
57
|
export * from "./coValues/extensions/imageDef.js";
|
|
57
58
|
|
|
58
59
|
export * from "./implementation/ContextManager.js";
|
|
@@ -309,64 +309,86 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
309
309
|
|
|
310
310
|
unloadedValue: NotLoaded<D> | undefined;
|
|
311
311
|
|
|
312
|
-
lastPromise:
|
|
313
|
-
| {
|
|
314
|
-
value: MaybeLoaded<D> | undefined;
|
|
315
|
-
promise: PromiseWithStatus<MaybeLoaded<D>>;
|
|
316
|
-
}
|
|
317
|
-
| undefined;
|
|
318
|
-
|
|
319
|
-
cachePromise(value: MaybeLoaded<D>, callback: () => PromiseWithStatus<D>) {
|
|
320
|
-
if (this.lastPromise?.value === value) {
|
|
321
|
-
return this.lastPromise.promise;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const promise = callback();
|
|
325
|
-
this.lastPromise = { value, promise };
|
|
326
|
-
|
|
327
|
-
return promise;
|
|
328
|
-
}
|
|
312
|
+
lastPromise: PromiseWithStatus<D> | undefined;
|
|
329
313
|
|
|
330
314
|
getPromise() {
|
|
331
315
|
const currentValue = this.getCurrentValue();
|
|
332
316
|
|
|
333
317
|
if (currentValue.$isLoaded) {
|
|
334
|
-
return resolvedPromise(currentValue);
|
|
318
|
+
return resolvedPromise<D>(currentValue);
|
|
335
319
|
}
|
|
336
320
|
|
|
337
321
|
if (currentValue.$jazz.loadingState !== CoValueLoadingState.LOADING) {
|
|
338
322
|
const error = this.getError();
|
|
339
|
-
return rejectedPromise(
|
|
323
|
+
return rejectedPromise<D>(
|
|
340
324
|
new Error(error?.toString() ?? "Unknown error", {
|
|
341
325
|
cause: this.callerStack,
|
|
342
326
|
}),
|
|
343
327
|
);
|
|
344
328
|
}
|
|
345
329
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const unsubscribe = this.subscribe(() => {
|
|
350
|
-
const currentValue = this.getCurrentValue();
|
|
330
|
+
const promise = new Promise<D>((resolve, reject) => {
|
|
331
|
+
const unsubscribe = this.subscribe(() => {
|
|
332
|
+
const currentValue = this.getCurrentValue();
|
|
351
333
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
334
|
+
if (currentValue.$jazz.loadingState === CoValueLoadingState.LOADING) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
355
337
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
)
|
|
364
|
-
|
|
338
|
+
if (currentValue.$isLoaded) {
|
|
339
|
+
promise.status = "fulfilled";
|
|
340
|
+
promise.value = currentValue;
|
|
341
|
+
resolve(currentValue);
|
|
342
|
+
} else {
|
|
343
|
+
promise.status = "rejected";
|
|
344
|
+
promise.reason = new Error(
|
|
345
|
+
this.getError()?.toString() ?? "Unknown error",
|
|
346
|
+
{
|
|
347
|
+
cause: this.callerStack,
|
|
348
|
+
},
|
|
349
|
+
);
|
|
350
|
+
reject(
|
|
351
|
+
new Error(this.getError()?.toString() ?? "Unknown error", {
|
|
352
|
+
cause: this.callerStack,
|
|
353
|
+
}),
|
|
354
|
+
);
|
|
355
|
+
}
|
|
365
356
|
|
|
366
|
-
|
|
367
|
-
});
|
|
357
|
+
unsubscribe();
|
|
368
358
|
});
|
|
369
|
-
})
|
|
359
|
+
}) as PromiseWithStatus<D>;
|
|
360
|
+
|
|
361
|
+
promise.status = "pending";
|
|
362
|
+
|
|
363
|
+
return promise;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
getCachedPromise() {
|
|
367
|
+
if (this.lastPromise) {
|
|
368
|
+
const value = this.getCurrentValue();
|
|
369
|
+
|
|
370
|
+
// if the value is loaded, we update the promise state
|
|
371
|
+
// to ensure that the value provided is always up to date
|
|
372
|
+
if (value.$isLoaded) {
|
|
373
|
+
this.lastPromise.status = "fulfilled";
|
|
374
|
+
this.lastPromise.value = value;
|
|
375
|
+
} else if (value.$jazz.loadingState !== CoValueLoadingState.LOADING) {
|
|
376
|
+
this.lastPromise.status = "rejected";
|
|
377
|
+
this.lastPromise.reason = new Error(
|
|
378
|
+
this.getError()?.toString() ?? "Unknown error",
|
|
379
|
+
{
|
|
380
|
+
cause: this.callerStack,
|
|
381
|
+
},
|
|
382
|
+
);
|
|
383
|
+
} else if (this.lastPromise.status !== "pending") {
|
|
384
|
+
// Value got into loading state, we need to suspend again
|
|
385
|
+
this.lastPromise = this.getPromise();
|
|
386
|
+
}
|
|
387
|
+
} else {
|
|
388
|
+
this.lastPromise = this.getPromise();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return this.lastPromise;
|
|
370
392
|
}
|
|
371
393
|
|
|
372
394
|
private getUnloadedValue(reason: NotLoadedCoValueState): NotLoaded<D> {
|
package/src/tools/testing.ts
CHANGED
|
@@ -16,9 +16,11 @@ import {
|
|
|
16
16
|
coValueClassFromCoValueClassOrSchema,
|
|
17
17
|
createAnonymousJazzContext,
|
|
18
18
|
createJazzContext,
|
|
19
|
-
|
|
19
|
+
MockSessionProvider,
|
|
20
20
|
} from "./internal.js";
|
|
21
21
|
|
|
22
|
+
const randomSessionProvider = new MockSessionProvider();
|
|
23
|
+
|
|
22
24
|
export { assertLoaded } from "./lib/utils.js";
|
|
23
25
|
|
|
24
26
|
const syncServer: { current: LocalNode | null; asyncPeers: boolean } = {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "../implementation/ContextManager";
|
|
20
20
|
import {
|
|
21
21
|
createJazzContext,
|
|
22
|
-
|
|
22
|
+
MockSessionProvider,
|
|
23
23
|
} from "../implementation/createContext";
|
|
24
24
|
import {
|
|
25
25
|
CoValueFromRaw,
|
|
@@ -37,6 +37,7 @@ import { SubscriptionCache } from "../subscribe/SubscriptionCache";
|
|
|
37
37
|
import { createAsyncStorage, getDbPath } from "./testStorage";
|
|
38
38
|
|
|
39
39
|
const Crypto = await WasmCrypto.create();
|
|
40
|
+
const randomSessionProvider = new MockSessionProvider();
|
|
40
41
|
|
|
41
42
|
class TestJazzContextManager<Acc extends Account> extends JazzContextManager<
|
|
42
43
|
Acc,
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
createJazzContextFromExistingCredentials,
|
|
8
8
|
isControlledAccount,
|
|
9
9
|
} from "../index.js";
|
|
10
|
-
import { co,
|
|
10
|
+
import { co, MockSessionProvider } from "../internal.js";
|
|
11
11
|
|
|
12
12
|
const Crypto = await WasmCrypto.create();
|
|
13
|
-
|
|
13
|
+
const randomSessionProvider = new MockSessionProvider();
|
|
14
14
|
const connectedPeers = cojsonInternals.connectedPeers;
|
|
15
15
|
|
|
16
16
|
describe("CoPlainText", () => {
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
createJazzContext,
|
|
16
16
|
createJazzContextForNewAccount,
|
|
17
17
|
createJazzContextFromExistingCredentials,
|
|
18
|
-
|
|
18
|
+
MockSessionProvider,
|
|
19
19
|
} from "../exports";
|
|
20
20
|
import { activeAccountContext } from "../implementation/activeAccountContext";
|
|
21
21
|
import {
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { assertLoaded, loadCoValueOrFail } from "./utils";
|
|
27
27
|
const Crypto = await WasmCrypto.create();
|
|
28
28
|
|
|
29
|
+
let randomSessionProvider = new MockSessionProvider();
|
|
29
30
|
KvStoreContext.getInstance().initialize(new InMemoryKVStore());
|
|
30
31
|
|
|
31
32
|
describe("createContext methods", () => {
|
|
@@ -35,6 +36,9 @@ describe("createContext methods", () => {
|
|
|
35
36
|
authSecretStorage = new AuthSecretStorage();
|
|
36
37
|
authSecretStorage.clear();
|
|
37
38
|
await setupJazzTestSync();
|
|
39
|
+
randomSessionProvider = new MockSessionProvider();
|
|
40
|
+
vi.spyOn(randomSessionProvider, "acquireSession");
|
|
41
|
+
vi.spyOn(randomSessionProvider, "persistSession");
|
|
38
42
|
});
|
|
39
43
|
|
|
40
44
|
describe("createJazzContextFromExistingCredentials", () => {
|
|
@@ -49,6 +53,13 @@ describe("createContext methods", () => {
|
|
|
49
53
|
secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
|
|
50
54
|
};
|
|
51
55
|
|
|
56
|
+
const sessionID = Crypto.newRandomSessionID(account.$jazz.raw.id);
|
|
57
|
+
|
|
58
|
+
vi.spyOn(randomSessionProvider, "acquireSession").mockResolvedValue({
|
|
59
|
+
sessionID: sessionID,
|
|
60
|
+
sessionDone: () => {},
|
|
61
|
+
});
|
|
62
|
+
|
|
52
63
|
const context = await createJazzContextFromExistingCredentials({
|
|
53
64
|
credentials,
|
|
54
65
|
peers: [getPeerConnectedToTestSyncServer()],
|
|
@@ -60,10 +71,47 @@ describe("createContext methods", () => {
|
|
|
60
71
|
expect(context.node).toBeDefined();
|
|
61
72
|
expect(context.account).toBeDefined();
|
|
62
73
|
expect(context.account.$jazz.id).toBe(credentials.accountID);
|
|
74
|
+
expect(context.node.currentSessionID).toBe(sessionID);
|
|
63
75
|
expect(typeof context.done).toBe("function");
|
|
64
76
|
expect(typeof context.logOut).toBe("function");
|
|
65
77
|
});
|
|
66
78
|
|
|
79
|
+
test("releasese the session when the context is done", async () => {
|
|
80
|
+
const spy = vi.fn();
|
|
81
|
+
|
|
82
|
+
// Create an account first to get valid credentials
|
|
83
|
+
const account = await createJazzTestAccount({
|
|
84
|
+
isCurrentActiveAccount: true,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const credentials: Credentials = {
|
|
88
|
+
accountID: account.$jazz.id,
|
|
89
|
+
secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const sessionID = Crypto.newRandomSessionID(account.$jazz.raw.id);
|
|
93
|
+
|
|
94
|
+
vi.spyOn(randomSessionProvider, "acquireSession").mockResolvedValue({
|
|
95
|
+
sessionID: sessionID,
|
|
96
|
+
sessionDone: spy,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const context = await createJazzContextFromExistingCredentials({
|
|
100
|
+
credentials,
|
|
101
|
+
peers: [getPeerConnectedToTestSyncServer()],
|
|
102
|
+
crypto: Crypto,
|
|
103
|
+
sessionProvider: randomSessionProvider,
|
|
104
|
+
asActiveAccount: true,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(randomSessionProvider.acquireSession).toHaveBeenCalled();
|
|
108
|
+
expect(spy).not.toHaveBeenCalled();
|
|
109
|
+
|
|
110
|
+
context.done();
|
|
111
|
+
|
|
112
|
+
expect(spy).toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
|
|
67
115
|
test("handles custom account schema", async () => {
|
|
68
116
|
const CustomAccount = co
|
|
69
117
|
.account({
|
|
@@ -187,6 +235,7 @@ describe("createContext methods", () => {
|
|
|
187
235
|
creationProps: { name: "New User" },
|
|
188
236
|
peers: [],
|
|
189
237
|
crypto: Crypto,
|
|
238
|
+
sessionProvider: randomSessionProvider,
|
|
190
239
|
});
|
|
191
240
|
|
|
192
241
|
expect(context.account).toBeDefined();
|
|
@@ -202,11 +251,38 @@ describe("createContext methods", () => {
|
|
|
202
251
|
initialAgentSecret: initialSecret,
|
|
203
252
|
peers: [],
|
|
204
253
|
crypto: Crypto,
|
|
254
|
+
sessionProvider: randomSessionProvider,
|
|
205
255
|
});
|
|
206
256
|
|
|
257
|
+
expect(randomSessionProvider.persistSession).toHaveBeenCalledWith(
|
|
258
|
+
context.account.$jazz.id,
|
|
259
|
+
context.node.currentSessionID,
|
|
260
|
+
);
|
|
261
|
+
expect(randomSessionProvider.acquireSession).not.toHaveBeenCalled();
|
|
207
262
|
expect(context.node.getCurrentAgent().agentSecret).toBe(initialSecret);
|
|
208
263
|
});
|
|
209
264
|
|
|
265
|
+
test("releasese the session when the context is done", async () => {
|
|
266
|
+
const spy = vi.fn();
|
|
267
|
+
vi.spyOn(randomSessionProvider, "persistSession").mockResolvedValue({
|
|
268
|
+
sessionDone: spy,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const context = await createJazzContextForNewAccount({
|
|
272
|
+
creationProps: { name: "New User" },
|
|
273
|
+
peers: [],
|
|
274
|
+
crypto: Crypto,
|
|
275
|
+
sessionProvider: randomSessionProvider,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
expect(randomSessionProvider.persistSession).toHaveBeenCalled();
|
|
279
|
+
expect(spy).not.toHaveBeenCalled();
|
|
280
|
+
|
|
281
|
+
context.done();
|
|
282
|
+
|
|
283
|
+
expect(spy).toHaveBeenCalled();
|
|
284
|
+
});
|
|
285
|
+
|
|
210
286
|
test("handles custom account schema", async () => {
|
|
211
287
|
const CustomAccount = co
|
|
212
288
|
.account({
|
|
@@ -220,6 +296,7 @@ describe("createContext methods", () => {
|
|
|
220
296
|
peers: [],
|
|
221
297
|
crypto: Crypto,
|
|
222
298
|
AccountSchema: CustomAccount,
|
|
299
|
+
sessionProvider: randomSessionProvider,
|
|
223
300
|
});
|
|
224
301
|
|
|
225
302
|
expect(context.account).toBeInstanceOf(
|
|
@@ -232,6 +309,7 @@ describe("createContext methods", () => {
|
|
|
232
309
|
creationProps: { name: "New User" },
|
|
233
310
|
peers: [],
|
|
234
311
|
crypto: Crypto,
|
|
312
|
+
sessionProvider: randomSessionProvider,
|
|
235
313
|
});
|
|
236
314
|
expect(activeAccountContext.get()).toBe(context.account);
|
|
237
315
|
});
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
MaybeLoaded,
|
|
24
24
|
Settled,
|
|
25
25
|
co,
|
|
26
|
-
|
|
26
|
+
MockSessionProvider,
|
|
27
27
|
CoValueLoadingState,
|
|
28
28
|
CoValueErrorState,
|
|
29
29
|
} from "../internal.js";
|
|
@@ -33,7 +33,7 @@ import { setCustomErrorReporter } from "../config.js";
|
|
|
33
33
|
|
|
34
34
|
const Crypto = await WasmCrypto.create();
|
|
35
35
|
const { connectedPeers } = cojsonInternals;
|
|
36
|
-
|
|
36
|
+
const randomSessionProvider = new MockSessionProvider();
|
|
37
37
|
const InnermostMap = co.map({
|
|
38
38
|
value: z.string(),
|
|
39
39
|
});
|
|
@@ -1192,6 +1192,29 @@ test("should not throw when calling ensureLoaded a record with a non-existent ke
|
|
|
1192
1192
|
expect(loadedPerson.pet1).toBeUndefined();
|
|
1193
1193
|
});
|
|
1194
1194
|
|
|
1195
|
+
test("should load a record with a non-existent key if there's a catch block", async () => {
|
|
1196
|
+
const Person = co.record(
|
|
1197
|
+
z.string(),
|
|
1198
|
+
co.map({
|
|
1199
|
+
name: z.string(),
|
|
1200
|
+
breed: z.string(),
|
|
1201
|
+
}),
|
|
1202
|
+
);
|
|
1203
|
+
|
|
1204
|
+
const person = Person.create({});
|
|
1205
|
+
|
|
1206
|
+
const loadedPerson = await Person.load(person.$jazz.id, {
|
|
1207
|
+
resolve: {
|
|
1208
|
+
pet1: {
|
|
1209
|
+
$onError: "catch",
|
|
1210
|
+
},
|
|
1211
|
+
},
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
assertLoaded(loadedPerson);
|
|
1215
|
+
expect(loadedPerson.pet1).toBeUndefined();
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1195
1218
|
// This was a regression that ocurred when we migrated `DeeplyLoaded` to use explicit loading states.
|
|
1196
1219
|
// Keeping this test to prevent it from happening again.
|
|
1197
1220
|
test("deep loaded CoList nested inside another CoValue can be iterated over", async () => {
|
|
@@ -796,4 +796,14 @@ describe("Schema.resolved()", () => {
|
|
|
796
796
|
expect(loadedPerson.friends[0]?.friends.$isLoaded).toBe(false);
|
|
797
797
|
});
|
|
798
798
|
});
|
|
799
|
+
|
|
800
|
+
test("resolved() does not override previous schema configuration", () => {
|
|
801
|
+
const TestMap = co
|
|
802
|
+
.map({ name: co.plainText() })
|
|
803
|
+
.withPermissions({ onInlineCreate: "sameAsContainer" });
|
|
804
|
+
const TestMapWithName = TestMap.resolved({ name: true });
|
|
805
|
+
expect(TestMapWithName.permissions).toEqual({
|
|
806
|
+
onInlineCreate: "sameAsContainer",
|
|
807
|
+
});
|
|
808
|
+
});
|
|
799
809
|
});
|