jazz-tools 0.19.12 → 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 +50 -50
- package/CHANGELOG.md +10 -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-AGF4HEDH.js → chunk-GAPMDNJY.js} +437 -82
- package/dist/chunk-GAPMDNJY.js.map +1 -0
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/react-native/index.js +41 -12
- 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 +41 -12
- 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/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/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/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/react-native-core/ReactNativeSessionProvider.ts +52 -0
- package/src/react-native-core/platform.ts +5 -30
- 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/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/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-AGF4HEDH.js.map +0 -1
|
@@ -28,10 +28,39 @@ export type Credentials = {
|
|
|
28
28
|
secret: AgentSecret;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
export interface SessionProvider {
|
|
32
|
+
acquireSession: (
|
|
33
|
+
accountID: ID<Account>,
|
|
34
|
+
crypto: CryptoProvider,
|
|
35
|
+
) => Promise<{ sessionID: SessionID; sessionDone: () => void }>;
|
|
36
|
+
persistSession: (
|
|
37
|
+
accountID: ID<Account>,
|
|
38
|
+
sessionID: SessionID,
|
|
39
|
+
) => Promise<{ sessionDone: () => void }>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class MockSessionProvider implements SessionProvider {
|
|
43
|
+
async acquireSession(
|
|
44
|
+
accountID: ID<Account>,
|
|
45
|
+
crypto: CryptoProvider,
|
|
46
|
+
): Promise<{ sessionID: SessionID; sessionDone: () => void }> {
|
|
47
|
+
return {
|
|
48
|
+
sessionID: crypto.newRandomSessionID(
|
|
49
|
+
accountID as unknown as RawAccountID,
|
|
50
|
+
),
|
|
51
|
+
sessionDone: () => {},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async persistSession(
|
|
56
|
+
_accountID: ID<Account>,
|
|
57
|
+
_sessionID: SessionID,
|
|
58
|
+
): Promise<{ sessionDone: () => void }> {
|
|
59
|
+
return {
|
|
60
|
+
sessionDone: () => {},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
35
64
|
|
|
36
65
|
export type AuthResult =
|
|
37
66
|
| {
|
|
@@ -57,16 +86,6 @@ export type AuthResult =
|
|
|
57
86
|
logOut: () => Promise<void>;
|
|
58
87
|
};
|
|
59
88
|
|
|
60
|
-
export async function randomSessionProvider(
|
|
61
|
-
accountID: ID<Account>,
|
|
62
|
-
crypto: CryptoProvider,
|
|
63
|
-
) {
|
|
64
|
-
return {
|
|
65
|
-
sessionID: crypto.newRandomSessionID(accountID as unknown as RawAccountID),
|
|
66
|
-
sessionDone: () => {},
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
89
|
export type JazzContextWithAccount<Acc extends Account> = {
|
|
71
90
|
node: LocalNode;
|
|
72
91
|
account: Acc;
|
|
@@ -107,7 +126,7 @@ export async function createJazzContextFromExistingCredentials<
|
|
|
107
126
|
storage?: StorageAPI;
|
|
108
127
|
asActiveAccount: boolean;
|
|
109
128
|
}): Promise<JazzContextWithAccount<InstanceOfSchema<S>>> {
|
|
110
|
-
const { sessionID, sessionDone } = await sessionProvider(
|
|
129
|
+
const { sessionID, sessionDone } = await sessionProvider.acquireSession(
|
|
111
130
|
credentials.accountID,
|
|
112
131
|
crypto,
|
|
113
132
|
);
|
|
@@ -167,6 +186,7 @@ export async function createJazzContextForNewAccount<
|
|
|
167
186
|
AccountSchema: PropsAccountSchema,
|
|
168
187
|
onLogOut,
|
|
169
188
|
storage,
|
|
189
|
+
sessionProvider,
|
|
170
190
|
}: {
|
|
171
191
|
creationProps: { name: string };
|
|
172
192
|
initialAgentSecret?: AgentSecret;
|
|
@@ -175,6 +195,7 @@ export async function createJazzContextForNewAccount<
|
|
|
175
195
|
AccountSchema?: S;
|
|
176
196
|
onLogOut?: () => Promise<void>;
|
|
177
197
|
storage?: StorageAPI;
|
|
198
|
+
sessionProvider: SessionProvider;
|
|
178
199
|
}): Promise<JazzContextWithAccount<InstanceOfSchema<S>>> {
|
|
179
200
|
const CurrentAccountSchema =
|
|
180
201
|
PropsAccountSchema ?? (RegisteredSchemas["Account"] as unknown as S);
|
|
@@ -199,11 +220,17 @@ export async function createJazzContextForNewAccount<
|
|
|
199
220
|
const account = AccountClass.fromNode(node);
|
|
200
221
|
activeAccountContext.set(account);
|
|
201
222
|
|
|
223
|
+
const { sessionDone } = await sessionProvider.persistSession(
|
|
224
|
+
account.$jazz.id,
|
|
225
|
+
node.currentSessionID,
|
|
226
|
+
);
|
|
227
|
+
|
|
202
228
|
return {
|
|
203
229
|
node,
|
|
204
230
|
account: account as InstanceOfSchema<S>,
|
|
205
231
|
done: () => {
|
|
206
232
|
node.gracefulShutdown();
|
|
233
|
+
sessionDone();
|
|
207
234
|
},
|
|
208
235
|
logOut: async () => {
|
|
209
236
|
node.gracefulShutdown();
|
|
@@ -270,6 +297,7 @@ export async function createJazzContext<
|
|
|
270
297
|
peers: options.peers,
|
|
271
298
|
crypto,
|
|
272
299
|
AccountSchema: options.AccountSchema,
|
|
300
|
+
sessionProvider: options.sessionProvider,
|
|
273
301
|
onLogOut: async () => {
|
|
274
302
|
await authSecretStorage.clearWithoutNotify();
|
|
275
303
|
},
|
|
@@ -5,9 +5,14 @@ import {
|
|
|
5
5
|
type CoValue,
|
|
6
6
|
type CoValueClass,
|
|
7
7
|
CoValueFromRaw,
|
|
8
|
+
extendContainerOwner,
|
|
8
9
|
Group,
|
|
10
|
+
type GroupRole,
|
|
9
11
|
ItemsSym,
|
|
10
12
|
LoadedAndRequired,
|
|
13
|
+
type NewInlineOwnerStrategy,
|
|
14
|
+
type RefOnCreateCallback,
|
|
15
|
+
type RefPermissions,
|
|
11
16
|
SchemaInit,
|
|
12
17
|
isCoValueClass,
|
|
13
18
|
} from "../internal.js";
|
|
@@ -94,31 +99,33 @@ export const coField = {
|
|
|
94
99
|
|
|
95
100
|
function optionalRef<C extends CoValueClass>(
|
|
96
101
|
arg: C | ((raw: InstanceType<C>["$jazz"]["raw"]) => C),
|
|
102
|
+
options: { permissions: RefPermissions },
|
|
97
103
|
): InstanceType<C> | null | undefined {
|
|
98
|
-
return ref(arg, { optional: true });
|
|
104
|
+
return ref(arg, { optional: true, permissions: options.permissions });
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
function ref<C extends CoValueClass>(
|
|
102
108
|
arg: C | ((raw: InstanceType<C>["$jazz"]["raw"]) => C),
|
|
103
|
-
options?:
|
|
109
|
+
options: { permissions?: RefPermissions },
|
|
104
110
|
): InstanceType<C> | null;
|
|
105
111
|
function ref<C extends CoValueClass>(
|
|
106
112
|
arg: C | ((raw: InstanceType<C>["$jazz"]["raw"]) => C),
|
|
107
|
-
options: { optional: true },
|
|
113
|
+
options: { optional: true; permissions?: RefPermissions },
|
|
108
114
|
): InstanceType<C> | null | undefined;
|
|
109
115
|
function ref<
|
|
110
116
|
C extends CoValueClass,
|
|
111
|
-
Options extends { optional?: boolean
|
|
117
|
+
Options extends { optional?: boolean; permissions?: RefPermissions },
|
|
112
118
|
>(
|
|
113
119
|
arg: C | ((raw: InstanceType<C>["$jazz"]["raw"]) => C),
|
|
114
|
-
options
|
|
120
|
+
options: Options,
|
|
115
121
|
): Options extends { optional: true }
|
|
116
122
|
? InstanceType<C> | null | undefined
|
|
117
123
|
: InstanceType<C> | null {
|
|
118
124
|
return {
|
|
119
125
|
[SchemaInit]: {
|
|
120
126
|
ref: arg,
|
|
121
|
-
optional: options
|
|
127
|
+
optional: options.optional || false,
|
|
128
|
+
permissions: options.permissions,
|
|
122
129
|
} satisfies Schema,
|
|
123
130
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
124
131
|
} as any;
|
|
@@ -129,6 +136,7 @@ export type EncodedAs<V> = { encoded: Encoder<V> | OptionalEncoder<V> };
|
|
|
129
136
|
export type RefEncoded<V extends CoValue> = {
|
|
130
137
|
ref: CoValueClass<V> | ((raw: RawCoValue) => CoValueClass<V>);
|
|
131
138
|
optional: boolean;
|
|
139
|
+
permissions?: RefPermissions;
|
|
132
140
|
};
|
|
133
141
|
|
|
134
142
|
export function isRefEncoded<V extends CoValue>(
|
|
@@ -158,24 +166,26 @@ export function instantiateRefEncodedFromRaw<V extends CoValue>(
|
|
|
158
166
|
*
|
|
159
167
|
* @param schema - The schema of the CoValue to create.
|
|
160
168
|
* @param init - The init values to use to create the CoValue.
|
|
161
|
-
* @param
|
|
162
|
-
*
|
|
169
|
+
* @param containerOwner - The owner of the referencing CoValue. Will be used
|
|
170
|
+
* to determine the owner of the new CoValue
|
|
171
|
+
* @param newOwnerStrategy - The strategy to use to determine the owner of the new CoValue
|
|
172
|
+
* @param onCreate - The callback to call when the new CoValue is created
|
|
163
173
|
* @returns The created CoValue.
|
|
164
174
|
*/
|
|
165
175
|
export function instantiateRefEncodedWithInit<V extends CoValue>(
|
|
166
176
|
schema: RefEncoded<V>,
|
|
167
177
|
init: any,
|
|
168
|
-
|
|
178
|
+
containerOwner: Group,
|
|
179
|
+
newOwnerStrategy: NewInlineOwnerStrategy = extendContainerOwner,
|
|
180
|
+
onCreate?: RefOnCreateCallback,
|
|
169
181
|
): V {
|
|
170
182
|
if (!isCoValueClass<V>(schema.ref)) {
|
|
171
183
|
throw Error(
|
|
172
184
|
`Cannot automatically create CoValue from value: ${JSON.stringify(init)}. Use the CoValue schema's create() method instead.`,
|
|
173
185
|
);
|
|
174
186
|
}
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const owner = new Group({ fromRaw: rawGroup });
|
|
178
|
-
owner.addMember(parentOwner);
|
|
187
|
+
const owner = newOwnerStrategy(() => Group.create(), containerOwner, init);
|
|
188
|
+
onCreate?.(owner, init);
|
|
179
189
|
// @ts-expect-error - create is a static method in all CoValue classes
|
|
180
190
|
return schema.ref.create(init, owner);
|
|
181
191
|
}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import type { JsonValue } from "cojson";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CoValueClass,
|
|
4
|
+
isCoValueClass,
|
|
5
|
+
schemaToRefPermissions,
|
|
6
|
+
getDefaultRefPermissions,
|
|
7
|
+
SchemaPermissions,
|
|
8
|
+
RefPermissions,
|
|
9
|
+
type NewInlineOwnerStrategy,
|
|
10
|
+
type CoreCoDiscriminatedUnionSchema,
|
|
11
|
+
type DiscriminableCoValueSchemas,
|
|
12
|
+
type RefOnCreateCallback,
|
|
13
|
+
} from "../../../internal.js";
|
|
3
14
|
import { coField } from "../../schema.js";
|
|
4
15
|
import { CoreCoValueSchema } from "../schemaTypes/CoValueSchema.js";
|
|
5
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
isUnionOfPrimitivesDeeply,
|
|
18
|
+
getFlattenedUnionOptions,
|
|
19
|
+
getDiscriminatorValuesForOption,
|
|
20
|
+
resolveDiscriminantValue,
|
|
21
|
+
} from "../unionUtils.js";
|
|
6
22
|
import {
|
|
7
23
|
ZodCatch,
|
|
8
24
|
ZodDefault,
|
|
@@ -76,17 +92,28 @@ export function schemaFieldToCoFieldDef(schema: SchemaField): CoFieldDef {
|
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
if (isCoValueClass(schema)) {
|
|
79
|
-
return cacheSchemaField(
|
|
95
|
+
return cacheSchemaField(
|
|
96
|
+
schema,
|
|
97
|
+
coField.ref(schema, {
|
|
98
|
+
permissions: getDefaultRefPermissions(),
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
80
101
|
} else if (isCoValueSchema(schema)) {
|
|
81
102
|
if (schema.builtin === "CoOptional") {
|
|
82
103
|
return cacheSchemaField(
|
|
83
104
|
schema,
|
|
84
105
|
coField.ref(schema.getCoValueClass(), {
|
|
85
106
|
optional: true,
|
|
107
|
+
permissions: schemaFieldPermissions(schema),
|
|
86
108
|
}),
|
|
87
109
|
);
|
|
88
110
|
}
|
|
89
|
-
return cacheSchemaField(
|
|
111
|
+
return cacheSchemaField(
|
|
112
|
+
schema,
|
|
113
|
+
coField.ref(schema.getCoValueClass(), {
|
|
114
|
+
permissions: schemaFieldPermissions(schema),
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
90
117
|
} else {
|
|
91
118
|
if ("_zod" in schema) {
|
|
92
119
|
const zodSchemaDef = schema._zod.def;
|
|
@@ -228,3 +255,77 @@ export function schemaFieldToCoFieldDef(schema: SchemaField): CoFieldDef {
|
|
|
228
255
|
}
|
|
229
256
|
}
|
|
230
257
|
}
|
|
258
|
+
|
|
259
|
+
function schemaFieldPermissions(schema: CoreCoValueSchema): RefPermissions {
|
|
260
|
+
if (schema.builtin === "CoOptional") {
|
|
261
|
+
return schemaFieldPermissions((schema as any).innerType);
|
|
262
|
+
}
|
|
263
|
+
if (schema.builtin === "CoDiscriminatedUnion") {
|
|
264
|
+
return discriminatedUnionFieldPermissions(
|
|
265
|
+
schema as CoreCoDiscriminatedUnionSchema<DiscriminableCoValueSchemas>,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return "permissions" in schema
|
|
269
|
+
? schemaToRefPermissions(schema.permissions as SchemaPermissions)
|
|
270
|
+
: getDefaultRefPermissions();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function discriminatedUnionFieldPermissions(
|
|
274
|
+
schema: CoreCoDiscriminatedUnionSchema<DiscriminableCoValueSchemas>,
|
|
275
|
+
): RefPermissions {
|
|
276
|
+
const discriminatorKey = schema.getDefinition().discriminator;
|
|
277
|
+
const allOptions = getFlattenedUnionOptions(schema);
|
|
278
|
+
|
|
279
|
+
const valueToStrategy = new Map<unknown, RefPermissions>();
|
|
280
|
+
for (const option of allOptions) {
|
|
281
|
+
const optionPermissions = schemaFieldPermissions(option);
|
|
282
|
+
const discriminatorValues = getDiscriminatorValuesForOption(
|
|
283
|
+
option,
|
|
284
|
+
discriminatorKey,
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
if (!discriminatorValues) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
for (const value of discriminatorValues) {
|
|
292
|
+
if (!valueToStrategy.has(value)) {
|
|
293
|
+
valueToStrategy.set(value, optionPermissions);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const fallbackStrategy = getDefaultRefPermissions();
|
|
299
|
+
|
|
300
|
+
const newInlineOwnerStrategy: NewInlineOwnerStrategy = (
|
|
301
|
+
createNewGroup,
|
|
302
|
+
containerOwner,
|
|
303
|
+
init,
|
|
304
|
+
) => {
|
|
305
|
+
const discriminantValue = resolveDiscriminantValue(init, discriminatorKey);
|
|
306
|
+
const strategy =
|
|
307
|
+
discriminantValue !== undefined
|
|
308
|
+
? valueToStrategy.get(discriminantValue)
|
|
309
|
+
: undefined;
|
|
310
|
+
|
|
311
|
+
const effectiveStrategy = strategy ?? fallbackStrategy;
|
|
312
|
+
return effectiveStrategy.newInlineOwnerStrategy(
|
|
313
|
+
createNewGroup,
|
|
314
|
+
containerOwner,
|
|
315
|
+
init,
|
|
316
|
+
);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const onCreate: RefOnCreateCallback = (newGroup, init) => {
|
|
320
|
+
const discriminantValue = resolveDiscriminantValue(init, discriminatorKey);
|
|
321
|
+
const strategy =
|
|
322
|
+
discriminantValue !== undefined
|
|
323
|
+
? valueToStrategy.get(discriminantValue)
|
|
324
|
+
: undefined;
|
|
325
|
+
|
|
326
|
+
const effectiveStrategy = strategy ?? fallbackStrategy;
|
|
327
|
+
effectiveStrategy.onCreate?.(newGroup, init);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
return { newInlineOwnerStrategy, onCreate };
|
|
331
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Account, Group, TypeSym, type GroupRole } from "../../internal.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines how a nested CoValue’s owner is obtained when creating CoValues from JSON.
|
|
5
|
+
*
|
|
6
|
+
* This configuration is not used when using an explicit .create() for nested CoValues.
|
|
7
|
+
* In that case, {@link SchemaPermissions.default} is used.
|
|
8
|
+
*/
|
|
9
|
+
export type OnInlineCreateOptions =
|
|
10
|
+
/**
|
|
11
|
+
* Always create a new group for CoValues created inline
|
|
12
|
+
*/
|
|
13
|
+
| "newGroup"
|
|
14
|
+
/**
|
|
15
|
+
* Use the same owner as the container CoValue
|
|
16
|
+
*/
|
|
17
|
+
| "sameAsContainer"
|
|
18
|
+
/**
|
|
19
|
+
* Create a new group that includes the container CoValue's owner as a member (effectively inheriting
|
|
20
|
+
* all permissions from the container)
|
|
21
|
+
*/
|
|
22
|
+
| "extendsContainer"
|
|
23
|
+
/**
|
|
24
|
+
* Similar to "extendsContainer", but allows overriding the role of the container CoValue's owner
|
|
25
|
+
*/
|
|
26
|
+
| { extendsContainer: GroupRole }
|
|
27
|
+
/**
|
|
28
|
+
* Create a new group and configure it as needed
|
|
29
|
+
*/
|
|
30
|
+
| InlineGroupConfigurationCallback;
|
|
31
|
+
|
|
32
|
+
export type InlineGroupConfigurationCallback = (
|
|
33
|
+
newGroup: Group,
|
|
34
|
+
context: { containerOwner: Group },
|
|
35
|
+
) => void;
|
|
36
|
+
|
|
37
|
+
export type OnCreateCallback = (newGroup: Group) => void;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Internal callback type used by RefPermissions that includes init for discriminated union support.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export type RefOnCreateCallback = (newGroup: Group, init?: unknown) => void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Permissions to be used when creating or composing CoValues
|
|
47
|
+
* @param default - default owner to be used when creating a CoValue without providing an explicit owner.
|
|
48
|
+
* @param onInlineCreate - defines how a nested CoValue's owner is obtained when creating CoValues from JSON.
|
|
49
|
+
* @param onCreate - callback that runs every time a CoValue is created. Can be used to configure the CoValue's owner.
|
|
50
|
+
* Runs both when creating CoValues with `.create()` and when creating CoValues from JSON.
|
|
51
|
+
* @default { default: () => Group.create(), onInlineCreate: "extendsContainer" }
|
|
52
|
+
*/
|
|
53
|
+
export type SchemaPermissions = {
|
|
54
|
+
/**
|
|
55
|
+
* default owner to be used when creating a CoValue without providing an explicit owner.
|
|
56
|
+
*/
|
|
57
|
+
default?: () => Group;
|
|
58
|
+
/**
|
|
59
|
+
* Defines how a nested CoValue's owner is obtained when creating CoValues from JSON.
|
|
60
|
+
*/
|
|
61
|
+
onInlineCreate?: OnInlineCreateOptions;
|
|
62
|
+
/**
|
|
63
|
+
* callback that runs every time a CoValue is created. Can be used to configure the CoValue's owner.
|
|
64
|
+
* Runs both when creating CoValues with `.create()` and when creating CoValues from JSON.
|
|
65
|
+
*/
|
|
66
|
+
onCreate?: OnCreateCallback;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export let DEFAULT_SCHEMA_PERMISSIONS: SchemaPermissions = {
|
|
70
|
+
default: () => Group.create(),
|
|
71
|
+
onInlineCreate: "extendsContainer",
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Update the default schema permissions for all new CoValue schemas.
|
|
76
|
+
* Schemas created before calling this function will not be affected.
|
|
77
|
+
*/
|
|
78
|
+
export function setDefaultSchemaPermissions(permissions: SchemaPermissions) {
|
|
79
|
+
DEFAULT_SCHEMA_PERMISSIONS = {
|
|
80
|
+
...DEFAULT_SCHEMA_PERMISSIONS,
|
|
81
|
+
...permissions,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Parsed {@link SchemaPermissions}, used by CoValue classes to set up permissions for referenced CoValues.
|
|
87
|
+
*/
|
|
88
|
+
export type RefPermissions = {
|
|
89
|
+
newInlineOwnerStrategy: NewInlineOwnerStrategy;
|
|
90
|
+
onCreate?: RefOnCreateCallback;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* A function that creates a new owner for a new CoValue created inline.
|
|
95
|
+
* @param createNewGroup - A function that creates a new group.
|
|
96
|
+
* @param containerOwner - The owner of the container CoValue.
|
|
97
|
+
* @param init - The value used to create the new CoValue. Necessary to determine the concrete
|
|
98
|
+
* strategy to use in discriminated unions.
|
|
99
|
+
* @returns The new owner.
|
|
100
|
+
*/
|
|
101
|
+
export type NewInlineOwnerStrategy = (
|
|
102
|
+
createNewGroup: () => Group,
|
|
103
|
+
containerOwner: Group,
|
|
104
|
+
init?: unknown,
|
|
105
|
+
) => Group;
|
|
106
|
+
|
|
107
|
+
export const extendContainerOwnerFactory =
|
|
108
|
+
(roleOverride?: GroupRole): NewInlineOwnerStrategy =>
|
|
109
|
+
(createNewGroup: () => Group, containerOwner: Group): Group => {
|
|
110
|
+
const node = containerOwner.$jazz.localNode;
|
|
111
|
+
const rawGroup = node.createGroup();
|
|
112
|
+
const owner = new Group({ fromRaw: rawGroup });
|
|
113
|
+
owner.addMember(containerOwner, roleOverride);
|
|
114
|
+
return owner;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A function that creates a new owner for a new CoValue by extending the container CoValue's owner
|
|
119
|
+
* (without overriding its role)
|
|
120
|
+
*/
|
|
121
|
+
export const extendContainerOwner = extendContainerOwnerFactory();
|
|
122
|
+
|
|
123
|
+
export function schemaToRefPermissions(
|
|
124
|
+
permissions: SchemaPermissions,
|
|
125
|
+
): RefPermissions {
|
|
126
|
+
const newInlineOwnerStrategy = parseOnInlineCreate(
|
|
127
|
+
permissions.onInlineCreate,
|
|
128
|
+
);
|
|
129
|
+
const onCreate: RefOnCreateCallback | undefined = permissions.onCreate
|
|
130
|
+
? (newGroup, _init) => permissions.onCreate?.(newGroup)
|
|
131
|
+
: undefined;
|
|
132
|
+
return {
|
|
133
|
+
newInlineOwnerStrategy,
|
|
134
|
+
onCreate,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function parseOnInlineCreate(
|
|
139
|
+
onInlineCreate?: OnInlineCreateOptions,
|
|
140
|
+
): NewInlineOwnerStrategy {
|
|
141
|
+
if (!onInlineCreate || onInlineCreate === "extendsContainer") {
|
|
142
|
+
return extendContainerOwner;
|
|
143
|
+
}
|
|
144
|
+
if (
|
|
145
|
+
typeof onInlineCreate === "object" &&
|
|
146
|
+
"extendsContainer" in onInlineCreate
|
|
147
|
+
) {
|
|
148
|
+
return extendContainerOwnerFactory(onInlineCreate.extendsContainer);
|
|
149
|
+
}
|
|
150
|
+
if (onInlineCreate === "newGroup") {
|
|
151
|
+
return (createNewGroup) => createNewGroup();
|
|
152
|
+
}
|
|
153
|
+
if (onInlineCreate === "sameAsContainer") {
|
|
154
|
+
return (_createNewGroup, containerOwner) => containerOwner;
|
|
155
|
+
}
|
|
156
|
+
return (createNewGroup, containerOwner) => {
|
|
157
|
+
const newGroup = createNewGroup();
|
|
158
|
+
onInlineCreate(newGroup, { containerOwner });
|
|
159
|
+
return newGroup;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function getDefaultRefPermissions(): RefPermissions {
|
|
164
|
+
return schemaToRefPermissions(DEFAULT_SCHEMA_PERMISSIONS);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function withSchemaPermissions<T extends { owner?: Account | Group }>(
|
|
168
|
+
options?: T | Account | Group,
|
|
169
|
+
schemaPermissions?: SchemaPermissions,
|
|
170
|
+
): T & { onCreate?: OnCreateCallback } {
|
|
171
|
+
const onCreate = schemaPermissions?.onCreate;
|
|
172
|
+
if (!options) {
|
|
173
|
+
const owner = schemaPermissions?.default?.() ?? Group.create();
|
|
174
|
+
return { owner, onCreate } as T & { onCreate?: OnCreateCallback };
|
|
175
|
+
}
|
|
176
|
+
if (TypeSym in options) {
|
|
177
|
+
return { owner: options, onCreate } as T & {
|
|
178
|
+
onCreate?: OnCreateCallback;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const owner =
|
|
182
|
+
options.owner ?? schemaPermissions?.default?.() ?? Group.create();
|
|
183
|
+
return {
|
|
184
|
+
...options,
|
|
185
|
+
owner,
|
|
186
|
+
onCreate,
|
|
187
|
+
} as T & { onCreate?: OnCreateCallback };
|
|
188
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
BranchDefinition,
|
|
5
5
|
CoFeed,
|
|
6
6
|
Group,
|
|
7
|
+
hydrateCoreCoValueSchema,
|
|
7
8
|
Settled,
|
|
8
9
|
RefsToResolve,
|
|
9
10
|
RefsToResolveStrict,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
coOptionalDefiner,
|
|
13
14
|
parseSubscribeRestArgs,
|
|
14
15
|
unstable_mergeBranchWithResolve,
|
|
16
|
+
withSchemaPermissions,
|
|
15
17
|
} from "../../../internal.js";
|
|
16
18
|
import { AnonymousJazzAgent } from "../../anonymousJazzAgent.js";
|
|
17
19
|
import { CoFeedSchemaInit } from "../typeConverters/CoFieldSchemaInit.js";
|
|
@@ -20,6 +22,10 @@ import { InstanceOrPrimitiveOfSchemaCoValuesMaybeLoaded } from "../typeConverter
|
|
|
20
22
|
import { CoOptionalSchema } from "./CoOptionalSchema.js";
|
|
21
23
|
import { CoreCoValueSchema, CoreResolveQuery } from "./CoValueSchema.js";
|
|
22
24
|
import { withSchemaResolveQuery } from "../../schemaUtils.js";
|
|
25
|
+
import {
|
|
26
|
+
DEFAULT_SCHEMA_PERMISSIONS,
|
|
27
|
+
SchemaPermissions,
|
|
28
|
+
} from "../schemaPermissions.js";
|
|
23
29
|
|
|
24
30
|
export class CoFeedSchema<
|
|
25
31
|
T extends AnyZodOrCoValueSchema,
|
|
@@ -36,6 +42,12 @@ export class CoFeedSchema<
|
|
|
36
42
|
*/
|
|
37
43
|
resolveQuery: DefaultResolveQuery = true as DefaultResolveQuery;
|
|
38
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Permissions to be used when creating or composing CoValues
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
permissions: SchemaPermissions = DEFAULT_SCHEMA_PERMISSIONS;
|
|
50
|
+
|
|
39
51
|
constructor(
|
|
40
52
|
public element: T,
|
|
41
53
|
private coValueClass: typeof CoFeed,
|
|
@@ -54,7 +66,14 @@ export class CoFeedSchema<
|
|
|
54
66
|
init: CoFeedSchemaInit<T>,
|
|
55
67
|
options?: { owner: Account | Group } | Account | Group,
|
|
56
68
|
): CoFeedInstance<T> {
|
|
57
|
-
|
|
69
|
+
const optionsWithPermissions = withSchemaPermissions(
|
|
70
|
+
options,
|
|
71
|
+
this.permissions,
|
|
72
|
+
);
|
|
73
|
+
return this.coValueClass.create(
|
|
74
|
+
init as any,
|
|
75
|
+
optionsWithPermissions,
|
|
76
|
+
) as CoFeedInstance<T>;
|
|
58
77
|
}
|
|
59
78
|
|
|
60
79
|
load<
|
|
@@ -146,8 +165,32 @@ export class CoFeedSchema<
|
|
|
146
165
|
>(
|
|
147
166
|
resolveQuery: RefsToResolveStrict<CoFeedInstanceCoValuesMaybeLoaded<T>, R>,
|
|
148
167
|
): CoFeedSchema<T, R> {
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
return this.copy({ resolveQuery: resolveQuery as R });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Configure permissions to be used when creating or composing CoValues
|
|
173
|
+
*/
|
|
174
|
+
withPermissions(
|
|
175
|
+
permissions: SchemaPermissions,
|
|
176
|
+
): CoFeedSchema<T, DefaultResolveQuery> {
|
|
177
|
+
return this.copy({ permissions });
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private copy<ResolveQuery extends CoreResolveQuery = DefaultResolveQuery>({
|
|
181
|
+
permissions,
|
|
182
|
+
resolveQuery,
|
|
183
|
+
}: {
|
|
184
|
+
permissions?: SchemaPermissions;
|
|
185
|
+
resolveQuery?: ResolveQuery;
|
|
186
|
+
}): CoFeedSchema<T, ResolveQuery> {
|
|
187
|
+
const coreSchema = createCoreCoFeedSchema(this.element);
|
|
188
|
+
// @ts-expect-error
|
|
189
|
+
const copy: CoFeedSchema<T, ResolveQuery> =
|
|
190
|
+
hydrateCoreCoValueSchema(coreSchema);
|
|
191
|
+
// @ts-expect-error TS cannot infer that the resolveQuery type is valid
|
|
192
|
+
copy.resolveQuery = resolveQuery ?? this.resolveQuery;
|
|
193
|
+
copy.permissions = permissions ?? this.permissions;
|
|
151
194
|
return copy;
|
|
152
195
|
}
|
|
153
196
|
}
|