jazz-tools 0.17.14 → 0.18.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/.svelte-kit/__package__/jazz.class.svelte.js +1 -1
- package/.svelte-kit/__package__/media/image.svelte +3 -9
- package/.svelte-kit/__package__/media/image.svelte.d.ts +1 -6
- package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
- package/.svelte-kit/__package__/media/image.types.d.ts +7 -0
- package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -0
- package/.svelte-kit/__package__/media/image.types.js +1 -0
- package/.svelte-kit/__package__/tests/media/image.svelte.test.js +31 -31
- package/.turbo/turbo-build.log +50 -50
- package/CHANGELOG.md +31 -0
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-LZOF6WP5.js → chunk-HJ3GTGY7.js} +1320 -1018
- package/dist/chunk-HJ3GTGY7.js.map +1 -0
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/dist/inspector/{custom-element-ZSNTCECD.js → custom-element-WCY6D3QJ.js} +3 -3
- package/dist/inspector/{custom-element-ZSNTCECD.js.map → custom-element-WCY6D3QJ.js.map} +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/media/{chunk-E5J3WLQW.js → chunk-KR2V6X2N.js} +14 -9
- package/dist/media/chunk-KR2V6X2N.js.map +1 -0
- package/dist/media/create-image.d.ts +6 -6
- package/dist/media/index.browser.d.ts +6 -6
- package/dist/media/index.browser.js +1 -1
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/index.native.d.ts +6 -6
- package/dist/media/index.native.js +1 -1
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/prosemirror/index.js +2 -2
- package/dist/prosemirror/index.js.map +1 -1
- package/dist/react/index.js +7 -5
- package/dist/react/index.js.map +1 -1
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +4658 -23
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native-core/index.js +1 -1
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/svelte/jazz.class.svelte.js +1 -1
- package/dist/svelte/media/image.svelte +3 -9
- package/dist/svelte/media/image.svelte.d.ts +1 -6
- package/dist/svelte/media/image.svelte.d.ts.map +1 -1
- package/dist/svelte/media/image.types.d.ts +7 -0
- package/dist/svelte/media/image.types.d.ts.map +1 -0
- package/dist/svelte/media/image.types.js +1 -0
- package/dist/svelte/tests/media/image.svelte.test.js +31 -31
- package/dist/testing.js +18 -14
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/CoFieldInit.d.ts +13 -0
- package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -0
- package/dist/tools/coValues/CoValueBase.d.ts +18 -15
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/coValues/account.d.ts +100 -46
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coFeed.d.ts +78 -62
- package/dist/tools/coValues/coFeed.d.ts.map +1 -1
- package/dist/tools/coValues/coList.d.ts +212 -99
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +200 -192
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/coPlainText.d.ts +30 -22
- package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +13 -13
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/extensions/imageDef.d.ts +1 -1
- package/dist/tools/coValues/group.d.ts +32 -32
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/inbox.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +18 -17
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/profile.d.ts +6 -5
- package/dist/tools/coValues/profile.d.ts.map +1 -1
- package/dist/tools/coValues/schemaUnion.d.ts +3 -3
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/anonymousJazzAgent.d.ts +2 -1
- package/dist/tools/implementation/anonymousJazzAgent.d.ts.map +1 -1
- package/dist/tools/implementation/schema.d.ts +5 -5
- package/dist/tools/implementation/schema.d.ts.map +1 -1
- package/dist/tools/implementation/symbols.d.ts +2 -0
- package/dist/tools/implementation/symbols.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +2 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +6 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +8 -3
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +12 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +13 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +11 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +4 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +4 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/{CoFieldInit.d.ts → CoFieldSchemaInit.d.ts} +7 -7
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +4 -4
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +4 -4
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts +2 -2
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +2 -1
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/lib/migration.d.ts +1 -1
- package/dist/tools/lib/migration.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/subscribe/index.d.ts +1 -1
- package/dist/tools/subscribe/index.d.ts.map +1 -1
- package/dist/tools/subscribe/utils.d.ts +2 -2
- package/dist/tools/subscribe/utils.d.ts.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/utils.d.ts +2 -6
- package/dist/tools/tests/utils.d.ts.map +1 -1
- package/dist/worker/index.js +3 -3
- package/dist/worker/index.js.map +1 -1
- package/package.json +4 -4
- package/src/browser/auth/PasskeyAuth.ts +2 -2
- package/src/browser/createBrowserContext.ts +2 -2
- package/src/browser/tests/PasskeyAuth.test.ts +2 -2
- package/src/inspector/custom-element.tsx +2 -2
- package/src/inspector/viewer/new-app.tsx +1 -1
- package/src/media/create-image.test.ts +7 -7
- package/src/media/create-image.ts +5 -3
- package/src/media/index.ts +1 -1
- package/src/media/utils.test.ts +72 -66
- package/src/media/utils.ts +9 -6
- package/src/prosemirror/lib/plugin.ts +1 -1
- package/src/prosemirror/lib/sync.ts +1 -1
- package/src/prosemirror/tests/plugin.test.ts +4 -4
- package/src/react/media/image.tsx +2 -2
- package/src/react/tests/media/image.test.tsx +52 -32
- package/src/react-core/hooks.ts +11 -5
- package/src/react-core/tests/useAccount.test.ts +16 -22
- package/src/react-core/tests/useCoState.test.ts +19 -19
- package/src/react-core/tests/useInboxSender.test.ts +5 -2
- package/src/react-core/tests/usePassPhraseAuth.test.ts +6 -6
- package/src/react-native-core/media/image.tsx +1 -1
- package/src/svelte/jazz.class.svelte.ts +1 -1
- package/src/svelte/media/image.svelte +3 -9
- package/src/svelte/media/image.types.ts +7 -0
- package/src/svelte/tests/media/image.svelte.test.ts +34 -32
- package/src/tools/auth/DemoAuth.ts +2 -2
- package/src/tools/auth/PassphraseAuth.ts +2 -2
- package/src/tools/auth/clerk/index.ts +2 -2
- package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +1 -1
- package/src/tools/coValues/CoFieldInit.ts +20 -0
- package/src/tools/coValues/CoValueBase.ts +40 -60
- package/src/tools/coValues/account.ts +306 -232
- package/src/tools/coValues/coFeed.ts +185 -153
- package/src/tools/coValues/coList.ts +507 -334
- package/src/tools/coValues/coMap.ts +420 -286
- package/src/tools/coValues/coPlainText.ts +94 -110
- package/src/tools/coValues/deepLoading.ts +13 -13
- package/src/tools/coValues/group.ts +100 -114
- package/src/tools/coValues/inbox.ts +16 -14
- package/src/tools/coValues/interfaces.ts +49 -31
- package/src/tools/coValues/profile.ts +8 -6
- package/src/tools/coValues/request.ts +9 -9
- package/src/tools/coValues/schemaUnion.ts +11 -5
- package/src/tools/exports.ts +1 -1
- package/src/tools/implementation/ContextManager.ts +4 -4
- package/src/tools/implementation/anonymousJazzAgent.ts +2 -1
- package/src/tools/implementation/createContext.ts +1 -1
- package/src/tools/implementation/devtoolsFormatters.ts +9 -9
- package/src/tools/implementation/invites.ts +2 -2
- package/src/tools/implementation/schema.ts +7 -7
- package/src/tools/implementation/symbols.ts +3 -0
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -2
- package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +11 -2
- package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +18 -7
- package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +17 -7
- package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +20 -11
- package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +19 -2
- package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +6 -0
- package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +6 -0
- package/src/tools/implementation/zodSchema/typeConverters/{CoFieldInit.ts → CoFieldSchemaInit.ts} +11 -11
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +4 -4
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +4 -4
- package/src/tools/implementation/zodSchema/zodCo.ts +2 -2
- package/src/tools/internal.ts +2 -1
- package/src/tools/lib/migration.ts +5 -5
- package/src/tools/subscribe/SubscriptionScope.ts +32 -24
- package/src/tools/subscribe/index.ts +4 -4
- package/src/tools/subscribe/utils.ts +11 -11
- package/src/tools/testing.ts +17 -13
- package/src/tools/tests/ContextManager.test.ts +68 -57
- package/src/tools/tests/PassphraseAuth.test.ts +2 -2
- package/src/tools/tests/account.test.ts +139 -69
- package/src/tools/tests/coDiscriminatedUnion.test-d.ts +12 -6
- package/src/tools/tests/coDiscriminatedUnion.test.ts +26 -17
- package/src/tools/tests/coFeed.test-d.ts +18 -17
- package/src/tools/tests/coFeed.test.ts +108 -97
- package/src/tools/tests/coList.test-d.ts +18 -23
- package/src/tools/tests/coList.test.ts +350 -165
- package/src/tools/tests/coMap.record.test-d.ts +9 -13
- package/src/tools/tests/coMap.record.test.ts +37 -23
- package/src/tools/tests/coMap.test-d.ts +43 -21
- package/src/tools/tests/coMap.test.ts +360 -182
- package/src/tools/tests/coOptional.test.ts +28 -13
- package/src/tools/tests/coPlainText.test.ts +15 -15
- package/src/tools/tests/createContext.test.ts +14 -14
- package/src/tools/tests/deepLoading.test.ts +95 -94
- package/src/tools/tests/exportImport.test.ts +61 -41
- package/src/tools/tests/groupsAndAccounts.test.ts +333 -116
- package/src/tools/tests/inbox.test.ts +22 -17
- package/src/tools/tests/interfaces.test.ts +12 -11
- package/src/tools/tests/invites.test.ts +6 -4
- package/src/tools/tests/load.test.ts +20 -18
- package/src/tools/tests/patterns/notifications.test.ts +6 -6
- package/src/tools/tests/patterns/quest.test.ts +3 -3
- package/src/tools/tests/patterns/requestToJoin.test.ts +22 -22
- package/src/tools/tests/request.test.ts +38 -39
- package/src/tools/tests/schemaUnion.test.ts +64 -10
- package/src/tools/tests/subscribe.test.ts +64 -64
- package/src/tools/tests/testing.test.ts +5 -9
- package/src/tools/tests/utils.ts +3 -3
- package/src/tools/tests/zod.test.ts +3 -3
- package/src/worker/index.ts +3 -3
- package/dist/chunk-LZOF6WP5.js.map +0 -1
- package/dist/media/chunk-E5J3WLQW.js.map +0 -1
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts.map +0 -1
package/dist/react-core/index.js
CHANGED
@@ -12,10 +12,10 @@ import React, {
|
|
12
12
|
useSyncExternalStore
|
13
13
|
} from "react";
|
14
14
|
import {
|
15
|
-
Account,
|
15
|
+
Account as Account13,
|
16
16
|
InboxSender,
|
17
|
-
SubscriptionScope,
|
18
|
-
coValueClassFromCoValueClassOrSchema
|
17
|
+
SubscriptionScope as SubscriptionScope2,
|
18
|
+
coValueClassFromCoValueClassOrSchema as coValueClassFromCoValueClassOrSchema2
|
19
19
|
} from "jazz-tools";
|
20
20
|
|
21
21
|
// src/react-core/utils.ts
|
@@ -27,6 +27,4635 @@ function getCurrentAccountFromContextManager(contextManager) {
|
|
27
27
|
return "me" in context ? context.me : context.guest;
|
28
28
|
}
|
29
29
|
|
30
|
+
// src/tools/coValues/interfaces.ts
|
31
|
+
function isCoValueClass(value) {
|
32
|
+
return typeof value === "function" && value.fromRaw !== void 0;
|
33
|
+
}
|
34
|
+
function loadCoValueWithoutMe(cls, id, options) {
|
35
|
+
return loadCoValue(cls, id, {
|
36
|
+
...options,
|
37
|
+
loadAs: options?.loadAs ?? activeAccountContext.get()
|
38
|
+
});
|
39
|
+
}
|
40
|
+
function loadCoValue(cls, id, options) {
|
41
|
+
return new Promise((resolve) => {
|
42
|
+
subscribeToCoValue(
|
43
|
+
cls,
|
44
|
+
id,
|
45
|
+
{
|
46
|
+
resolve: options.resolve,
|
47
|
+
loadAs: options.loadAs,
|
48
|
+
syncResolution: true,
|
49
|
+
skipRetry: options.skipRetry,
|
50
|
+
onUnavailable: () => {
|
51
|
+
resolve(null);
|
52
|
+
},
|
53
|
+
onUnauthorized: () => {
|
54
|
+
resolve(null);
|
55
|
+
}
|
56
|
+
},
|
57
|
+
(value, unsubscribe) => {
|
58
|
+
resolve(value);
|
59
|
+
unsubscribe();
|
60
|
+
}
|
61
|
+
);
|
62
|
+
});
|
63
|
+
}
|
64
|
+
async function ensureCoValueLoaded(existing, options) {
|
65
|
+
const response = await loadCoValue(
|
66
|
+
existing.constructor,
|
67
|
+
existing.$jazz.id,
|
68
|
+
{
|
69
|
+
loadAs: existing.$jazz.loadedAs,
|
70
|
+
resolve: options?.resolve
|
71
|
+
}
|
72
|
+
);
|
73
|
+
if (!response) {
|
74
|
+
throw new Error("Failed to deeply load CoValue " + existing.$jazz.id);
|
75
|
+
}
|
76
|
+
return response;
|
77
|
+
}
|
78
|
+
function parseSubscribeRestArgs(args) {
|
79
|
+
if (args.length === 2) {
|
80
|
+
if (typeof args[0] === "object" && args[0] && typeof args[1] === "function") {
|
81
|
+
return {
|
82
|
+
options: {
|
83
|
+
resolve: args[0].resolve,
|
84
|
+
loadAs: args[0].loadAs,
|
85
|
+
onUnauthorized: args[0].onUnauthorized,
|
86
|
+
onUnavailable: args[0].onUnavailable
|
87
|
+
},
|
88
|
+
listener: args[1]
|
89
|
+
};
|
90
|
+
} else {
|
91
|
+
throw new Error("Invalid arguments");
|
92
|
+
}
|
93
|
+
} else {
|
94
|
+
if (typeof args[0] === "function") {
|
95
|
+
return { options: {}, listener: args[0] };
|
96
|
+
} else {
|
97
|
+
throw new Error("Invalid arguments");
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
function subscribeToCoValueWithoutMe(cls, id, options, listener) {
|
102
|
+
return subscribeToCoValue(
|
103
|
+
cls,
|
104
|
+
id,
|
105
|
+
{
|
106
|
+
...options,
|
107
|
+
loadAs: options.loadAs ?? activeAccountContext.get()
|
108
|
+
},
|
109
|
+
listener
|
110
|
+
);
|
111
|
+
}
|
112
|
+
function subscribeToCoValue(cls, id, options, listener) {
|
113
|
+
const loadAs = options.loadAs ?? activeAccountContext.get();
|
114
|
+
const node = "node" in loadAs ? loadAs.node : loadAs.$jazz.localNode;
|
115
|
+
const resolve = options.resolve ?? true;
|
116
|
+
let unsubscribed = false;
|
117
|
+
const rootNode = new SubscriptionScope(
|
118
|
+
node,
|
119
|
+
resolve,
|
120
|
+
id,
|
121
|
+
{
|
122
|
+
ref: cls,
|
123
|
+
optional: false
|
124
|
+
},
|
125
|
+
options.skipRetry
|
126
|
+
);
|
127
|
+
const handleUpdate = (value) => {
|
128
|
+
if (unsubscribed) return;
|
129
|
+
if (value.type === "unavailable") {
|
130
|
+
options.onUnavailable?.();
|
131
|
+
console.error(value.toString());
|
132
|
+
} else if (value.type === "unauthorized") {
|
133
|
+
options.onUnauthorized?.();
|
134
|
+
console.error(value.toString());
|
135
|
+
} else if (value.type === "loaded") {
|
136
|
+
listener(value.value, unsubscribe);
|
137
|
+
}
|
138
|
+
};
|
139
|
+
let shouldDefer = !options.syncResolution;
|
140
|
+
rootNode.setListener((value) => {
|
141
|
+
if (shouldDefer) {
|
142
|
+
shouldDefer = false;
|
143
|
+
Promise.resolve().then(() => {
|
144
|
+
handleUpdate(value);
|
145
|
+
});
|
146
|
+
} else {
|
147
|
+
handleUpdate(value);
|
148
|
+
}
|
149
|
+
});
|
150
|
+
function unsubscribe() {
|
151
|
+
unsubscribed = true;
|
152
|
+
rootNode.destroy();
|
153
|
+
}
|
154
|
+
return unsubscribe;
|
155
|
+
}
|
156
|
+
function subscribeToExistingCoValue(existing, options, listener) {
|
157
|
+
return subscribeToCoValue(
|
158
|
+
existing.constructor,
|
159
|
+
existing.$jazz.id,
|
160
|
+
{
|
161
|
+
loadAs: existing.$jazz.loadedAs,
|
162
|
+
resolve: options?.resolve,
|
163
|
+
onUnavailable: options?.onUnavailable,
|
164
|
+
onUnauthorized: options?.onUnauthorized
|
165
|
+
},
|
166
|
+
listener
|
167
|
+
);
|
168
|
+
}
|
169
|
+
function isAccountInstance(instance) {
|
170
|
+
if (typeof instance !== "object" || instance === null) {
|
171
|
+
return false;
|
172
|
+
}
|
173
|
+
return TypeSym in instance && instance[TypeSym] === "Account";
|
174
|
+
}
|
175
|
+
function parseCoValueCreateOptions(options) {
|
176
|
+
const Group16 = RegisteredSchemas["Group"];
|
177
|
+
if (!options) {
|
178
|
+
return { owner: Group16.create(), uniqueness: void 0 };
|
179
|
+
}
|
180
|
+
if (TypeSym in options) {
|
181
|
+
if (options[TypeSym] === "Account") {
|
182
|
+
return { owner: accountOrGroupToGroup(options), uniqueness: void 0 };
|
183
|
+
} else if (options[TypeSym] === "Group") {
|
184
|
+
return { owner: options, uniqueness: void 0 };
|
185
|
+
}
|
186
|
+
}
|
187
|
+
const uniqueness = options.unique ? { uniqueness: options.unique } : void 0;
|
188
|
+
const opts = {
|
189
|
+
owner: options.owner ? accountOrGroupToGroup(options.owner) : Group16.create(),
|
190
|
+
uniqueness
|
191
|
+
};
|
192
|
+
return opts;
|
193
|
+
}
|
194
|
+
function accountOrGroupToGroup(accountOrGroup) {
|
195
|
+
if (accountOrGroup[TypeSym] === "Group") {
|
196
|
+
return accountOrGroup;
|
197
|
+
}
|
198
|
+
return RegisteredSchemas["Group"].fromRaw(accountOrGroup.$jazz.raw);
|
199
|
+
}
|
200
|
+
function parseGroupCreateOptions(options) {
|
201
|
+
if (!options) {
|
202
|
+
return { owner: activeAccountContext.get() };
|
203
|
+
}
|
204
|
+
return TypeSym in options && isAccountInstance(options) ? { owner: options } : { owner: options.owner ?? activeAccountContext.get() };
|
205
|
+
}
|
206
|
+
|
207
|
+
// src/tools/coValues/CoValueBase.ts
|
208
|
+
import { ControlledAccount } from "cojson";
|
209
|
+
var CoValueBase = class {
|
210
|
+
/** @category Internals */
|
211
|
+
static fromRaw(raw) {
|
212
|
+
return new this({ fromRaw: raw });
|
213
|
+
}
|
214
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
215
|
+
toJSON() {
|
216
|
+
return {
|
217
|
+
id: this.$jazz.id,
|
218
|
+
type: this[TypeSym],
|
219
|
+
error: "unknown CoValue class"
|
220
|
+
};
|
221
|
+
}
|
222
|
+
[inspect2]() {
|
223
|
+
return this.toJSON();
|
224
|
+
}
|
225
|
+
};
|
226
|
+
var CoValueJazzApi = class {
|
227
|
+
constructor(coValue) {
|
228
|
+
this.coValue = coValue;
|
229
|
+
Object.defineProperty(this, "_instanceID", {
|
230
|
+
value: `instance-${Math.random().toString(36).slice(2)}`,
|
231
|
+
enumerable: false
|
232
|
+
});
|
233
|
+
}
|
234
|
+
/** @internal */
|
235
|
+
get localNode() {
|
236
|
+
return this.raw.core.node;
|
237
|
+
}
|
238
|
+
/** @private */
|
239
|
+
get loadedAs() {
|
240
|
+
const agent = this.localNode.getCurrentAgent();
|
241
|
+
if (agent instanceof ControlledAccount) {
|
242
|
+
return coValuesCache.get(
|
243
|
+
agent.account,
|
244
|
+
() => coValueClassFromCoValueClassOrSchema(
|
245
|
+
RegisteredSchemas["Account"]
|
246
|
+
).fromRaw(agent.account)
|
247
|
+
);
|
248
|
+
}
|
249
|
+
return new AnonymousJazzAgent2(this.localNode);
|
250
|
+
}
|
251
|
+
};
|
252
|
+
|
253
|
+
// src/tools/implementation/inspect.ts
|
254
|
+
var inspect2 = Symbol.for("nodejs.util.inspect.custom");
|
255
|
+
|
256
|
+
// src/tools/implementation/symbols.ts
|
257
|
+
var SchemaInit = "$SchemaInit$";
|
258
|
+
var ItemsSym = "$items$";
|
259
|
+
var TypeSym = "$type$";
|
260
|
+
|
261
|
+
// src/tools/coValues/registeredSchemas.ts
|
262
|
+
var RegisteredSchemas = {};
|
263
|
+
|
264
|
+
// src/tools/coValues/coMap.ts
|
265
|
+
import {
|
266
|
+
cojsonInternals
|
267
|
+
} from "cojson";
|
268
|
+
var _CoMap = class _CoMap extends CoValueBase {
|
269
|
+
/** @internal */
|
270
|
+
constructor(options) {
|
271
|
+
super();
|
272
|
+
const proxy = new Proxy(this, CoMapProxyHandler);
|
273
|
+
if (options) {
|
274
|
+
if ("fromRaw" in options) {
|
275
|
+
Object.defineProperties(this, {
|
276
|
+
$jazz: {
|
277
|
+
value: new CoMapJazzApi(proxy, () => options.fromRaw),
|
278
|
+
enumerable: false
|
279
|
+
}
|
280
|
+
});
|
281
|
+
} else {
|
282
|
+
throw new Error("Invalid CoMap constructor arguments");
|
283
|
+
}
|
284
|
+
}
|
285
|
+
return proxy;
|
286
|
+
}
|
287
|
+
/**
|
288
|
+
* Create a new CoMap with the given initial values and owner.
|
289
|
+
*
|
290
|
+
* The owner (a Group or Account) determines access rights to the CoMap.
|
291
|
+
*
|
292
|
+
* The CoMap will immediately be persisted and synced to connected peers.
|
293
|
+
*
|
294
|
+
* @example
|
295
|
+
* ```ts
|
296
|
+
* const person = Person.create({
|
297
|
+
* name: "Alice",
|
298
|
+
* age: 42,
|
299
|
+
* pet: cat,
|
300
|
+
* }, { owner: friendGroup });
|
301
|
+
* ```
|
302
|
+
*
|
303
|
+
* @category Creation
|
304
|
+
*
|
305
|
+
* @deprecated Use `co.map(...).create`.
|
306
|
+
**/
|
307
|
+
static create(init, options) {
|
308
|
+
const instance = new this();
|
309
|
+
return _CoMap._createCoMap(instance, init, options);
|
310
|
+
}
|
311
|
+
/**
|
312
|
+
* Return a JSON representation of the `CoMap`
|
313
|
+
* @category Content
|
314
|
+
*/
|
315
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
316
|
+
toJSON(_key, processedValues) {
|
317
|
+
const result = {};
|
318
|
+
for (const key of this.$jazz.raw.keys()) {
|
319
|
+
const tKey = key;
|
320
|
+
const descriptor = this.$jazz.getDescriptor(tKey);
|
321
|
+
if (!descriptor) {
|
322
|
+
continue;
|
323
|
+
}
|
324
|
+
if (descriptor == "json" || "encoded" in descriptor) {
|
325
|
+
result[key] = this.$jazz.raw.get(key);
|
326
|
+
} else if (isRefEncoded(descriptor)) {
|
327
|
+
const id = this.$jazz.raw.get(key);
|
328
|
+
if (processedValues?.includes(id) || id === this.$jazz.id) {
|
329
|
+
result[key] = { _circular: id };
|
330
|
+
continue;
|
331
|
+
}
|
332
|
+
const ref2 = this[tKey];
|
333
|
+
if (ref2 && typeof ref2 === "object" && "toJSON" in ref2 && typeof ref2.toJSON === "function") {
|
334
|
+
const jsonedRef = ref2.toJSON(tKey, [
|
335
|
+
...processedValues || [],
|
336
|
+
this.$jazz.id
|
337
|
+
]);
|
338
|
+
result[key] = jsonedRef;
|
339
|
+
}
|
340
|
+
} else {
|
341
|
+
result[key] = void 0;
|
342
|
+
}
|
343
|
+
}
|
344
|
+
return result;
|
345
|
+
}
|
346
|
+
[inspect2]() {
|
347
|
+
return this.toJSON();
|
348
|
+
}
|
349
|
+
/**
|
350
|
+
* @internal
|
351
|
+
*/
|
352
|
+
static _createCoMap(instance, init, options) {
|
353
|
+
const { owner, uniqueness } = parseCoValueCreateOptions(options);
|
354
|
+
Object.defineProperties(instance, {
|
355
|
+
$jazz: {
|
356
|
+
value: new CoMapJazzApi(instance, () => raw),
|
357
|
+
enumerable: false
|
358
|
+
}
|
359
|
+
});
|
360
|
+
const raw = _CoMap.rawFromInit(instance, init, owner, uniqueness);
|
361
|
+
return instance;
|
362
|
+
}
|
363
|
+
/**
|
364
|
+
* Create a new `RawCoMap` from an initialization object
|
365
|
+
* @internal
|
366
|
+
*/
|
367
|
+
static rawFromInit(instance, init, owner, uniqueness) {
|
368
|
+
const rawOwner = owner.$jazz.raw;
|
369
|
+
const rawInit = {};
|
370
|
+
if (init)
|
371
|
+
for (const key of Object.keys(init)) {
|
372
|
+
const initValue = init[key];
|
373
|
+
const descriptor = instance.$jazz.getDescriptor(key);
|
374
|
+
if (!descriptor) {
|
375
|
+
continue;
|
376
|
+
}
|
377
|
+
if (descriptor === "json") {
|
378
|
+
rawInit[key] = initValue;
|
379
|
+
} else if (isRefEncoded(descriptor)) {
|
380
|
+
if (initValue != null) {
|
381
|
+
let refId = initValue.$jazz?.id;
|
382
|
+
if (!refId) {
|
383
|
+
const coValue = instantiateRefEncodedWithInit(
|
384
|
+
descriptor,
|
385
|
+
initValue,
|
386
|
+
owner
|
387
|
+
);
|
388
|
+
refId = coValue.$jazz.id;
|
389
|
+
}
|
390
|
+
rawInit[key] = refId;
|
391
|
+
}
|
392
|
+
} else if ("encoded" in descriptor) {
|
393
|
+
rawInit[key] = descriptor.encoded.encode(
|
394
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
395
|
+
initValue
|
396
|
+
);
|
397
|
+
}
|
398
|
+
}
|
399
|
+
return rawOwner.createMap(rawInit, null, "private", uniqueness);
|
400
|
+
}
|
401
|
+
/**
|
402
|
+
* Declare a Record-like CoMap schema, by extending `CoMap.Record(...)` and passing the value schema using `co`. Keys are always `string`.
|
403
|
+
*
|
404
|
+
* @example
|
405
|
+
* ```ts
|
406
|
+
* import { coField, CoMap } from "jazz-tools";
|
407
|
+
*
|
408
|
+
* class ColorToFruitMap extends CoMap.Record(
|
409
|
+
* coField.ref(Fruit)
|
410
|
+
* ) {}
|
411
|
+
*
|
412
|
+
* // assume we have map: ColorToFruitMap
|
413
|
+
* // and strawberry: Fruit
|
414
|
+
* map["red"] = strawberry;
|
415
|
+
* ```
|
416
|
+
*
|
417
|
+
* @category Declaration
|
418
|
+
*/
|
419
|
+
static Record(value) {
|
420
|
+
var _a2, _b;
|
421
|
+
class RecordLikeCoMap extends (_b = _CoMap, _a2 = ItemsSym, _b) {
|
422
|
+
constructor() {
|
423
|
+
super(...arguments);
|
424
|
+
this[_a2] = value;
|
425
|
+
}
|
426
|
+
}
|
427
|
+
return RecordLikeCoMap;
|
428
|
+
}
|
429
|
+
/**
|
430
|
+
* Load a `CoMap` with a given ID, as a given account.
|
431
|
+
*
|
432
|
+
* `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
|
433
|
+
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
434
|
+
*
|
435
|
+
* You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
436
|
+
*
|
437
|
+
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
438
|
+
*
|
439
|
+
* @example
|
440
|
+
* ```ts
|
441
|
+
* const person = await Person.load(
|
442
|
+
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
443
|
+
* { pet: {} }
|
444
|
+
* );
|
445
|
+
* ```
|
446
|
+
*
|
447
|
+
* @category Subscription & Loading
|
448
|
+
*
|
449
|
+
* @deprecated Use `co.map(...).load` instead.
|
450
|
+
*/
|
451
|
+
static load(id, options) {
|
452
|
+
return loadCoValueWithoutMe(this, id, options);
|
453
|
+
}
|
454
|
+
static subscribe(id, ...args) {
|
455
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
456
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
457
|
+
}
|
458
|
+
/** @deprecated Use `CoMap.upsertUnique` and `CoMap.loadUnique` instead. */
|
459
|
+
static findUnique(unique, ownerID, as) {
|
460
|
+
return _CoMap._findUnique(unique, ownerID, as);
|
461
|
+
}
|
462
|
+
/** @internal */
|
463
|
+
static _findUnique(unique, ownerID, as) {
|
464
|
+
as ||= activeAccountContext.get();
|
465
|
+
const header = {
|
466
|
+
type: "comap",
|
467
|
+
ruleset: {
|
468
|
+
type: "ownedByGroup",
|
469
|
+
group: ownerID
|
470
|
+
},
|
471
|
+
meta: null,
|
472
|
+
uniqueness: unique
|
473
|
+
};
|
474
|
+
const crypto = as[TypeSym] === "Anonymous" ? as.node.crypto : as.$jazz.localNode.crypto;
|
475
|
+
return cojsonInternals.idforHeader(header, crypto);
|
476
|
+
}
|
477
|
+
/**
|
478
|
+
* Given some data, updates an existing CoMap or initialises a new one if none exists.
|
479
|
+
*
|
480
|
+
* Note: This method respects resolve options, and thus can return `null` if the references cannot be resolved.
|
481
|
+
*
|
482
|
+
* @example
|
483
|
+
* ```ts
|
484
|
+
* const activeEvent = await Event.upsertUnique(
|
485
|
+
* sourceData.identifier,
|
486
|
+
* workspace.id,
|
487
|
+
* {
|
488
|
+
* title: sourceData.title,
|
489
|
+
* identifier: sourceData.identifier,
|
490
|
+
* external_id: sourceData._id,
|
491
|
+
* },
|
492
|
+
* workspace
|
493
|
+
* );
|
494
|
+
* ```
|
495
|
+
*
|
496
|
+
* @param options The options for creating or loading the CoMap. This includes the intended state of the CoMap, its unique identifier, its owner, and the references to resolve.
|
497
|
+
* @returns Either an existing & modified CoMap, or a new initialised CoMap if none exists.
|
498
|
+
* @category Subscription & Loading
|
499
|
+
*
|
500
|
+
* @deprecated Use `co.map(...).upsertUnique` instead.
|
501
|
+
*/
|
502
|
+
static async upsertUnique(options) {
|
503
|
+
const mapId = _CoMap._findUnique(
|
504
|
+
options.unique,
|
505
|
+
options.owner.$jazz.id,
|
506
|
+
options.owner.$jazz.loadedAs
|
507
|
+
);
|
508
|
+
let map = await loadCoValueWithoutMe(this, mapId, {
|
509
|
+
...options,
|
510
|
+
loadAs: options.owner.$jazz.loadedAs,
|
511
|
+
skipRetry: true
|
512
|
+
});
|
513
|
+
if (!map) {
|
514
|
+
const instance = new this();
|
515
|
+
map = _CoMap._createCoMap(instance, options.value, {
|
516
|
+
owner: options.owner,
|
517
|
+
unique: options.unique
|
518
|
+
});
|
519
|
+
} else {
|
520
|
+
map.$jazz.applyDiff(
|
521
|
+
options.value
|
522
|
+
);
|
523
|
+
}
|
524
|
+
return await loadCoValueWithoutMe(this, mapId, {
|
525
|
+
...options,
|
526
|
+
loadAs: options.owner.$jazz.loadedAs,
|
527
|
+
skipRetry: true
|
528
|
+
});
|
529
|
+
}
|
530
|
+
/**
|
531
|
+
* Loads a CoMap by its unique identifier and owner's ID.
|
532
|
+
* @param unique The unique identifier of the CoMap to load.
|
533
|
+
* @param ownerID The ID of the owner of the CoMap.
|
534
|
+
* @param options Additional options for loading the CoMap.
|
535
|
+
* @returns The loaded CoMap, or null if unavailable.
|
536
|
+
*
|
537
|
+
* @deprecated Use `co.map(...).loadUnique` instead.
|
538
|
+
*/
|
539
|
+
static loadUnique(unique, ownerID, options) {
|
540
|
+
return loadCoValueWithoutMe(
|
541
|
+
this,
|
542
|
+
_CoMap._findUnique(unique, ownerID, options?.loadAs),
|
543
|
+
{ ...options, skipRetry: true }
|
544
|
+
);
|
545
|
+
}
|
546
|
+
};
|
547
|
+
_CoMap.prototype[TypeSym] = "CoMap";
|
548
|
+
var CoMap = _CoMap;
|
549
|
+
var CoMapJazzApi = class extends CoValueJazzApi {
|
550
|
+
constructor(coMap, getRaw) {
|
551
|
+
super(coMap);
|
552
|
+
this.coMap = coMap;
|
553
|
+
this.getRaw = getRaw;
|
554
|
+
}
|
555
|
+
/**
|
556
|
+
* The ID of this `CoMap`
|
557
|
+
* @category Content
|
558
|
+
*/
|
559
|
+
get id() {
|
560
|
+
return this.raw.id;
|
561
|
+
}
|
562
|
+
get owner() {
|
563
|
+
return getCoValueOwner(this.coMap);
|
564
|
+
}
|
565
|
+
/**
|
566
|
+
* Set a value on the CoMap
|
567
|
+
*
|
568
|
+
* @param key The key to set
|
569
|
+
* @param value The value to set
|
570
|
+
*
|
571
|
+
* @category Content
|
572
|
+
*/
|
573
|
+
set(key, value) {
|
574
|
+
const descriptor = this.getDescriptor(key);
|
575
|
+
if (!descriptor) {
|
576
|
+
throw Error(`Cannot set unknown key ${key}`);
|
577
|
+
}
|
578
|
+
let refId = value?.$jazz?.id;
|
579
|
+
if (descriptor === "json") {
|
580
|
+
this.raw.set(key, value);
|
581
|
+
} else if ("encoded" in descriptor) {
|
582
|
+
this.raw.set(key, descriptor.encoded.encode(value));
|
583
|
+
} else if (isRefEncoded(descriptor)) {
|
584
|
+
if (value === void 0) {
|
585
|
+
if (!descriptor.optional) {
|
586
|
+
throw Error(`Cannot set required reference ${key} to undefined`);
|
587
|
+
}
|
588
|
+
this.raw.set(key, null);
|
589
|
+
} else {
|
590
|
+
if (!refId) {
|
591
|
+
const coValue = instantiateRefEncodedWithInit(
|
592
|
+
descriptor,
|
593
|
+
value,
|
594
|
+
this.owner
|
595
|
+
);
|
596
|
+
refId = coValue.$jazz.id;
|
597
|
+
}
|
598
|
+
this.raw.set(key, refId);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
}
|
602
|
+
/**
|
603
|
+
* Delete a value from a CoMap.
|
604
|
+
*
|
605
|
+
* For record-like CoMaps (created with `co.record`), any string key can be deleted.
|
606
|
+
* For struct-like CoMaps (created with `co.map`), only optional properties can be deleted.
|
607
|
+
*
|
608
|
+
* @param key The key to delete
|
609
|
+
*
|
610
|
+
* @category Content
|
611
|
+
*/
|
612
|
+
delete(key) {
|
613
|
+
this.raw.delete(key);
|
614
|
+
}
|
615
|
+
/**
|
616
|
+
* Modify the `CoMap` to match another map.
|
617
|
+
*
|
618
|
+
* The new values are assigned to the CoMap, overwriting existing values
|
619
|
+
* when the property already exists.
|
620
|
+
*
|
621
|
+
* @param newValues - The new values to apply to the CoMap. For collaborative values,
|
622
|
+
* both CoValues and JSON values are supported.
|
623
|
+
* @returns The modified CoMap.
|
624
|
+
*
|
625
|
+
* @category Content
|
626
|
+
*/
|
627
|
+
applyDiff(newValues) {
|
628
|
+
for (const key in newValues) {
|
629
|
+
if (Object.prototype.hasOwnProperty.call(newValues, key)) {
|
630
|
+
const tKey = key;
|
631
|
+
const descriptor = this.getDescriptor(key);
|
632
|
+
if (!descriptor) continue;
|
633
|
+
const newValue = newValues[tKey];
|
634
|
+
const currentValue = this.coMap[tKey];
|
635
|
+
if (descriptor === "json" || "encoded" in descriptor) {
|
636
|
+
if (currentValue !== newValue) {
|
637
|
+
this.set(tKey, newValue);
|
638
|
+
}
|
639
|
+
} else if (isRefEncoded(descriptor)) {
|
640
|
+
const currentId = currentValue?.$jazz.id;
|
641
|
+
let newId = newValue?.$jazz?.id;
|
642
|
+
if (currentId !== newId) {
|
643
|
+
this.set(tKey, newValue);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
}
|
647
|
+
}
|
648
|
+
return this.coMap;
|
649
|
+
}
|
650
|
+
/**
|
651
|
+
* Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth.
|
652
|
+
*
|
653
|
+
* Works like `CoMap.load()`, but you don't need to pass the ID or the account to load as again.
|
654
|
+
*
|
655
|
+
* @category Subscription & Loading
|
656
|
+
*/
|
657
|
+
ensureLoaded(options) {
|
658
|
+
return ensureCoValueLoaded(this.coMap, options);
|
659
|
+
}
|
660
|
+
subscribe(...args) {
|
661
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
662
|
+
return subscribeToExistingCoValue(this.coMap, options, listener);
|
663
|
+
}
|
664
|
+
/**
|
665
|
+
* Wait for the `CoMap` to be uploaded to the other peers.
|
666
|
+
*
|
667
|
+
* @category Subscription & Loading
|
668
|
+
*/
|
669
|
+
async waitForSync(options) {
|
670
|
+
await this.raw.core.waitForSync(options);
|
671
|
+
}
|
672
|
+
/**
|
673
|
+
* Get the descriptor for a given key
|
674
|
+
* @internal
|
675
|
+
*/
|
676
|
+
getDescriptor(key) {
|
677
|
+
return this.schema?.[key] || this.schema?.[ItemsSym];
|
678
|
+
}
|
679
|
+
/**
|
680
|
+
* If property `prop` is a `coField.ref(...)`, you can use `coMap.$jazz.refs.prop` to access
|
681
|
+
* the `Ref` instead of the potentially loaded/null value.
|
682
|
+
*
|
683
|
+
* This allows you to always get the ID or load the value manually.
|
684
|
+
*
|
685
|
+
* @example
|
686
|
+
* ```ts
|
687
|
+
* person.$jazz.refs.pet.id; // => ID<Animal>
|
688
|
+
* person.$jazz.refs.pet.value;
|
689
|
+
* // => Animal | null
|
690
|
+
* const pet = await person.$jazz.refs.pet.load();
|
691
|
+
* ```
|
692
|
+
*
|
693
|
+
* @category Content
|
694
|
+
**/
|
695
|
+
get refs() {
|
696
|
+
return makeRefs(
|
697
|
+
this.coMap,
|
698
|
+
(key) => this.raw.get(key),
|
699
|
+
() => {
|
700
|
+
const keys = this.raw.keys().filter((key) => {
|
701
|
+
const descriptor = this.getDescriptor(key);
|
702
|
+
return descriptor && descriptor !== "json" && isRefEncoded(descriptor);
|
703
|
+
});
|
704
|
+
return keys;
|
705
|
+
},
|
706
|
+
this.loadedAs,
|
707
|
+
(key) => this.getDescriptor(key)
|
708
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
709
|
+
);
|
710
|
+
}
|
711
|
+
/**
|
712
|
+
* Get the edits made to the CoMap.
|
713
|
+
*
|
714
|
+
* @category Collaboration
|
715
|
+
*/
|
716
|
+
getEdits() {
|
717
|
+
const map = this.coMap;
|
718
|
+
return new Proxy(
|
719
|
+
{},
|
720
|
+
{
|
721
|
+
get(_target, key) {
|
722
|
+
const rawEdit = map.$jazz.raw.lastEditAt(key);
|
723
|
+
if (!rawEdit) return void 0;
|
724
|
+
const descriptor = map.$jazz.getDescriptor(key);
|
725
|
+
if (!descriptor) return void 0;
|
726
|
+
return {
|
727
|
+
...getEditFromRaw(map, rawEdit, descriptor, key),
|
728
|
+
get all() {
|
729
|
+
return [...map.$jazz.raw.editsAt(key)].map(
|
730
|
+
(rawEdit2) => getEditFromRaw(map, rawEdit2, descriptor, key)
|
731
|
+
);
|
732
|
+
}
|
733
|
+
};
|
734
|
+
},
|
735
|
+
ownKeys(_target) {
|
736
|
+
return map.$jazz.raw.keys();
|
737
|
+
},
|
738
|
+
getOwnPropertyDescriptor(target, key) {
|
739
|
+
return {
|
740
|
+
value: Reflect.get(target, key),
|
741
|
+
writable: false,
|
742
|
+
enumerable: true,
|
743
|
+
configurable: true
|
744
|
+
};
|
745
|
+
}
|
746
|
+
}
|
747
|
+
);
|
748
|
+
}
|
749
|
+
/** @internal */
|
750
|
+
get raw() {
|
751
|
+
return this.getRaw();
|
752
|
+
}
|
753
|
+
/**
|
754
|
+
* The timestamp of the creation time of the CoMap
|
755
|
+
*
|
756
|
+
* @category Content
|
757
|
+
*/
|
758
|
+
get createdAt() {
|
759
|
+
return this.raw.earliestTxMadeAt ?? Number.MAX_SAFE_INTEGER;
|
760
|
+
}
|
761
|
+
/**
|
762
|
+
* The timestamp of the last updated time of the CoMap
|
763
|
+
*
|
764
|
+
* @category Content
|
765
|
+
*/
|
766
|
+
get lastUpdatedAt() {
|
767
|
+
return this.raw.latestTxMadeAt;
|
768
|
+
}
|
769
|
+
/** @internal */
|
770
|
+
get schema() {
|
771
|
+
return this.coMap.constructor._schema;
|
772
|
+
}
|
773
|
+
};
|
774
|
+
var CoMapProxyHandler = {
|
775
|
+
get(target, key, receiver) {
|
776
|
+
if (key === "_schema") {
|
777
|
+
return Reflect.get(target, key);
|
778
|
+
} else if (key in target) {
|
779
|
+
return Reflect.get(target, key, receiver);
|
780
|
+
} else {
|
781
|
+
if (typeof key !== "string") {
|
782
|
+
return void 0;
|
783
|
+
}
|
784
|
+
const descriptor = target.$jazz.getDescriptor(key);
|
785
|
+
if (!descriptor) {
|
786
|
+
return void 0;
|
787
|
+
}
|
788
|
+
const raw = target.$jazz.raw.get(key);
|
789
|
+
if (descriptor === "json") {
|
790
|
+
return raw;
|
791
|
+
} else if ("encoded" in descriptor) {
|
792
|
+
return raw === void 0 ? void 0 : descriptor.encoded.decode(raw);
|
793
|
+
} else if (isRefEncoded(descriptor)) {
|
794
|
+
return raw === void 0 || raw === null ? void 0 : accessChildByKey(target, raw, key);
|
795
|
+
}
|
796
|
+
}
|
797
|
+
},
|
798
|
+
set(target, key, value, receiver) {
|
799
|
+
if (typeof key === "string" && typeof value === "object" && value !== null && SchemaInit in value) {
|
800
|
+
target.constructor._schema ||= {};
|
801
|
+
target.constructor._schema[key] = value[SchemaInit];
|
802
|
+
return true;
|
803
|
+
}
|
804
|
+
const descriptor = target.$jazz.getDescriptor(key);
|
805
|
+
if (!descriptor) return false;
|
806
|
+
if (typeof key === "string") {
|
807
|
+
throw Error("Cannot update a CoMap directly. Use `$jazz.set` instead.");
|
808
|
+
} else {
|
809
|
+
return Reflect.set(target, key, value, receiver);
|
810
|
+
}
|
811
|
+
},
|
812
|
+
defineProperty(target, key, attributes) {
|
813
|
+
if ("value" in attributes && typeof attributes.value === "object" && SchemaInit in attributes.value) {
|
814
|
+
target.constructor._schema ||= {};
|
815
|
+
target.constructor._schema[key] = attributes.value[SchemaInit];
|
816
|
+
return true;
|
817
|
+
} else {
|
818
|
+
return Reflect.defineProperty(target, key, attributes);
|
819
|
+
}
|
820
|
+
},
|
821
|
+
ownKeys(target) {
|
822
|
+
const keys = Reflect.ownKeys(target).filter((k) => k !== ItemsSym);
|
823
|
+
for (const key of target.$jazz.raw.keys()) {
|
824
|
+
if (!keys.includes(key)) {
|
825
|
+
keys.push(key);
|
826
|
+
}
|
827
|
+
}
|
828
|
+
return keys;
|
829
|
+
},
|
830
|
+
getOwnPropertyDescriptor(target, key) {
|
831
|
+
if (key in target) {
|
832
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
833
|
+
} else {
|
834
|
+
const descriptor = target.$jazz.getDescriptor(key);
|
835
|
+
if (descriptor || key in target.$jazz.raw.latest) {
|
836
|
+
return {
|
837
|
+
enumerable: true,
|
838
|
+
configurable: true,
|
839
|
+
writable: true
|
840
|
+
};
|
841
|
+
}
|
842
|
+
}
|
843
|
+
},
|
844
|
+
has(target, key) {
|
845
|
+
const descriptor = target.$jazz?.getDescriptor(key);
|
846
|
+
if (target.$jazz?.raw && typeof key === "string" && descriptor) {
|
847
|
+
return target.$jazz.raw.get(key) !== void 0;
|
848
|
+
} else {
|
849
|
+
return Reflect.has(target, key);
|
850
|
+
}
|
851
|
+
},
|
852
|
+
deleteProperty(target, key) {
|
853
|
+
const descriptor = target.$jazz.getDescriptor(key);
|
854
|
+
if (typeof key === "string" && descriptor) {
|
855
|
+
throw Error(
|
856
|
+
"Cannot delete a CoMap property directly. Use `$jazz.delete` instead."
|
857
|
+
);
|
858
|
+
} else {
|
859
|
+
return Reflect.deleteProperty(target, key);
|
860
|
+
}
|
861
|
+
}
|
862
|
+
};
|
863
|
+
RegisteredSchemas["CoMap"] = CoMap;
|
864
|
+
function getEditFromRaw(target, rawEdit, descriptor, key) {
|
865
|
+
return {
|
866
|
+
value: descriptor === "json" ? rawEdit.value : "encoded" in descriptor ? rawEdit.value === null || rawEdit.value === void 0 ? rawEdit.value : descriptor.encoded.decode(rawEdit.value) : accessChildById(target, rawEdit.value, descriptor),
|
867
|
+
ref: descriptor !== "json" && isRefEncoded(descriptor) ? new Ref(
|
868
|
+
rawEdit.value,
|
869
|
+
target.$jazz.loadedAs,
|
870
|
+
descriptor,
|
871
|
+
target
|
872
|
+
) : void 0,
|
873
|
+
get by() {
|
874
|
+
return rawEdit.by && accessChildById(target, rawEdit.by, {
|
875
|
+
ref: Account,
|
876
|
+
optional: false
|
877
|
+
});
|
878
|
+
},
|
879
|
+
madeAt: rawEdit.at,
|
880
|
+
key
|
881
|
+
};
|
882
|
+
}
|
883
|
+
|
884
|
+
// src/tools/coValues/coList.ts
|
885
|
+
import { cojsonInternals as cojsonInternals2 } from "cojson";
|
886
|
+
import { calcPatch } from "fast-myers-diff";
|
887
|
+
var _CoList = class _CoList extends Array {
|
888
|
+
/**
|
889
|
+
* Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
|
890
|
+
*
|
891
|
+
* @example
|
892
|
+
* ```ts
|
893
|
+
* class ColorList extends CoList.Of(
|
894
|
+
* coField.string
|
895
|
+
* ) {}
|
896
|
+
* class AnimalList extends CoList.Of(
|
897
|
+
* coField.ref(Animal)
|
898
|
+
* ) {}
|
899
|
+
* ```
|
900
|
+
*
|
901
|
+
* @category Declaration
|
902
|
+
*/
|
903
|
+
static Of(item) {
|
904
|
+
var _a2, _b;
|
905
|
+
return class CoListOf extends (_b = _CoList, _a2 = coField.items, _b) {
|
906
|
+
constructor() {
|
907
|
+
super(...arguments);
|
908
|
+
this[_a2] = item;
|
909
|
+
}
|
910
|
+
};
|
911
|
+
}
|
912
|
+
/**
|
913
|
+
* @ignore
|
914
|
+
* @deprecated Use UPPERCASE `CoList.Of` instead! */
|
915
|
+
static of(..._args) {
|
916
|
+
throw new Error("Can't use Array.of with CoLists");
|
917
|
+
}
|
918
|
+
static get [(ItemsSym, Symbol.species)]() {
|
919
|
+
return Array;
|
920
|
+
}
|
921
|
+
constructor(options) {
|
922
|
+
super();
|
923
|
+
const proxy = new Proxy(this, CoListProxyHandler);
|
924
|
+
if (options && "fromRaw" in options) {
|
925
|
+
Object.defineProperties(this, {
|
926
|
+
$jazz: {
|
927
|
+
value: new CoListJazzApi(proxy, () => options.fromRaw),
|
928
|
+
enumerable: false
|
929
|
+
}
|
930
|
+
});
|
931
|
+
}
|
932
|
+
return proxy;
|
933
|
+
}
|
934
|
+
/**
|
935
|
+
* Create a new CoList with the given initial values and owner.
|
936
|
+
*
|
937
|
+
* The owner (a Group or Account) determines access rights to the CoMap.
|
938
|
+
*
|
939
|
+
* The CoList will immediately be persisted and synced to connected peers.
|
940
|
+
*
|
941
|
+
* @example
|
942
|
+
* ```ts
|
943
|
+
* const colours = ColorList.create(
|
944
|
+
* ["red", "green", "blue"],
|
945
|
+
* { owner: me }
|
946
|
+
* );
|
947
|
+
* const animals = AnimalList.create(
|
948
|
+
* [cat, dog, fish],
|
949
|
+
* { owner: me }
|
950
|
+
* );
|
951
|
+
* ```
|
952
|
+
*
|
953
|
+
* @category Creation
|
954
|
+
* @deprecated Use `co.list(...).create` instead.
|
955
|
+
**/
|
956
|
+
static create(items, options) {
|
957
|
+
const { owner, uniqueness } = parseCoValueCreateOptions(options);
|
958
|
+
const instance = new this();
|
959
|
+
Object.defineProperties(instance, {
|
960
|
+
$jazz: {
|
961
|
+
value: new CoListJazzApi(instance, () => raw),
|
962
|
+
enumerable: false
|
963
|
+
}
|
964
|
+
});
|
965
|
+
const raw = owner.$jazz.raw.createList(
|
966
|
+
toRawItems(items, instance.$jazz.schema[ItemsSym], owner),
|
967
|
+
null,
|
968
|
+
"private",
|
969
|
+
uniqueness
|
970
|
+
);
|
971
|
+
return instance;
|
972
|
+
}
|
973
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
974
|
+
toJSON(_key, seenAbove) {
|
975
|
+
const itemDescriptor = this.$jazz.schema[ItemsSym];
|
976
|
+
if (itemDescriptor === "json") {
|
977
|
+
return this.$jazz.raw.asArray();
|
978
|
+
} else if ("encoded" in itemDescriptor) {
|
979
|
+
return this.$jazz.raw.asArray().map((e) => itemDescriptor.encoded.encode(e));
|
980
|
+
} else if (isRefEncoded(itemDescriptor)) {
|
981
|
+
return this.map(
|
982
|
+
(item, idx) => seenAbove?.includes(item?.$jazz.id) ? { _circular: item.$jazz.id } : item?.toJSON(idx + "", [
|
983
|
+
...seenAbove || [],
|
984
|
+
this.$jazz.id
|
985
|
+
])
|
986
|
+
);
|
987
|
+
} else {
|
988
|
+
return [];
|
989
|
+
}
|
990
|
+
}
|
991
|
+
[inspect2]() {
|
992
|
+
return this.toJSON();
|
993
|
+
}
|
994
|
+
/** @category Internals */
|
995
|
+
static fromRaw(raw) {
|
996
|
+
return new this({ fromRaw: raw });
|
997
|
+
}
|
998
|
+
/** @internal */
|
999
|
+
static schema(def) {
|
1000
|
+
this._schema ||= {};
|
1001
|
+
Object.assign(this._schema, def);
|
1002
|
+
}
|
1003
|
+
/**
|
1004
|
+
* Load a `CoList` with a given ID, as a given account.
|
1005
|
+
*
|
1006
|
+
* `depth` specifies if item CoValue references should be loaded as well before resolving.
|
1007
|
+
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
1008
|
+
*
|
1009
|
+
* You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
|
1010
|
+
*
|
1011
|
+
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
1012
|
+
*
|
1013
|
+
* @example
|
1014
|
+
* ```ts
|
1015
|
+
* const animalsWithVets =
|
1016
|
+
* await ListOfAnimals.load(
|
1017
|
+
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
1018
|
+
* me,
|
1019
|
+
* [{ vet: {} }]
|
1020
|
+
* );
|
1021
|
+
* ```
|
1022
|
+
*
|
1023
|
+
* @category Subscription & Loading
|
1024
|
+
* @deprecated Use `co.list(...).load` instead.
|
1025
|
+
*/
|
1026
|
+
static load(id, options) {
|
1027
|
+
return loadCoValueWithoutMe(this, id, options);
|
1028
|
+
}
|
1029
|
+
static subscribe(id, ...args) {
|
1030
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
1031
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
1032
|
+
}
|
1033
|
+
/** @deprecated Use `CoList.upsertUnique` and `CoList.loadUnique` instead. */
|
1034
|
+
static findUnique(unique, ownerID, as) {
|
1035
|
+
return _CoList._findUnique(unique, ownerID, as);
|
1036
|
+
}
|
1037
|
+
/** @internal */
|
1038
|
+
static _findUnique(unique, ownerID, as) {
|
1039
|
+
as ||= activeAccountContext.get();
|
1040
|
+
const header = {
|
1041
|
+
type: "colist",
|
1042
|
+
ruleset: {
|
1043
|
+
type: "ownedByGroup",
|
1044
|
+
group: ownerID
|
1045
|
+
},
|
1046
|
+
meta: null,
|
1047
|
+
uniqueness: unique
|
1048
|
+
};
|
1049
|
+
const crypto = as[TypeSym] === "Anonymous" ? as.node.crypto : as.$jazz.localNode.crypto;
|
1050
|
+
return cojsonInternals2.idforHeader(header, crypto);
|
1051
|
+
}
|
1052
|
+
/**
|
1053
|
+
* Given some data, updates an existing CoList or initialises a new one if none exists.
|
1054
|
+
*
|
1055
|
+
* Note: This method respects resolve options, and thus can return `null` if the references cannot be resolved.
|
1056
|
+
*
|
1057
|
+
* @example
|
1058
|
+
* ```ts
|
1059
|
+
* const activeItems = await ItemList.upsertUnique(
|
1060
|
+
* {
|
1061
|
+
* value: [item1, item2, item3],
|
1062
|
+
* unique: sourceData.identifier,
|
1063
|
+
* owner: workspace,
|
1064
|
+
* }
|
1065
|
+
* );
|
1066
|
+
* ```
|
1067
|
+
*
|
1068
|
+
* @param options The options for creating or loading the CoList. This includes the intended state of the CoList, its unique identifier, its owner, and the references to resolve.
|
1069
|
+
* @returns Either an existing & modified CoList, or a new initialised CoList if none exists.
|
1070
|
+
* @category Subscription & Loading
|
1071
|
+
*/
|
1072
|
+
static async upsertUnique(options) {
|
1073
|
+
const listId = _CoList._findUnique(
|
1074
|
+
options.unique,
|
1075
|
+
options.owner.$jazz.id,
|
1076
|
+
options.owner.$jazz.loadedAs
|
1077
|
+
);
|
1078
|
+
let list = await loadCoValueWithoutMe(this, listId, {
|
1079
|
+
...options,
|
1080
|
+
loadAs: options.owner.$jazz.loadedAs,
|
1081
|
+
skipRetry: true
|
1082
|
+
});
|
1083
|
+
if (!list) {
|
1084
|
+
list = this.create(options.value, {
|
1085
|
+
owner: options.owner,
|
1086
|
+
unique: options.unique
|
1087
|
+
});
|
1088
|
+
} else {
|
1089
|
+
list.$jazz.applyDiff(options.value);
|
1090
|
+
}
|
1091
|
+
return await loadCoValueWithoutMe(this, listId, {
|
1092
|
+
...options,
|
1093
|
+
loadAs: options.owner.$jazz.loadedAs,
|
1094
|
+
skipRetry: true
|
1095
|
+
});
|
1096
|
+
}
|
1097
|
+
/**
|
1098
|
+
* Loads a CoList by its unique identifier and owner's ID.
|
1099
|
+
* @param unique The unique identifier of the CoList to load.
|
1100
|
+
* @param ownerID The ID of the owner of the CoList.
|
1101
|
+
* @param options Additional options for loading the CoList.
|
1102
|
+
* @returns The loaded CoList, or null if unavailable.
|
1103
|
+
*/
|
1104
|
+
static loadUnique(unique, ownerID, options) {
|
1105
|
+
return loadCoValueWithoutMe(
|
1106
|
+
this,
|
1107
|
+
_CoList._findUnique(unique, ownerID, options?.loadAs),
|
1108
|
+
{ ...options, skipRetry: true }
|
1109
|
+
);
|
1110
|
+
}
|
1111
|
+
// Override mutation methods defined on Array, as CoLists aren't meant to be mutated directly
|
1112
|
+
/**
|
1113
|
+
* @deprecated Use `.$jazz.push` instead.
|
1114
|
+
*/
|
1115
|
+
push(...items) {
|
1116
|
+
throw new Error(
|
1117
|
+
"Cannot mutate a CoList directly. Use `.$jazz.push` instead."
|
1118
|
+
);
|
1119
|
+
}
|
1120
|
+
/**
|
1121
|
+
* @deprecated Use `.$jazz.unshift` instead.
|
1122
|
+
*/
|
1123
|
+
unshift(...items) {
|
1124
|
+
throw new Error(
|
1125
|
+
"Cannot mutate a CoList directly. Use `.$jazz.unshift` instead."
|
1126
|
+
);
|
1127
|
+
}
|
1128
|
+
/**
|
1129
|
+
* @deprecated Use `.$jazz.pop` instead.
|
1130
|
+
*/
|
1131
|
+
// @ts-expect-error
|
1132
|
+
pop(value) {
|
1133
|
+
throw new Error(
|
1134
|
+
"Cannot mutate a CoList directly. Use `.$jazz.pop` instead."
|
1135
|
+
);
|
1136
|
+
}
|
1137
|
+
/**
|
1138
|
+
* @deprecated Use `.$jazz.shift` instead.
|
1139
|
+
*/
|
1140
|
+
// @ts-expect-error
|
1141
|
+
shift(value) {
|
1142
|
+
throw new Error(
|
1143
|
+
"Cannot mutate a CoList directly. Use `.$jazz.shift` instead."
|
1144
|
+
);
|
1145
|
+
}
|
1146
|
+
/**
|
1147
|
+
* @deprecated Use `.$jazz.splice` instead.
|
1148
|
+
*/
|
1149
|
+
splice(start, deleteCount, ...items) {
|
1150
|
+
throw new Error(
|
1151
|
+
"Cannot mutate a CoList directly. Use `.$jazz.splice` instead."
|
1152
|
+
);
|
1153
|
+
}
|
1154
|
+
/**
|
1155
|
+
* @deprecated Use `.$jazz.set` instead.
|
1156
|
+
*/
|
1157
|
+
copyWithin(target, start, end) {
|
1158
|
+
throw new Error(
|
1159
|
+
"Cannot mutate a CoList directly. Use `.$jazz.set` instead."
|
1160
|
+
);
|
1161
|
+
}
|
1162
|
+
/**
|
1163
|
+
* @deprecated Use `.$jazz.set` instead.
|
1164
|
+
*/
|
1165
|
+
fill(value, start, end) {
|
1166
|
+
throw new Error(
|
1167
|
+
"Cannot mutate a CoList directly. Use `.$jazz.set` instead."
|
1168
|
+
);
|
1169
|
+
}
|
1170
|
+
/**
|
1171
|
+
* @deprecated Use `.toReversed` if you want a reversed copy, or `.$jazz.set` to mutate the CoList.
|
1172
|
+
*/
|
1173
|
+
// @ts-expect-error
|
1174
|
+
reverse(value) {
|
1175
|
+
throw new Error(
|
1176
|
+
"Cannot mutate a CoList directly. Use `.toReversed` if you want a reversed copy, or `.$jazz.set` to mutate the CoList."
|
1177
|
+
);
|
1178
|
+
}
|
1179
|
+
/**
|
1180
|
+
* @deprecated Use `.toSorted()` if you want a sorted copy, or `.$jazz.set` to mutate the CoList.
|
1181
|
+
*/
|
1182
|
+
sort(compareFn) {
|
1183
|
+
throw new Error(
|
1184
|
+
"Cannot mutate a CoList directly. Use `.toSorted` if you want a sorted copy, or `.$jazz.set` to mutate the CoList."
|
1185
|
+
);
|
1186
|
+
}
|
1187
|
+
};
|
1188
|
+
_CoList.prototype[TypeSym] = "CoList";
|
1189
|
+
var CoList = _CoList;
|
1190
|
+
var CoListJazzApi = class extends CoValueJazzApi {
|
1191
|
+
constructor(coList, getRaw) {
|
1192
|
+
super(coList);
|
1193
|
+
this.coList = coList;
|
1194
|
+
this.getRaw = getRaw;
|
1195
|
+
}
|
1196
|
+
/**
|
1197
|
+
* The ID of this `CoList`
|
1198
|
+
* @category Content
|
1199
|
+
*/
|
1200
|
+
get id() {
|
1201
|
+
return this.raw.id;
|
1202
|
+
}
|
1203
|
+
/** @category Collaboration */
|
1204
|
+
get owner() {
|
1205
|
+
return getCoValueOwner(this.coList);
|
1206
|
+
}
|
1207
|
+
set(index, value) {
|
1208
|
+
const itemDescriptor = this.schema[ItemsSym];
|
1209
|
+
const rawValue = toRawItems([value], itemDescriptor, this.owner)[0];
|
1210
|
+
if (rawValue === null && !itemDescriptor.optional) {
|
1211
|
+
throw new Error(`Cannot set required reference ${index} to undefined`);
|
1212
|
+
}
|
1213
|
+
this.raw.replace(index, rawValue);
|
1214
|
+
}
|
1215
|
+
/**
|
1216
|
+
* Appends new elements to the end of an array, and returns the new length of the array.
|
1217
|
+
* @param items New elements to add to the array.
|
1218
|
+
*
|
1219
|
+
* @category Content
|
1220
|
+
*/
|
1221
|
+
push(...items) {
|
1222
|
+
this.raw.appendItems(
|
1223
|
+
toRawItems(items, this.schema[ItemsSym], this.owner),
|
1224
|
+
void 0,
|
1225
|
+
"private"
|
1226
|
+
);
|
1227
|
+
return this.raw.entries().length;
|
1228
|
+
}
|
1229
|
+
/**
|
1230
|
+
* Inserts new elements at the start of an array, and returns the new length of the array.
|
1231
|
+
* @param items Elements to insert at the start of the array.
|
1232
|
+
*
|
1233
|
+
* @category Content
|
1234
|
+
*/
|
1235
|
+
unshift(...items) {
|
1236
|
+
for (const item of toRawItems(
|
1237
|
+
items,
|
1238
|
+
this.schema[ItemsSym],
|
1239
|
+
this.owner
|
1240
|
+
)) {
|
1241
|
+
this.raw.prepend(item);
|
1242
|
+
}
|
1243
|
+
return this.raw.entries().length;
|
1244
|
+
}
|
1245
|
+
/**
|
1246
|
+
* Removes the last element from an array and returns it.
|
1247
|
+
* If the array is empty, undefined is returned and the array is not modified.
|
1248
|
+
*
|
1249
|
+
* @category Content
|
1250
|
+
*/
|
1251
|
+
pop() {
|
1252
|
+
const last = this.coList[this.coList.length - 1];
|
1253
|
+
this.raw.delete(this.coList.length - 1);
|
1254
|
+
return last;
|
1255
|
+
}
|
1256
|
+
/**
|
1257
|
+
* Removes the first element from an array and returns it.
|
1258
|
+
* If the array is empty, undefined is returned and the array is not modified.
|
1259
|
+
*
|
1260
|
+
* @category Content
|
1261
|
+
*/
|
1262
|
+
shift() {
|
1263
|
+
const first = this.coList[0];
|
1264
|
+
this.raw.delete(0);
|
1265
|
+
return first;
|
1266
|
+
}
|
1267
|
+
/**
|
1268
|
+
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
|
1269
|
+
* @param start The zero-based location in the array from which to start removing elements.
|
1270
|
+
* @param deleteCount The number of elements to remove.
|
1271
|
+
* @param items Elements to insert into the array in place of the deleted elements.
|
1272
|
+
* @returns An array containing the elements that were deleted.
|
1273
|
+
*
|
1274
|
+
* @category Content
|
1275
|
+
*/
|
1276
|
+
splice(start, deleteCount, ...items) {
|
1277
|
+
const deleted = this.coList.slice(start, start + deleteCount);
|
1278
|
+
for (let idxToDelete = start + deleteCount - 1; idxToDelete >= start; idxToDelete--) {
|
1279
|
+
this.raw.delete(idxToDelete);
|
1280
|
+
}
|
1281
|
+
const rawItems = toRawItems(
|
1282
|
+
items,
|
1283
|
+
this.schema[ItemsSym],
|
1284
|
+
this.owner
|
1285
|
+
);
|
1286
|
+
if (rawItems.length === 0) {
|
1287
|
+
return deleted;
|
1288
|
+
}
|
1289
|
+
if (rawItems.length === 1) {
|
1290
|
+
const item = rawItems[0];
|
1291
|
+
if (item === void 0) return deleted;
|
1292
|
+
if (start === 0) {
|
1293
|
+
this.raw.prepend(item);
|
1294
|
+
} else {
|
1295
|
+
this.raw.append(item, Math.max(start - 1, 0));
|
1296
|
+
}
|
1297
|
+
return deleted;
|
1298
|
+
}
|
1299
|
+
if (start === 0) {
|
1300
|
+
for (let i = rawItems.length - 1; i >= 0; i--) {
|
1301
|
+
const item = rawItems[i];
|
1302
|
+
if (item === void 0) continue;
|
1303
|
+
this.raw.prepend(item);
|
1304
|
+
}
|
1305
|
+
} else {
|
1306
|
+
let appendAfter = Math.max(start - 1, 0);
|
1307
|
+
for (const item of rawItems) {
|
1308
|
+
if (item === void 0) continue;
|
1309
|
+
this.raw.append(item, appendAfter);
|
1310
|
+
appendAfter++;
|
1311
|
+
}
|
1312
|
+
}
|
1313
|
+
return deleted;
|
1314
|
+
}
|
1315
|
+
remove(...args) {
|
1316
|
+
const predicate = args[0] instanceof Function ? args[0] : void 0;
|
1317
|
+
let indices = [];
|
1318
|
+
if (predicate) {
|
1319
|
+
for (let i = 0; i < this.coList.length; i++) {
|
1320
|
+
if (predicate(this.coList[i], i, this.coList)) {
|
1321
|
+
indices.push(i);
|
1322
|
+
}
|
1323
|
+
}
|
1324
|
+
} else {
|
1325
|
+
indices = args.filter((index) => index >= 0 && index < this.coList.length).sort((a, b) => a - b);
|
1326
|
+
}
|
1327
|
+
const deletedItems = indices.map((index) => this.coList[index]);
|
1328
|
+
for (const index of indices.reverse()) {
|
1329
|
+
this.raw.delete(index);
|
1330
|
+
}
|
1331
|
+
return deletedItems;
|
1332
|
+
}
|
1333
|
+
/**
|
1334
|
+
* Retains only the elements matching the predicate from the array.
|
1335
|
+
* @param predicate The predicate to match the elements to retain.
|
1336
|
+
* @returns The removed elements.
|
1337
|
+
*
|
1338
|
+
* @category Content
|
1339
|
+
*/
|
1340
|
+
retain(predicate) {
|
1341
|
+
return this.remove((...args) => !predicate(...args));
|
1342
|
+
}
|
1343
|
+
/**
|
1344
|
+
* Modify the `CoList` to match another list, where the changes are managed internally.
|
1345
|
+
*
|
1346
|
+
* Changes are detected using `Object.is` for non-collaborative values and `$jazz.id` for collaborative values.
|
1347
|
+
*
|
1348
|
+
* @param result - The resolved list of items. For collaborative values, both CoValues and JSON values are supported.
|
1349
|
+
* @returns The modified CoList.
|
1350
|
+
*
|
1351
|
+
* @category Content
|
1352
|
+
*/
|
1353
|
+
applyDiff(result) {
|
1354
|
+
const current = this.raw.asArray();
|
1355
|
+
const comparator = isRefEncoded(this.schema[ItemsSym]) ? (aIdx, bIdx) => {
|
1356
|
+
const oldCoValueId = current[aIdx]?.$jazz?.id;
|
1357
|
+
const newCoValueId = result[bIdx]?.$jazz?.id;
|
1358
|
+
const isSame = !!oldCoValueId && !!newCoValueId && oldCoValueId === newCoValueId;
|
1359
|
+
return isSame;
|
1360
|
+
} : void 0;
|
1361
|
+
const patches = [...calcPatch(current, result, comparator)];
|
1362
|
+
for (const [from, to, insert] of patches.reverse()) {
|
1363
|
+
this.splice(from, to - from, ...insert);
|
1364
|
+
}
|
1365
|
+
return this.coList;
|
1366
|
+
}
|
1367
|
+
/**
|
1368
|
+
* Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
|
1369
|
+
*
|
1370
|
+
* Works like `CoList.load()`, but you don't need to pass the ID or the account to load as again.
|
1371
|
+
*
|
1372
|
+
* @category Subscription & Loading
|
1373
|
+
*/
|
1374
|
+
ensureLoaded(options) {
|
1375
|
+
return ensureCoValueLoaded(this.coList, options);
|
1376
|
+
}
|
1377
|
+
subscribe(...args) {
|
1378
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
1379
|
+
return subscribeToExistingCoValue(this.coList, options, listener);
|
1380
|
+
}
|
1381
|
+
/**
|
1382
|
+
* Wait for the `CoList` to be uploaded to the other peers.
|
1383
|
+
*
|
1384
|
+
* @category Subscription & Loading
|
1385
|
+
*/
|
1386
|
+
async waitForSync(options) {
|
1387
|
+
await this.raw.core.waitForSync(options);
|
1388
|
+
}
|
1389
|
+
/**
|
1390
|
+
* Get the descriptor for the items in the `CoList`
|
1391
|
+
* @internal
|
1392
|
+
*/
|
1393
|
+
getItemsDescriptor() {
|
1394
|
+
return this.schema[ItemsSym];
|
1395
|
+
}
|
1396
|
+
/**
|
1397
|
+
* If a `CoList`'s items are a `coField.ref(...)`, you can use `coList.$jazz.refs[i]` to access
|
1398
|
+
* the `Ref` instead of the potentially loaded/null value.
|
1399
|
+
*
|
1400
|
+
* This allows you to always get the ID or load the value manually.
|
1401
|
+
*
|
1402
|
+
* @example
|
1403
|
+
* ```ts
|
1404
|
+
* animals.$jazz.refs[0].id; // => ID<Animal>
|
1405
|
+
* animals.$jazz.refs[0].value;
|
1406
|
+
* // => Animal | null
|
1407
|
+
* const animal = await animals.$jazz.refs[0].load();
|
1408
|
+
* ```
|
1409
|
+
*
|
1410
|
+
* @category Content
|
1411
|
+
**/
|
1412
|
+
get refs() {
|
1413
|
+
return makeRefs(
|
1414
|
+
this.coList,
|
1415
|
+
(idx) => this.raw.get(idx),
|
1416
|
+
() => Array.from({ length: this.raw.entries().length }, (_, idx) => idx),
|
1417
|
+
this.loadedAs,
|
1418
|
+
(_idx) => this.schema[ItemsSym]
|
1419
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1420
|
+
);
|
1421
|
+
}
|
1422
|
+
/**
|
1423
|
+
* Get the edits made to the CoList.
|
1424
|
+
*
|
1425
|
+
* @category Collaboration
|
1426
|
+
*/
|
1427
|
+
getEdits() {
|
1428
|
+
throw new Error("Not implemented");
|
1429
|
+
}
|
1430
|
+
/** @internal */
|
1431
|
+
get raw() {
|
1432
|
+
return this.getRaw();
|
1433
|
+
}
|
1434
|
+
/** @internal */
|
1435
|
+
get schema() {
|
1436
|
+
return this.coList.constructor._schema;
|
1437
|
+
}
|
1438
|
+
};
|
1439
|
+
function toRawItems(items, itemDescriptor, owner) {
|
1440
|
+
let rawItems = [];
|
1441
|
+
if (itemDescriptor === "json") {
|
1442
|
+
rawItems = items;
|
1443
|
+
} else if ("encoded" in itemDescriptor) {
|
1444
|
+
rawItems = items?.map((e) => itemDescriptor.encoded.encode(e));
|
1445
|
+
} else if (isRefEncoded(itemDescriptor)) {
|
1446
|
+
rawItems = items?.map((value) => {
|
1447
|
+
if (value == null) {
|
1448
|
+
return null;
|
1449
|
+
}
|
1450
|
+
let refId = value.$jazz?.id;
|
1451
|
+
if (!refId) {
|
1452
|
+
const coValue = instantiateRefEncodedWithInit(
|
1453
|
+
itemDescriptor,
|
1454
|
+
value,
|
1455
|
+
owner
|
1456
|
+
);
|
1457
|
+
refId = coValue.$jazz.id;
|
1458
|
+
}
|
1459
|
+
return refId;
|
1460
|
+
});
|
1461
|
+
} else {
|
1462
|
+
throw new Error("Invalid element descriptor");
|
1463
|
+
}
|
1464
|
+
return rawItems;
|
1465
|
+
}
|
1466
|
+
var CoListProxyHandler = {
|
1467
|
+
get(target, key, receiver) {
|
1468
|
+
if (typeof key === "string" && !isNaN(+key)) {
|
1469
|
+
const itemDescriptor = target.$jazz.schema[ItemsSym];
|
1470
|
+
const rawValue = target.$jazz.raw.get(Number(key));
|
1471
|
+
if (itemDescriptor === "json") {
|
1472
|
+
return rawValue;
|
1473
|
+
} else if ("encoded" in itemDescriptor) {
|
1474
|
+
return rawValue === void 0 ? void 0 : itemDescriptor.encoded.decode(rawValue);
|
1475
|
+
} else if (isRefEncoded(itemDescriptor)) {
|
1476
|
+
return rawValue === void 0 || rawValue === null ? void 0 : accessChildByKey(target, rawValue, key);
|
1477
|
+
}
|
1478
|
+
} else if (key === "length") {
|
1479
|
+
return target.$jazz.raw.entries().length;
|
1480
|
+
} else {
|
1481
|
+
return Reflect.get(target, key, receiver);
|
1482
|
+
}
|
1483
|
+
},
|
1484
|
+
set(target, key, value, receiver) {
|
1485
|
+
if (key === ItemsSym && typeof value === "object" && SchemaInit in value) {
|
1486
|
+
target.constructor._schema ||= {};
|
1487
|
+
target.constructor._schema[ItemsSym] = value[SchemaInit];
|
1488
|
+
return true;
|
1489
|
+
}
|
1490
|
+
if (typeof key === "string" && !isNaN(+key)) {
|
1491
|
+
throw Error("Cannot update a CoList directly. Use `$jazz.set` instead.");
|
1492
|
+
} else {
|
1493
|
+
return Reflect.set(target, key, value, receiver);
|
1494
|
+
}
|
1495
|
+
},
|
1496
|
+
defineProperty(target, key, descriptor) {
|
1497
|
+
if (descriptor.value && key === ItemsSym && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
|
1498
|
+
target.constructor._schema ||= {};
|
1499
|
+
target.constructor._schema[ItemsSym] = descriptor.value[SchemaInit];
|
1500
|
+
return true;
|
1501
|
+
} else {
|
1502
|
+
return Reflect.defineProperty(target, key, descriptor);
|
1503
|
+
}
|
1504
|
+
},
|
1505
|
+
has(target, key) {
|
1506
|
+
if (typeof key === "string" && !isNaN(+key)) {
|
1507
|
+
return Number(key) < target.$jazz.raw.entries().length;
|
1508
|
+
} else {
|
1509
|
+
return Reflect.has(target, key);
|
1510
|
+
}
|
1511
|
+
}
|
1512
|
+
};
|
1513
|
+
|
1514
|
+
// src/tools/coValues/coFeed.ts
|
1515
|
+
import { cojsonInternals as cojsonInternals3 } from "cojson";
|
1516
|
+
var _CoFeed = class _CoFeed extends CoValueBase {
|
1517
|
+
/**
|
1518
|
+
* Declare a `CoFeed` by subclassing `CoFeed.Of(...)` and passing the item schema using a `co` primitive or a `coField.ref`.
|
1519
|
+
*
|
1520
|
+
* @example
|
1521
|
+
* ```ts
|
1522
|
+
* class ColorFeed extends CoFeed.Of(coField.string) {}
|
1523
|
+
* class AnimalFeed extends CoFeed.Of(coField.ref(Animal)) {}
|
1524
|
+
* ```
|
1525
|
+
*
|
1526
|
+
* @category Declaration
|
1527
|
+
*/
|
1528
|
+
static Of(item) {
|
1529
|
+
var _a2, _b;
|
1530
|
+
const cls = class CoFeedOf extends (_b = _CoFeed, _a2 = coField.items, _b) {
|
1531
|
+
constructor() {
|
1532
|
+
super(...arguments);
|
1533
|
+
this[_a2] = item;
|
1534
|
+
}
|
1535
|
+
};
|
1536
|
+
cls._schema ||= {};
|
1537
|
+
cls._schema[ItemsSym] = item[SchemaInit];
|
1538
|
+
return cls;
|
1539
|
+
}
|
1540
|
+
/**
|
1541
|
+
* The current account's view of this `CoFeed`
|
1542
|
+
* @category Content
|
1543
|
+
*/
|
1544
|
+
get byMe() {
|
1545
|
+
if (this.$jazz.loadedAs[TypeSym] === "Account") {
|
1546
|
+
return this.perAccount[this.$jazz.loadedAs.$jazz.id];
|
1547
|
+
} else {
|
1548
|
+
return void 0;
|
1549
|
+
}
|
1550
|
+
}
|
1551
|
+
/**
|
1552
|
+
* The per-account view of this `CoFeed`
|
1553
|
+
*
|
1554
|
+
* @example
|
1555
|
+
* ```ts
|
1556
|
+
* // Access entries directly by account ID
|
1557
|
+
* const aliceEntries = feed[aliceAccount.id];
|
1558
|
+
* console.log(aliceEntries.value); // Latest value from Alice
|
1559
|
+
*
|
1560
|
+
* // Iterate through all accounts' entries
|
1561
|
+
* for (const [accountId, entries] of Object.entries(feed)) {
|
1562
|
+
* console.log(`Latest entry from ${accountId}:`, entries.value);
|
1563
|
+
*
|
1564
|
+
* // Access all entries from this account
|
1565
|
+
* for (const entry of entries.all) {
|
1566
|
+
* console.log(`Entry made at ${entry.madeAt}:`, entry.value);
|
1567
|
+
* }
|
1568
|
+
* }
|
1569
|
+
* ```
|
1570
|
+
*
|
1571
|
+
* @category Content
|
1572
|
+
*/
|
1573
|
+
get perAccount() {
|
1574
|
+
return new Proxy({}, CoStreamPerAccountProxyHandler(this));
|
1575
|
+
}
|
1576
|
+
/**
|
1577
|
+
* The per-session view of this `CoFeed`
|
1578
|
+
* @category Content
|
1579
|
+
*/
|
1580
|
+
get perSession() {
|
1581
|
+
return new Proxy(
|
1582
|
+
{},
|
1583
|
+
CoStreamPerSessionProxyHandler(this, this)
|
1584
|
+
);
|
1585
|
+
}
|
1586
|
+
/**
|
1587
|
+
* The current session's view of this `CoFeed`
|
1588
|
+
*
|
1589
|
+
* This is a shortcut for `this.perSession` where the session ID is the current session ID.
|
1590
|
+
*
|
1591
|
+
* @category Content
|
1592
|
+
*/
|
1593
|
+
get inCurrentSession() {
|
1594
|
+
if (this.$jazz.loadedAs[TypeSym] === "Account") {
|
1595
|
+
return this.perSession[this.$jazz.loadedAs.$jazz.sessionID];
|
1596
|
+
} else {
|
1597
|
+
return void 0;
|
1598
|
+
}
|
1599
|
+
}
|
1600
|
+
/** @internal */
|
1601
|
+
constructor(options) {
|
1602
|
+
super();
|
1603
|
+
Object.defineProperties(this, {
|
1604
|
+
$jazz: {
|
1605
|
+
value: new CoFeedJazzApi(this, options.fromRaw),
|
1606
|
+
enumerable: false
|
1607
|
+
}
|
1608
|
+
});
|
1609
|
+
return this;
|
1610
|
+
}
|
1611
|
+
/**
|
1612
|
+
* Create a new `CoFeed`
|
1613
|
+
* @category Creation
|
1614
|
+
* @deprecated Use `co.feed(...).create` instead.
|
1615
|
+
*/
|
1616
|
+
static create(init, options) {
|
1617
|
+
const { owner } = parseCoValueCreateOptions(options);
|
1618
|
+
const raw = owner.$jazz.raw.createStream();
|
1619
|
+
const instance = new this({ fromRaw: raw });
|
1620
|
+
if (init) {
|
1621
|
+
instance.$jazz.push(...init);
|
1622
|
+
}
|
1623
|
+
return instance;
|
1624
|
+
}
|
1625
|
+
/**
|
1626
|
+
* Get a JSON representation of the `CoFeed`
|
1627
|
+
* @category
|
1628
|
+
*/
|
1629
|
+
toJSON() {
|
1630
|
+
const itemDescriptor = this.$jazz.schema[ItemsSym];
|
1631
|
+
const mapper = itemDescriptor === "json" ? (v) => v : "encoded" in itemDescriptor ? itemDescriptor.encoded.encode : (v) => v && v.$jazz.id;
|
1632
|
+
return {
|
1633
|
+
...Object.fromEntries(
|
1634
|
+
Object.entries(this).map(([account, entry]) => [
|
1635
|
+
account,
|
1636
|
+
mapper(entry.value)
|
1637
|
+
])
|
1638
|
+
),
|
1639
|
+
in: Object.fromEntries(
|
1640
|
+
Object.entries(this.perSession).map(([session, entry]) => [
|
1641
|
+
session,
|
1642
|
+
mapper(entry.value)
|
1643
|
+
])
|
1644
|
+
)
|
1645
|
+
};
|
1646
|
+
}
|
1647
|
+
/** @internal */
|
1648
|
+
[(ItemsSym, inspect2)]() {
|
1649
|
+
return this.toJSON();
|
1650
|
+
}
|
1651
|
+
/** @internal */
|
1652
|
+
static schema(def) {
|
1653
|
+
this._schema ||= {};
|
1654
|
+
Object.assign(this._schema, def);
|
1655
|
+
}
|
1656
|
+
/**
|
1657
|
+
* Load a `CoFeed`
|
1658
|
+
* @category Subscription & Loading
|
1659
|
+
* @deprecated Use `co.feed(...).load` instead.
|
1660
|
+
*/
|
1661
|
+
static load(id, options) {
|
1662
|
+
return loadCoValueWithoutMe(this, id, options);
|
1663
|
+
}
|
1664
|
+
static subscribe(id, ...args) {
|
1665
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
1666
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
1667
|
+
}
|
1668
|
+
};
|
1669
|
+
_CoFeed.prototype[TypeSym] = "CoStream";
|
1670
|
+
var CoFeed = _CoFeed;
|
1671
|
+
var CoFeedJazzApi = class extends CoValueJazzApi {
|
1672
|
+
constructor(coFeed, raw) {
|
1673
|
+
super(coFeed);
|
1674
|
+
this.coFeed = coFeed;
|
1675
|
+
this.raw = raw;
|
1676
|
+
}
|
1677
|
+
/**
|
1678
|
+
* The ID of this `CoFeed`
|
1679
|
+
* @category Content
|
1680
|
+
*/
|
1681
|
+
get id() {
|
1682
|
+
return this.raw.id;
|
1683
|
+
}
|
1684
|
+
get owner() {
|
1685
|
+
return getCoValueOwner(this.coFeed);
|
1686
|
+
}
|
1687
|
+
/**
|
1688
|
+
* Push items to this `CoFeed`
|
1689
|
+
*
|
1690
|
+
* Items are appended to the current session's log. Each session (tab, device, app instance)
|
1691
|
+
* maintains its own append-only log, which is then aggregated into the per-account view.
|
1692
|
+
*
|
1693
|
+
* @example
|
1694
|
+
* ```ts
|
1695
|
+
* // Adds items to current session's log
|
1696
|
+
* feed.$jazz.push("item1", "item2");
|
1697
|
+
*
|
1698
|
+
* // View items from current session
|
1699
|
+
* console.log(feed.inCurrentSession);
|
1700
|
+
*
|
1701
|
+
* // View aggregated items from all sessions for current account
|
1702
|
+
* console.log(feed.byMe);
|
1703
|
+
* ```
|
1704
|
+
*
|
1705
|
+
* @category Content
|
1706
|
+
*/
|
1707
|
+
push(...items) {
|
1708
|
+
for (const item of items) {
|
1709
|
+
this.pushItem(item);
|
1710
|
+
}
|
1711
|
+
}
|
1712
|
+
pushItem(item) {
|
1713
|
+
const itemDescriptor = this.schema[ItemsSym];
|
1714
|
+
if (itemDescriptor === "json") {
|
1715
|
+
this.raw.push(item);
|
1716
|
+
} else if ("encoded" in itemDescriptor) {
|
1717
|
+
this.raw.push(itemDescriptor.encoded.encode(item));
|
1718
|
+
} else if (isRefEncoded(itemDescriptor)) {
|
1719
|
+
let refId = item.$jazz?.id;
|
1720
|
+
if (!refId) {
|
1721
|
+
const coValue = instantiateRefEncodedWithInit(
|
1722
|
+
itemDescriptor,
|
1723
|
+
item,
|
1724
|
+
this.owner
|
1725
|
+
);
|
1726
|
+
refId = coValue.$jazz.id;
|
1727
|
+
}
|
1728
|
+
this.raw.push(refId);
|
1729
|
+
}
|
1730
|
+
}
|
1731
|
+
/**
|
1732
|
+
* Ensure a `CoFeed` is loaded to the specified depth
|
1733
|
+
*
|
1734
|
+
* @returns A new instance of the same CoFeed that's loaded to the specified depth
|
1735
|
+
* @category Subscription & Loading
|
1736
|
+
*/
|
1737
|
+
ensureLoaded(options) {
|
1738
|
+
return ensureCoValueLoaded(this.coFeed, options);
|
1739
|
+
}
|
1740
|
+
subscribe(...args) {
|
1741
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
1742
|
+
return subscribeToExistingCoValue(this.coFeed, options, listener);
|
1743
|
+
}
|
1744
|
+
/**
|
1745
|
+
* Wait for the `CoFeed` to be uploaded to the other peers.
|
1746
|
+
*
|
1747
|
+
* @category Subscription & Loading
|
1748
|
+
*/
|
1749
|
+
waitForSync(options) {
|
1750
|
+
return this.raw.core.waitForSync(options);
|
1751
|
+
}
|
1752
|
+
/**
|
1753
|
+
* Get the descriptor for the items in the `CoFeed`
|
1754
|
+
* @internal
|
1755
|
+
*/
|
1756
|
+
getItemsDescriptor() {
|
1757
|
+
return this.schema[ItemsSym];
|
1758
|
+
}
|
1759
|
+
/** @internal */
|
1760
|
+
get schema() {
|
1761
|
+
return this.coFeed.constructor._schema;
|
1762
|
+
}
|
1763
|
+
};
|
1764
|
+
function entryFromRawEntry(accessFrom, rawEntry, loadedAs, accountID, itemField) {
|
1765
|
+
return {
|
1766
|
+
get value() {
|
1767
|
+
if (itemField === "json") {
|
1768
|
+
return rawEntry.value;
|
1769
|
+
} else if ("encoded" in itemField) {
|
1770
|
+
return itemField.encoded.decode(rawEntry.value);
|
1771
|
+
} else if (isRefEncoded(itemField)) {
|
1772
|
+
return accessChildById(
|
1773
|
+
accessFrom,
|
1774
|
+
rawEntry.value,
|
1775
|
+
itemField
|
1776
|
+
);
|
1777
|
+
} else {
|
1778
|
+
throw new Error("Invalid item field schema");
|
1779
|
+
}
|
1780
|
+
},
|
1781
|
+
get ref() {
|
1782
|
+
if (itemField !== "json" && isRefEncoded(itemField)) {
|
1783
|
+
const rawId = rawEntry.value;
|
1784
|
+
return new Ref(
|
1785
|
+
rawId,
|
1786
|
+
loadedAs,
|
1787
|
+
itemField,
|
1788
|
+
accessFrom
|
1789
|
+
);
|
1790
|
+
} else {
|
1791
|
+
return void 0;
|
1792
|
+
}
|
1793
|
+
},
|
1794
|
+
get by() {
|
1795
|
+
return accountID && accessChildById(accessFrom, accountID, {
|
1796
|
+
ref: Account,
|
1797
|
+
optional: false
|
1798
|
+
});
|
1799
|
+
},
|
1800
|
+
madeAt: rawEntry.at,
|
1801
|
+
tx: rawEntry.tx
|
1802
|
+
};
|
1803
|
+
}
|
1804
|
+
var CoStreamPerAccountProxyHandler = (innerTarget) => ({
|
1805
|
+
get(_target, key, receiver) {
|
1806
|
+
if (typeof key === "string" && key.startsWith("co_")) {
|
1807
|
+
const rawEntry = innerTarget.$jazz.raw.lastItemBy(key);
|
1808
|
+
if (!rawEntry) return;
|
1809
|
+
const entry = entryFromRawEntry(
|
1810
|
+
receiver,
|
1811
|
+
rawEntry,
|
1812
|
+
innerTarget.$jazz.loadedAs,
|
1813
|
+
key,
|
1814
|
+
innerTarget.$jazz.schema[ItemsSym]
|
1815
|
+
);
|
1816
|
+
Object.defineProperty(entry, "all", {
|
1817
|
+
get: () => {
|
1818
|
+
const allRawEntries = innerTarget.$jazz.raw.itemsBy(
|
1819
|
+
key
|
1820
|
+
);
|
1821
|
+
return function* () {
|
1822
|
+
while (true) {
|
1823
|
+
const rawEntry2 = allRawEntries.next();
|
1824
|
+
if (rawEntry2.done) return;
|
1825
|
+
yield entryFromRawEntry(
|
1826
|
+
receiver,
|
1827
|
+
rawEntry2.value,
|
1828
|
+
innerTarget.$jazz.loadedAs,
|
1829
|
+
key,
|
1830
|
+
innerTarget.$jazz.schema[ItemsSym]
|
1831
|
+
);
|
1832
|
+
}
|
1833
|
+
}();
|
1834
|
+
}
|
1835
|
+
});
|
1836
|
+
return entry;
|
1837
|
+
} else {
|
1838
|
+
return Reflect.get(innerTarget, key, receiver);
|
1839
|
+
}
|
1840
|
+
},
|
1841
|
+
ownKeys(_target) {
|
1842
|
+
return Array.from(innerTarget.$jazz.raw.accounts());
|
1843
|
+
},
|
1844
|
+
getOwnPropertyDescriptor(_target, key) {
|
1845
|
+
if (typeof key === "string" && key.startsWith("co_")) {
|
1846
|
+
return {
|
1847
|
+
configurable: true,
|
1848
|
+
enumerable: true,
|
1849
|
+
writable: false
|
1850
|
+
};
|
1851
|
+
} else {
|
1852
|
+
return Reflect.getOwnPropertyDescriptor(innerTarget, key);
|
1853
|
+
}
|
1854
|
+
}
|
1855
|
+
});
|
1856
|
+
var CoStreamPerSessionProxyHandler = (innerTarget, accessFrom) => ({
|
1857
|
+
get(_target, key, receiver) {
|
1858
|
+
if (typeof key === "string" && key.includes("session")) {
|
1859
|
+
const sessionID = key;
|
1860
|
+
const rawEntry = innerTarget.$jazz.raw.lastItemIn(sessionID);
|
1861
|
+
if (!rawEntry) return;
|
1862
|
+
const by = cojsonInternals3.accountOrAgentIDfromSessionID(sessionID);
|
1863
|
+
const entry = entryFromRawEntry(
|
1864
|
+
accessFrom,
|
1865
|
+
rawEntry,
|
1866
|
+
innerTarget.$jazz.loadedAs,
|
1867
|
+
cojsonInternals3.isAccountID(by) ? by : void 0,
|
1868
|
+
innerTarget.$jazz.schema[ItemsSym]
|
1869
|
+
);
|
1870
|
+
Object.defineProperty(entry, "all", {
|
1871
|
+
get: () => {
|
1872
|
+
const allRawEntries = innerTarget.$jazz.raw.itemsIn(sessionID);
|
1873
|
+
return function* () {
|
1874
|
+
while (true) {
|
1875
|
+
const rawEntry2 = allRawEntries.next();
|
1876
|
+
if (rawEntry2.done) return;
|
1877
|
+
yield entryFromRawEntry(
|
1878
|
+
accessFrom,
|
1879
|
+
rawEntry2.value,
|
1880
|
+
innerTarget.$jazz.loadedAs,
|
1881
|
+
cojsonInternals3.isAccountID(by) ? by : void 0,
|
1882
|
+
innerTarget.$jazz.schema[ItemsSym]
|
1883
|
+
);
|
1884
|
+
}
|
1885
|
+
}();
|
1886
|
+
}
|
1887
|
+
});
|
1888
|
+
return entry;
|
1889
|
+
} else {
|
1890
|
+
return Reflect.get(innerTarget, key, receiver);
|
1891
|
+
}
|
1892
|
+
},
|
1893
|
+
ownKeys() {
|
1894
|
+
return innerTarget.$jazz.raw.sessions();
|
1895
|
+
},
|
1896
|
+
getOwnPropertyDescriptor(target, key) {
|
1897
|
+
if (typeof key === "string" && key.startsWith("co_")) {
|
1898
|
+
return {
|
1899
|
+
configurable: true,
|
1900
|
+
enumerable: true,
|
1901
|
+
writable: false
|
1902
|
+
};
|
1903
|
+
} else {
|
1904
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
1905
|
+
}
|
1906
|
+
}
|
1907
|
+
});
|
1908
|
+
var FileStream = class extends CoValueBase {
|
1909
|
+
constructor(options) {
|
1910
|
+
super();
|
1911
|
+
let raw;
|
1912
|
+
if ("fromRaw" in options) {
|
1913
|
+
raw = options.fromRaw;
|
1914
|
+
} else {
|
1915
|
+
const rawOwner = options.owner.$jazz.raw;
|
1916
|
+
raw = rawOwner.createBinaryStream();
|
1917
|
+
}
|
1918
|
+
Object.defineProperties(this, {
|
1919
|
+
[TypeSym]: { value: "BinaryCoStream", enumerable: false },
|
1920
|
+
$jazz: {
|
1921
|
+
value: new FileStreamJazzApi(this, raw),
|
1922
|
+
enumerable: false
|
1923
|
+
}
|
1924
|
+
});
|
1925
|
+
}
|
1926
|
+
/**
|
1927
|
+
* Create a new empty `FileStream` instance.
|
1928
|
+
*
|
1929
|
+
* @param options - Configuration options for the new FileStream
|
1930
|
+
* @param options.owner - The Account or Group that will own this FileStream and control access rights
|
1931
|
+
*
|
1932
|
+
* @example
|
1933
|
+
* ```typescript
|
1934
|
+
* // Create owned by an account
|
1935
|
+
* const stream = FileStream.create({ owner: myAccount });
|
1936
|
+
*
|
1937
|
+
* // Create owned by a group
|
1938
|
+
* const stream = FileStream.create({ owner: teamGroup });
|
1939
|
+
*
|
1940
|
+
* // Create with implicit owner
|
1941
|
+
* const stream = FileStream.create(myAccount);
|
1942
|
+
* ```
|
1943
|
+
*
|
1944
|
+
* @remarks
|
1945
|
+
* For uploading an existing file or blob, use {@link FileStream.createFromBlob} instead.
|
1946
|
+
*
|
1947
|
+
* @category Creation
|
1948
|
+
* @deprecated Use `co.fileStream(...).create` instead.
|
1949
|
+
*/
|
1950
|
+
static create(options) {
|
1951
|
+
return new this(parseCoValueCreateOptions(options));
|
1952
|
+
}
|
1953
|
+
getMetadata() {
|
1954
|
+
return this.$jazz.raw.getBinaryStreamInfo();
|
1955
|
+
}
|
1956
|
+
getChunks(options) {
|
1957
|
+
return this.$jazz.raw.getBinaryChunks(options?.allowUnfinished);
|
1958
|
+
}
|
1959
|
+
isBinaryStreamEnded() {
|
1960
|
+
return this.$jazz.raw.isBinaryStreamEnded();
|
1961
|
+
}
|
1962
|
+
start(options) {
|
1963
|
+
this.$jazz.raw.startBinaryStream(options);
|
1964
|
+
}
|
1965
|
+
push(data) {
|
1966
|
+
this.$jazz.raw.pushBinaryStreamChunk(data);
|
1967
|
+
}
|
1968
|
+
end() {
|
1969
|
+
this.$jazz.raw.endBinaryStream();
|
1970
|
+
}
|
1971
|
+
toBlob(options) {
|
1972
|
+
const chunks = this.getChunks({
|
1973
|
+
allowUnfinished: options?.allowUnfinished
|
1974
|
+
});
|
1975
|
+
if (!chunks) {
|
1976
|
+
return void 0;
|
1977
|
+
}
|
1978
|
+
return new Blob(chunks.chunks, { type: chunks.mimeType });
|
1979
|
+
}
|
1980
|
+
/**
|
1981
|
+
* Load a `FileStream` as a `Blob`
|
1982
|
+
*
|
1983
|
+
* @category Content
|
1984
|
+
* @deprecated Use `co.fileStream(...).loadAsBlob` instead.
|
1985
|
+
*/
|
1986
|
+
static async loadAsBlob(id, options) {
|
1987
|
+
let stream = await this.load(id, options);
|
1988
|
+
return stream?.toBlob({
|
1989
|
+
allowUnfinished: options?.allowUnfinished
|
1990
|
+
});
|
1991
|
+
}
|
1992
|
+
static async loadAsBase64(id, options) {
|
1993
|
+
const stream = await this.load(id, options);
|
1994
|
+
return stream?.asBase64(options);
|
1995
|
+
}
|
1996
|
+
asBase64(options) {
|
1997
|
+
const chunks = this.getChunks(options);
|
1998
|
+
if (!chunks) return void 0;
|
1999
|
+
const output = [];
|
2000
|
+
for (const chunk of chunks.chunks) {
|
2001
|
+
for (const byte of chunk) {
|
2002
|
+
output.push(String.fromCharCode(byte));
|
2003
|
+
}
|
2004
|
+
}
|
2005
|
+
const base642 = btoa(output.join(""));
|
2006
|
+
if (options?.dataURL) {
|
2007
|
+
return `data:${chunks.mimeType};base64,${base642}`;
|
2008
|
+
}
|
2009
|
+
return base642;
|
2010
|
+
}
|
2011
|
+
/**
|
2012
|
+
* Create a `FileStream` from a `Blob` or `File`
|
2013
|
+
*
|
2014
|
+
* @example
|
2015
|
+
* ```ts
|
2016
|
+
* import { coField, FileStream } from "jazz-tools";
|
2017
|
+
*
|
2018
|
+
* const fileStream = await FileStream.createFromBlob(file, {owner: group})
|
2019
|
+
* ```
|
2020
|
+
* @category Content
|
2021
|
+
* @deprecated Use `co.fileStream(...).createFromBlob` instead.
|
2022
|
+
*/
|
2023
|
+
static async createFromBlob(blob, options) {
|
2024
|
+
const arrayBuffer = await blob.arrayBuffer();
|
2025
|
+
return this.createFromArrayBuffer(
|
2026
|
+
arrayBuffer,
|
2027
|
+
blob.type,
|
2028
|
+
blob instanceof File ? blob.name : void 0,
|
2029
|
+
options
|
2030
|
+
);
|
2031
|
+
}
|
2032
|
+
/**
|
2033
|
+
* Create a `FileStream` from a `Blob` or `File`
|
2034
|
+
*
|
2035
|
+
* @example
|
2036
|
+
* ```ts
|
2037
|
+
* import { coField, FileStream } from "jazz-tools";
|
2038
|
+
*
|
2039
|
+
* const fileStream = await FileStream.createFromBlob(file, {owner: group})
|
2040
|
+
* ```
|
2041
|
+
* @category Content
|
2042
|
+
* @deprecated Use `co.fileStream(...).createFromArrayBuffer` instead.
|
2043
|
+
*/
|
2044
|
+
static async createFromArrayBuffer(arrayBuffer, mimeType, fileName, options) {
|
2045
|
+
const stream = this.create(options);
|
2046
|
+
const onProgress = options && "onProgress" in options ? options.onProgress : void 0;
|
2047
|
+
const start = Date.now();
|
2048
|
+
const data = new Uint8Array(arrayBuffer);
|
2049
|
+
stream.start({
|
2050
|
+
mimeType,
|
2051
|
+
totalSizeBytes: arrayBuffer.byteLength,
|
2052
|
+
fileName
|
2053
|
+
});
|
2054
|
+
const chunkSize = cojsonInternals3.TRANSACTION_CONFIG.MAX_RECOMMENDED_TX_SIZE;
|
2055
|
+
let lastProgressUpdate = Date.now();
|
2056
|
+
for (let idx = 0; idx < data.length; idx += chunkSize) {
|
2057
|
+
stream.push(data.slice(idx, idx + chunkSize));
|
2058
|
+
if (Date.now() - lastProgressUpdate > 100) {
|
2059
|
+
onProgress?.(idx / data.length);
|
2060
|
+
lastProgressUpdate = Date.now();
|
2061
|
+
}
|
2062
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
2063
|
+
}
|
2064
|
+
stream.end();
|
2065
|
+
const end = Date.now();
|
2066
|
+
console.debug(
|
2067
|
+
"Finished creating binary stream in",
|
2068
|
+
(end - start) / 1e3,
|
2069
|
+
"s - Throughput in MB/s",
|
2070
|
+
1e3 * (arrayBuffer.byteLength / (end - start)) / (1024 * 1024)
|
2071
|
+
);
|
2072
|
+
onProgress?.(1);
|
2073
|
+
return stream;
|
2074
|
+
}
|
2075
|
+
/**
|
2076
|
+
* Get a JSON representation of the `FileStream`
|
2077
|
+
* @category Content
|
2078
|
+
*/
|
2079
|
+
toJSON() {
|
2080
|
+
return {
|
2081
|
+
...this.getChunks()
|
2082
|
+
};
|
2083
|
+
}
|
2084
|
+
/** @internal */
|
2085
|
+
[inspect2]() {
|
2086
|
+
return this.toJSON();
|
2087
|
+
}
|
2088
|
+
/**
|
2089
|
+
* Load a `FileStream`
|
2090
|
+
* @category Subscription & Loading
|
2091
|
+
* @deprecated Use `co.fileStream(...).load` instead.
|
2092
|
+
*/
|
2093
|
+
static async load(id, options) {
|
2094
|
+
const stream = await loadCoValueWithoutMe(this, id, options);
|
2095
|
+
if (!options?.allowUnfinished && !stream?.isBinaryStreamEnded()) {
|
2096
|
+
return new Promise((resolve) => {
|
2097
|
+
subscribeToCoValueWithoutMe(
|
2098
|
+
this,
|
2099
|
+
id,
|
2100
|
+
options || {},
|
2101
|
+
(value, unsubscribe) => {
|
2102
|
+
if (value.isBinaryStreamEnded()) {
|
2103
|
+
unsubscribe();
|
2104
|
+
resolve(value);
|
2105
|
+
}
|
2106
|
+
}
|
2107
|
+
);
|
2108
|
+
});
|
2109
|
+
}
|
2110
|
+
return stream;
|
2111
|
+
}
|
2112
|
+
static subscribe(id, ...args) {
|
2113
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2114
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
2115
|
+
}
|
2116
|
+
};
|
2117
|
+
var FileStreamJazzApi = class extends CoValueJazzApi {
|
2118
|
+
constructor(fileStream, raw) {
|
2119
|
+
super(fileStream);
|
2120
|
+
this.fileStream = fileStream;
|
2121
|
+
this.raw = raw;
|
2122
|
+
}
|
2123
|
+
/**
|
2124
|
+
* The ID of this `FileStream`
|
2125
|
+
* @category Content
|
2126
|
+
*/
|
2127
|
+
get id() {
|
2128
|
+
return this.raw.id;
|
2129
|
+
}
|
2130
|
+
get owner() {
|
2131
|
+
return getCoValueOwner(this.fileStream);
|
2132
|
+
}
|
2133
|
+
/**
|
2134
|
+
* An instance method to subscribe to an existing `FileStream`
|
2135
|
+
* @category Subscription & Loading
|
2136
|
+
*/
|
2137
|
+
subscribe(listener) {
|
2138
|
+
return subscribeToExistingCoValue(this.fileStream, {}, listener);
|
2139
|
+
}
|
2140
|
+
/**
|
2141
|
+
* Wait for the `FileStream` to be uploaded to the other peers.
|
2142
|
+
*
|
2143
|
+
* @category Subscription & Loading
|
2144
|
+
*/
|
2145
|
+
waitForSync(options) {
|
2146
|
+
return this.raw.core.waitForSync(options);
|
2147
|
+
}
|
2148
|
+
};
|
2149
|
+
|
2150
|
+
// src/tools/coValues/account.ts
|
2151
|
+
import {
|
2152
|
+
ControlledAccount as RawControlledAccount,
|
2153
|
+
LocalNode as LocalNode2,
|
2154
|
+
cojsonInternals as cojsonInternals4
|
2155
|
+
} from "cojson";
|
2156
|
+
var Account = class extends CoValueBase {
|
2157
|
+
constructor(options) {
|
2158
|
+
super();
|
2159
|
+
if (!("fromRaw" in options)) {
|
2160
|
+
throw new Error("Can only construct account from raw or with .create()");
|
2161
|
+
}
|
2162
|
+
const proxy = new Proxy(
|
2163
|
+
this,
|
2164
|
+
AccountAndGroupProxyHandler
|
2165
|
+
);
|
2166
|
+
Object.defineProperties(this, {
|
2167
|
+
[TypeSym]: { value: "Account", enumerable: false },
|
2168
|
+
$jazz: {
|
2169
|
+
value: new AccountJazzApi(proxy, options.fromRaw),
|
2170
|
+
enumerable: false
|
2171
|
+
}
|
2172
|
+
});
|
2173
|
+
return proxy;
|
2174
|
+
}
|
2175
|
+
/**
|
2176
|
+
* Whether this account is the currently active account.
|
2177
|
+
*/
|
2178
|
+
get isMe() {
|
2179
|
+
return activeAccountContext.get().$jazz.id === this.$jazz.id;
|
2180
|
+
}
|
2181
|
+
/**
|
2182
|
+
* Accept an invite to a `CoValue` or `Group`.
|
2183
|
+
*
|
2184
|
+
* @param valueID The ID of the `CoValue` or `Group` to accept the invite to.
|
2185
|
+
* @param inviteSecret The secret of the invite to accept.
|
2186
|
+
* @param coValueClass The class of the `CoValue` or `Group` to accept the invite to.
|
2187
|
+
* @returns The loaded `CoValue` or `Group`.
|
2188
|
+
*/
|
2189
|
+
async acceptInvite(valueID, inviteSecret, coValueClass) {
|
2190
|
+
if (!this.$jazz.isLocalNodeOwner) {
|
2191
|
+
throw new Error("Only a controlled account can accept invites");
|
2192
|
+
}
|
2193
|
+
await this.$jazz.localNode.acceptInvite(
|
2194
|
+
valueID,
|
2195
|
+
inviteSecret
|
2196
|
+
);
|
2197
|
+
return loadCoValue(
|
2198
|
+
coValueClassFromCoValueClassOrSchema(coValueClass),
|
2199
|
+
valueID,
|
2200
|
+
{
|
2201
|
+
loadAs: this
|
2202
|
+
}
|
2203
|
+
);
|
2204
|
+
}
|
2205
|
+
getRoleOf(member) {
|
2206
|
+
if (member === "me") {
|
2207
|
+
return this.isMe ? "admin" : void 0;
|
2208
|
+
}
|
2209
|
+
if (member === this.$jazz.id) {
|
2210
|
+
return "admin";
|
2211
|
+
}
|
2212
|
+
return void 0;
|
2213
|
+
}
|
2214
|
+
canRead(value) {
|
2215
|
+
const valueOwner = value.$jazz.owner;
|
2216
|
+
if (!valueOwner) {
|
2217
|
+
return true;
|
2218
|
+
}
|
2219
|
+
const role = valueOwner.getRoleOf(this.$jazz.id);
|
2220
|
+
return role === "admin" || role === "writer" || role === "reader" || role === "writeOnly";
|
2221
|
+
}
|
2222
|
+
canWrite(value) {
|
2223
|
+
const valueOwner = value.$jazz.owner;
|
2224
|
+
if (!valueOwner) {
|
2225
|
+
if (value[TypeSym] === "Group") {
|
2226
|
+
const roleInGroup = value.getRoleOf(this.$jazz.id);
|
2227
|
+
return roleInGroup === "admin" || roleInGroup === "writer";
|
2228
|
+
}
|
2229
|
+
if (value[TypeSym] === "Account") {
|
2230
|
+
return value.$jazz.id === this.$jazz.id;
|
2231
|
+
}
|
2232
|
+
return false;
|
2233
|
+
}
|
2234
|
+
const role = valueOwner.getRoleOf(this.$jazz.id);
|
2235
|
+
return role === "admin" || role === "writer" || role === "writeOnly";
|
2236
|
+
}
|
2237
|
+
canAdmin(value) {
|
2238
|
+
const valueOwner = value.$jazz.owner;
|
2239
|
+
if (!valueOwner) {
|
2240
|
+
if (value[TypeSym] === "Group") {
|
2241
|
+
const roleInGroup = value.getRoleOf(this.$jazz.id);
|
2242
|
+
return roleInGroup === "admin";
|
2243
|
+
}
|
2244
|
+
if (value[TypeSym] === "Account") {
|
2245
|
+
return value.$jazz.id === this.$jazz.id;
|
2246
|
+
}
|
2247
|
+
return false;
|
2248
|
+
}
|
2249
|
+
return valueOwner.getRoleOf(this.$jazz.id) === "admin";
|
2250
|
+
}
|
2251
|
+
/** @private */
|
2252
|
+
static async create(options) {
|
2253
|
+
const { node } = await LocalNode2.withNewlyCreatedAccount({
|
2254
|
+
...options,
|
2255
|
+
migration: async (rawAccount, _node, creationProps) => {
|
2256
|
+
const account = new this({
|
2257
|
+
fromRaw: rawAccount
|
2258
|
+
});
|
2259
|
+
await account.applyMigration?.(creationProps);
|
2260
|
+
}
|
2261
|
+
});
|
2262
|
+
return this.fromNode(node);
|
2263
|
+
}
|
2264
|
+
static getMe() {
|
2265
|
+
return activeAccountContext.get();
|
2266
|
+
}
|
2267
|
+
/**
|
2268
|
+
* @deprecated Use `co.account(...).createAs` instead.
|
2269
|
+
*/
|
2270
|
+
static async createAs(as, options) {
|
2271
|
+
const connectedPeers = cojsonInternals4.connectedPeers(
|
2272
|
+
"creatingAccount",
|
2273
|
+
"createdAccount",
|
2274
|
+
{ peer1role: "server", peer2role: "client" }
|
2275
|
+
);
|
2276
|
+
as.$jazz.localNode.syncManager.addPeer(connectedPeers[1]);
|
2277
|
+
const account = await this.create({
|
2278
|
+
creationProps: options.creationProps,
|
2279
|
+
crypto: as.$jazz.localNode.crypto,
|
2280
|
+
peersToLoadFrom: [connectedPeers[0]]
|
2281
|
+
});
|
2282
|
+
await account.$jazz.waitForAllCoValuesSync();
|
2283
|
+
return account;
|
2284
|
+
}
|
2285
|
+
static fromNode(node) {
|
2286
|
+
return new this({
|
2287
|
+
fromRaw: node.expectCurrentAccount("jazz-tools/Account.fromNode")
|
2288
|
+
});
|
2289
|
+
}
|
2290
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2291
|
+
toJSON() {
|
2292
|
+
return {};
|
2293
|
+
}
|
2294
|
+
[inspect2]() {
|
2295
|
+
return this.toJSON();
|
2296
|
+
}
|
2297
|
+
async applyMigration(creationProps) {
|
2298
|
+
await this.migrate(creationProps);
|
2299
|
+
if (this.profile === void 0 && creationProps) {
|
2300
|
+
const profileGroup = RegisteredSchemas["Group"].create({ owner: this });
|
2301
|
+
this.$jazz.set(
|
2302
|
+
"profile",
|
2303
|
+
Profile.create({ name: creationProps.name }, profileGroup)
|
2304
|
+
);
|
2305
|
+
profileGroup.addMember("everyone", "reader");
|
2306
|
+
}
|
2307
|
+
const profile = this.$jazz.localNode.expectCoValueLoaded(this.$jazz.raw.get("profile")).getCurrentContent();
|
2308
|
+
if (!profile.get("inbox")) {
|
2309
|
+
const inboxRoot = createInboxRoot(this);
|
2310
|
+
profile.set("inbox", inboxRoot.id);
|
2311
|
+
profile.set("inboxInvite", inboxRoot.inviteLink);
|
2312
|
+
}
|
2313
|
+
}
|
2314
|
+
// Placeholder method for subclasses to override
|
2315
|
+
migrate(creationProps) {
|
2316
|
+
creationProps;
|
2317
|
+
}
|
2318
|
+
/**
|
2319
|
+
* Load an `Account`
|
2320
|
+
* @category Subscription & Loading
|
2321
|
+
* @deprecated Use `co.account(...).load` instead.
|
2322
|
+
*/
|
2323
|
+
static load(id, options) {
|
2324
|
+
return loadCoValueWithoutMe(this, id, options);
|
2325
|
+
}
|
2326
|
+
static subscribe(id, ...args) {
|
2327
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2328
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
2329
|
+
}
|
2330
|
+
};
|
2331
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2332
|
+
Account._schema = {
|
2333
|
+
profile: {
|
2334
|
+
ref: () => Profile,
|
2335
|
+
optional: false
|
2336
|
+
},
|
2337
|
+
root: {
|
2338
|
+
ref: () => RegisteredSchemas["CoMap"],
|
2339
|
+
optional: true
|
2340
|
+
}
|
2341
|
+
};
|
2342
|
+
var AccountJazzApi = class extends CoValueJazzApi {
|
2343
|
+
constructor(account, raw) {
|
2344
|
+
super(account);
|
2345
|
+
this.account = account;
|
2346
|
+
this.raw = raw;
|
2347
|
+
this.isLocalNodeOwner = this.raw.id === this.localNode.getCurrentAgent().id;
|
2348
|
+
if (this.isLocalNodeOwner) {
|
2349
|
+
this.sessionID = this.localNode.currentSessionID;
|
2350
|
+
}
|
2351
|
+
}
|
2352
|
+
/**
|
2353
|
+
* The ID of this `Account`
|
2354
|
+
* @category Content
|
2355
|
+
*/
|
2356
|
+
get id() {
|
2357
|
+
return this.raw.id;
|
2358
|
+
}
|
2359
|
+
/**
|
2360
|
+
* Accounts have no owner. They can be accessed by everyone.
|
2361
|
+
*/
|
2362
|
+
get owner() {
|
2363
|
+
return void 0;
|
2364
|
+
}
|
2365
|
+
/**
|
2366
|
+
* Set the value of a key in the account.
|
2367
|
+
*
|
2368
|
+
* @param key The key to set.
|
2369
|
+
* @param value The value to set.
|
2370
|
+
*
|
2371
|
+
* @category Content
|
2372
|
+
*/
|
2373
|
+
set(key, value) {
|
2374
|
+
if (value) {
|
2375
|
+
let refId = value.$jazz?.id;
|
2376
|
+
if (!refId) {
|
2377
|
+
const descriptor = this.schema[key];
|
2378
|
+
const coValue = instantiateRefEncodedWithInit(
|
2379
|
+
descriptor,
|
2380
|
+
value,
|
2381
|
+
accountOrGroupToGroup(this.account)
|
2382
|
+
);
|
2383
|
+
refId = coValue.$jazz.id;
|
2384
|
+
}
|
2385
|
+
this.raw.set(key, refId, "trusting");
|
2386
|
+
}
|
2387
|
+
}
|
2388
|
+
/**
|
2389
|
+
* Get the descriptor for a given key
|
2390
|
+
* @internal
|
2391
|
+
*/
|
2392
|
+
getDescriptor(key) {
|
2393
|
+
if (key === "profile") {
|
2394
|
+
return this.schema.profile;
|
2395
|
+
} else if (key === "root") {
|
2396
|
+
return this.schema.root;
|
2397
|
+
}
|
2398
|
+
return void 0;
|
2399
|
+
}
|
2400
|
+
/**
|
2401
|
+
* If property `prop` is a `coField.ref(...)`, you can use `account.$jazz.refs.prop` to access
|
2402
|
+
* the `Ref` instead of the potentially loaded/null value.
|
2403
|
+
*
|
2404
|
+
* This allows you to always get the ID or load the value manually.
|
2405
|
+
*
|
2406
|
+
* @category Content
|
2407
|
+
*/
|
2408
|
+
get refs() {
|
2409
|
+
const profileID = this.raw.get("profile");
|
2410
|
+
const rootID = this.raw.get("root");
|
2411
|
+
return {
|
2412
|
+
profile: profileID ? new Ref(
|
2413
|
+
profileID,
|
2414
|
+
this.loadedAs,
|
2415
|
+
this.schema.profile,
|
2416
|
+
this.account
|
2417
|
+
) : void 0,
|
2418
|
+
root: rootID ? new Ref(
|
2419
|
+
rootID,
|
2420
|
+
this.loadedAs,
|
2421
|
+
this.schema.root,
|
2422
|
+
this.account
|
2423
|
+
) : void 0
|
2424
|
+
};
|
2425
|
+
}
|
2426
|
+
/** @category Subscription & Loading */
|
2427
|
+
ensureLoaded(options) {
|
2428
|
+
return ensureCoValueLoaded(this.account, options);
|
2429
|
+
}
|
2430
|
+
subscribe(...args) {
|
2431
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2432
|
+
return subscribeToExistingCoValue(this.account, options, listener);
|
2433
|
+
}
|
2434
|
+
/**
|
2435
|
+
* Wait for the `Account` to be uploaded to the other peers.
|
2436
|
+
*
|
2437
|
+
* @category Subscription & Loading
|
2438
|
+
*/
|
2439
|
+
waitForSync(options) {
|
2440
|
+
return this.raw.core.waitForSync(options);
|
2441
|
+
}
|
2442
|
+
/**
|
2443
|
+
* Wait for all the available `CoValues` to be uploaded to the other peers.
|
2444
|
+
*
|
2445
|
+
* @category Subscription & Loading
|
2446
|
+
*/
|
2447
|
+
waitForAllCoValuesSync(options) {
|
2448
|
+
return this.localNode.syncManager.waitForAllCoValuesSync(options?.timeout);
|
2449
|
+
}
|
2450
|
+
/** @internal */
|
2451
|
+
get schema() {
|
2452
|
+
return this.account.constructor._schema;
|
2453
|
+
}
|
2454
|
+
get loadedAs() {
|
2455
|
+
if (this.isLocalNodeOwner) return this.account;
|
2456
|
+
const agent = this.localNode.getCurrentAgent();
|
2457
|
+
if (agent instanceof RawControlledAccount) {
|
2458
|
+
return coValuesCache.get(
|
2459
|
+
agent.account,
|
2460
|
+
() => Account.fromRaw(agent.account)
|
2461
|
+
);
|
2462
|
+
}
|
2463
|
+
return new AnonymousJazzAgent2(this.localNode);
|
2464
|
+
}
|
2465
|
+
};
|
2466
|
+
var AccountAndGroupProxyHandler = {
|
2467
|
+
get(target, key, receiver) {
|
2468
|
+
if (key === "profile" || key === "root") {
|
2469
|
+
const id = target.$jazz.raw.get(key);
|
2470
|
+
if (id) {
|
2471
|
+
return accessChildByKey(target, id, key);
|
2472
|
+
} else {
|
2473
|
+
return void 0;
|
2474
|
+
}
|
2475
|
+
} else {
|
2476
|
+
return Reflect.get(target, key, receiver);
|
2477
|
+
}
|
2478
|
+
},
|
2479
|
+
set(target, key, value, receiver) {
|
2480
|
+
if (target instanceof Account && (key === "profile" || key === "root") && typeof value === "object" && SchemaInit in value) {
|
2481
|
+
target.constructor._schema ||= {};
|
2482
|
+
target.constructor._schema[key] = value[SchemaInit];
|
2483
|
+
return true;
|
2484
|
+
} else if (target instanceof Account && (key === "profile" || key === "root")) {
|
2485
|
+
if (value) {
|
2486
|
+
target.$jazz.set(key, value);
|
2487
|
+
}
|
2488
|
+
return true;
|
2489
|
+
} else {
|
2490
|
+
return Reflect.set(target, key, value, receiver);
|
2491
|
+
}
|
2492
|
+
},
|
2493
|
+
defineProperty(target, key, descriptor) {
|
2494
|
+
if ((key === "profile" || key === "root") && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
|
2495
|
+
target.constructor._schema ||= {};
|
2496
|
+
target.constructor._schema[key] = descriptor.value[SchemaInit];
|
2497
|
+
return true;
|
2498
|
+
} else {
|
2499
|
+
return Reflect.defineProperty(target, key, descriptor);
|
2500
|
+
}
|
2501
|
+
}
|
2502
|
+
};
|
2503
|
+
function isControlledAccount(account) {
|
2504
|
+
return account.$jazz.isLocalNodeOwner;
|
2505
|
+
}
|
2506
|
+
RegisteredSchemas["Account"] = Account;
|
2507
|
+
|
2508
|
+
// src/tools/coValues/group.ts
|
2509
|
+
var _Group = class _Group extends CoValueBase {
|
2510
|
+
/** @deprecated Don't use constructor directly, use .create */
|
2511
|
+
constructor(options) {
|
2512
|
+
super();
|
2513
|
+
let raw;
|
2514
|
+
if (options && "fromRaw" in options) {
|
2515
|
+
raw = options.fromRaw;
|
2516
|
+
} else {
|
2517
|
+
const initOwner = options.owner;
|
2518
|
+
if (!initOwner) throw new Error("No owner provided");
|
2519
|
+
if (initOwner[TypeSym] === "Account" && isControlledAccount(initOwner)) {
|
2520
|
+
const rawOwner = initOwner.$jazz.raw;
|
2521
|
+
raw = rawOwner.core.node.createGroup();
|
2522
|
+
} else {
|
2523
|
+
throw new Error("Can only construct group as a controlled account");
|
2524
|
+
}
|
2525
|
+
}
|
2526
|
+
const proxy = new Proxy(
|
2527
|
+
this,
|
2528
|
+
AccountAndGroupProxyHandler
|
2529
|
+
);
|
2530
|
+
Object.defineProperties(this, {
|
2531
|
+
$jazz: {
|
2532
|
+
value: new GroupJazzApi(proxy, raw),
|
2533
|
+
enumerable: false
|
2534
|
+
}
|
2535
|
+
});
|
2536
|
+
return proxy;
|
2537
|
+
}
|
2538
|
+
static create(options) {
|
2539
|
+
return new this(parseGroupCreateOptions(options));
|
2540
|
+
}
|
2541
|
+
myRole() {
|
2542
|
+
return this.$jazz.raw.myRole();
|
2543
|
+
}
|
2544
|
+
addMember(member, role) {
|
2545
|
+
if (member !== "everyone" && member[TypeSym] === "Group") {
|
2546
|
+
if (role === "writeOnly")
|
2547
|
+
throw new Error("Cannot add group as member with write-only role");
|
2548
|
+
this.$jazz.raw.extend(member.$jazz.raw, role);
|
2549
|
+
} else if (role !== void 0 && role !== "inherit") {
|
2550
|
+
this.$jazz.raw.addMember(
|
2551
|
+
member === "everyone" ? member : member.$jazz.raw,
|
2552
|
+
role
|
2553
|
+
);
|
2554
|
+
}
|
2555
|
+
}
|
2556
|
+
removeMember(member) {
|
2557
|
+
if (member !== "everyone" && member[TypeSym] === "Group") {
|
2558
|
+
this.$jazz.raw.revokeExtend(member.$jazz.raw);
|
2559
|
+
} else {
|
2560
|
+
return this.$jazz.raw.removeMember(
|
2561
|
+
member === "everyone" ? member : member.$jazz.raw
|
2562
|
+
);
|
2563
|
+
}
|
2564
|
+
}
|
2565
|
+
getMembersFromKeys(accountIDs) {
|
2566
|
+
const members = [];
|
2567
|
+
const refEncodedAccountSchema = {
|
2568
|
+
ref: () => Account,
|
2569
|
+
optional: false
|
2570
|
+
};
|
2571
|
+
for (const accountID of accountIDs) {
|
2572
|
+
if (!isAccountID(accountID)) continue;
|
2573
|
+
const role = this.$jazz.raw.roleOf(accountID);
|
2574
|
+
if (role === "admin" || role === "writer" || role === "reader" || role === "writeOnly") {
|
2575
|
+
const ref2 = new Ref(
|
2576
|
+
accountID,
|
2577
|
+
this.$jazz.loadedAs,
|
2578
|
+
refEncodedAccountSchema,
|
2579
|
+
this
|
2580
|
+
);
|
2581
|
+
const group = this;
|
2582
|
+
members.push({
|
2583
|
+
id: accountID,
|
2584
|
+
role,
|
2585
|
+
ref: ref2,
|
2586
|
+
get account() {
|
2587
|
+
return accessChildById(group, accountID, refEncodedAccountSchema);
|
2588
|
+
}
|
2589
|
+
});
|
2590
|
+
}
|
2591
|
+
}
|
2592
|
+
return members;
|
2593
|
+
}
|
2594
|
+
/**
|
2595
|
+
* Returns all members of the group, including inherited members from parent
|
2596
|
+
* groups.
|
2597
|
+
*
|
2598
|
+
* If you need only the direct members of the group, use
|
2599
|
+
* {@link getDirectMembers} instead.
|
2600
|
+
*
|
2601
|
+
* @returns The members of the group.
|
2602
|
+
*/
|
2603
|
+
get members() {
|
2604
|
+
return this.getMembersFromKeys(this.$jazz.raw.getAllMemberKeysSet());
|
2605
|
+
}
|
2606
|
+
/**
|
2607
|
+
* Returns the direct members of the group.
|
2608
|
+
*
|
2609
|
+
* If you need all members of the group, including inherited members from
|
2610
|
+
* parent groups, use {@link Group.members|members} instead.
|
2611
|
+
* @returns The direct members of the group.
|
2612
|
+
*/
|
2613
|
+
getDirectMembers() {
|
2614
|
+
return this.getMembersFromKeys(this.$jazz.raw.getMemberKeys());
|
2615
|
+
}
|
2616
|
+
getRoleOf(member) {
|
2617
|
+
const accountId = member === "me" ? activeAccountContext.get().$jazz.id : member === "everyone" ? member : member;
|
2618
|
+
return this.$jazz.raw.roleOf(accountId);
|
2619
|
+
}
|
2620
|
+
/**
|
2621
|
+
* Make the group public, so that everyone can read it.
|
2622
|
+
* Alias for `addMember("everyone", role)`.
|
2623
|
+
*
|
2624
|
+
* @param role - Optional: the role to grant to everyone. Defaults to "reader".
|
2625
|
+
* @returns The group itself.
|
2626
|
+
*/
|
2627
|
+
makePublic(role = "reader") {
|
2628
|
+
this.addMember("everyone", role);
|
2629
|
+
return this;
|
2630
|
+
}
|
2631
|
+
getParentGroups() {
|
2632
|
+
return this.$jazz.raw.getParentGroups().map((group) => _Group.fromRaw(group));
|
2633
|
+
}
|
2634
|
+
/** @category Identity & Permissions
|
2635
|
+
* Gives members of a parent group membership in this group.
|
2636
|
+
* @deprecated Use `addMember` instead.
|
2637
|
+
* @param parent The group that will gain access to this group.
|
2638
|
+
* @param roleMapping The role all members of the parent group should have in this group.
|
2639
|
+
* @returns This group.
|
2640
|
+
*/
|
2641
|
+
extend(parent, roleMapping) {
|
2642
|
+
this.$jazz.raw.extend(parent.$jazz.raw, roleMapping);
|
2643
|
+
return this;
|
2644
|
+
}
|
2645
|
+
/** @category Identity & Permissions
|
2646
|
+
* Revokes membership from members a parent group.
|
2647
|
+
* @deprecated Use `removeMember` instead.
|
2648
|
+
* @param parent The group that will lose access to this group.
|
2649
|
+
* @returns This group.
|
2650
|
+
*/
|
2651
|
+
async revokeExtend(parent) {
|
2652
|
+
await this.$jazz.raw.revokeExtend(parent.$jazz.raw);
|
2653
|
+
return this;
|
2654
|
+
}
|
2655
|
+
/** @category Subscription & Loading */
|
2656
|
+
static load(id, options) {
|
2657
|
+
return loadCoValueWithoutMe(this, id, options);
|
2658
|
+
}
|
2659
|
+
static subscribe(id, ...args) {
|
2660
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2661
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
2662
|
+
}
|
2663
|
+
};
|
2664
|
+
_Group.prototype[TypeSym] = "Group";
|
2665
|
+
var Group6 = _Group;
|
2666
|
+
var GroupJazzApi = class extends CoValueJazzApi {
|
2667
|
+
constructor(group, raw) {
|
2668
|
+
super(group);
|
2669
|
+
this.group = group;
|
2670
|
+
this.raw = raw;
|
2671
|
+
}
|
2672
|
+
/**
|
2673
|
+
* The ID of this `Group`
|
2674
|
+
* @category Content
|
2675
|
+
*/
|
2676
|
+
get id() {
|
2677
|
+
return this.raw.id;
|
2678
|
+
}
|
2679
|
+
/**
|
2680
|
+
* Groups have no owner. They can be accessed by everyone.
|
2681
|
+
*/
|
2682
|
+
get owner() {
|
2683
|
+
return void 0;
|
2684
|
+
}
|
2685
|
+
/** @category Subscription & Loading */
|
2686
|
+
ensureLoaded(options) {
|
2687
|
+
return ensureCoValueLoaded(this.group, options);
|
2688
|
+
}
|
2689
|
+
subscribe(...args) {
|
2690
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2691
|
+
return subscribeToExistingCoValue(this.group, options, listener);
|
2692
|
+
}
|
2693
|
+
/**
|
2694
|
+
* Wait for the `Group` to be uploaded to the other peers.
|
2695
|
+
*
|
2696
|
+
* @category Subscription & Loading
|
2697
|
+
*/
|
2698
|
+
waitForSync(options) {
|
2699
|
+
return this.raw.core.waitForSync(options);
|
2700
|
+
}
|
2701
|
+
};
|
2702
|
+
RegisteredSchemas["Group"] = Group6;
|
2703
|
+
function isAccountID(id) {
|
2704
|
+
return id.startsWith("co_");
|
2705
|
+
}
|
2706
|
+
function getCoValueOwner(coValue) {
|
2707
|
+
const group = accessChildById(coValue, coValue.$jazz.raw.group.id, {
|
2708
|
+
ref: RegisteredSchemas["Group"],
|
2709
|
+
optional: false
|
2710
|
+
});
|
2711
|
+
if (!group) {
|
2712
|
+
throw new Error("CoValue has no owner");
|
2713
|
+
}
|
2714
|
+
return group;
|
2715
|
+
}
|
2716
|
+
|
2717
|
+
// src/tools/coValues/profile.ts
|
2718
|
+
var Profile = class extends CoMap {
|
2719
|
+
constructor() {
|
2720
|
+
super(...arguments);
|
2721
|
+
this.name = coField.string;
|
2722
|
+
this.inbox = coField.optional.string;
|
2723
|
+
this.inboxInvite = coField.optional.string;
|
2724
|
+
}
|
2725
|
+
/**
|
2726
|
+
* Creates a new profile with the given initial values and owner.
|
2727
|
+
*
|
2728
|
+
* The owner (a Group) determines access rights to the Profile.
|
2729
|
+
*
|
2730
|
+
* @category Creation
|
2731
|
+
* @deprecated Use `co.profile(...).create` instead.
|
2732
|
+
*/
|
2733
|
+
static create(init, options) {
|
2734
|
+
const owner = options !== void 0 && "owner" in options ? options.owner : options;
|
2735
|
+
if (owner?.[TypeSym] === "Account") {
|
2736
|
+
throw new Error("Profiles should be owned by a group");
|
2737
|
+
}
|
2738
|
+
return super.create(init, options);
|
2739
|
+
}
|
2740
|
+
};
|
2741
|
+
|
2742
|
+
// src/tools/coValues/inbox.ts
|
2743
|
+
import { RawAccount as RawAccount2 } from "cojson";
|
2744
|
+
function createInboxRoot(account) {
|
2745
|
+
if (!account.$jazz.isLocalNodeOwner) {
|
2746
|
+
throw new Error("Account is not controlled");
|
2747
|
+
}
|
2748
|
+
const rawAccount = account.$jazz.raw;
|
2749
|
+
const group = rawAccount.core.node.createGroup();
|
2750
|
+
const messagesFeed = group.createStream();
|
2751
|
+
const inboxRoot = rawAccount.createMap();
|
2752
|
+
const processedFeed = rawAccount.createStream();
|
2753
|
+
const failedFeed = rawAccount.createStream();
|
2754
|
+
const inviteLink = `${messagesFeed.id}/${group.createInvite("writeOnly")}`;
|
2755
|
+
inboxRoot.set("messages", messagesFeed.id);
|
2756
|
+
inboxRoot.set("processed", processedFeed.id);
|
2757
|
+
inboxRoot.set("failed", failedFeed.id);
|
2758
|
+
return {
|
2759
|
+
id: inboxRoot.id,
|
2760
|
+
inviteLink
|
2761
|
+
};
|
2762
|
+
}
|
2763
|
+
|
2764
|
+
// src/tools/coValues/coPlainText.ts
|
2765
|
+
import { stringifyOpID } from "cojson";
|
2766
|
+
import { calcPatch as calcPatch2 } from "fast-myers-diff";
|
2767
|
+
var CoPlainText = class extends String {
|
2768
|
+
/** @internal */
|
2769
|
+
constructor(options) {
|
2770
|
+
if (!options) {
|
2771
|
+
super("");
|
2772
|
+
return;
|
2773
|
+
}
|
2774
|
+
if ("fromRaw" in options) {
|
2775
|
+
super(options.fromRaw.toString());
|
2776
|
+
const raw = options.fromRaw;
|
2777
|
+
Object.defineProperties(this, {
|
2778
|
+
[TypeSym]: { value: "CoPlainText", enumerable: false },
|
2779
|
+
$jazz: {
|
2780
|
+
value: new CoTextJazzApi(this, raw),
|
2781
|
+
enumerable: false
|
2782
|
+
}
|
2783
|
+
});
|
2784
|
+
return;
|
2785
|
+
}
|
2786
|
+
if ("text" in options && "owner" in options) {
|
2787
|
+
super(options.text);
|
2788
|
+
const raw = options.owner.$jazz.raw.createPlainText(options.text);
|
2789
|
+
Object.defineProperties(this, {
|
2790
|
+
[TypeSym]: { value: "CoPlainText", enumerable: false },
|
2791
|
+
$jazz: {
|
2792
|
+
value: new CoTextJazzApi(this, raw),
|
2793
|
+
enumerable: false
|
2794
|
+
}
|
2795
|
+
});
|
2796
|
+
return;
|
2797
|
+
}
|
2798
|
+
throw new Error("Invalid constructor arguments");
|
2799
|
+
}
|
2800
|
+
/**
|
2801
|
+
* Create a new `CoPlainText` with the given text and owner.
|
2802
|
+
*
|
2803
|
+
* The owner (a Group or Account) determines access rights to the CoPlainText.
|
2804
|
+
*
|
2805
|
+
* The CoPlainText will immediately be persisted and synced to connected peers.
|
2806
|
+
*
|
2807
|
+
* @example
|
2808
|
+
* ```ts
|
2809
|
+
* const text = CoPlainText.create("Hello, world!", { owner: me });
|
2810
|
+
* ```
|
2811
|
+
*
|
2812
|
+
* @category Creation
|
2813
|
+
* @deprecated Use `co.plainText(...).create` instead.
|
2814
|
+
*/
|
2815
|
+
static create(text, options) {
|
2816
|
+
const { owner } = parseCoValueCreateOptions(options);
|
2817
|
+
return new this({ text, owner });
|
2818
|
+
}
|
2819
|
+
get length() {
|
2820
|
+
return this.$jazz.raw.toString().length;
|
2821
|
+
}
|
2822
|
+
toString() {
|
2823
|
+
return this.$jazz.raw.toString();
|
2824
|
+
}
|
2825
|
+
valueOf() {
|
2826
|
+
return this.$jazz.raw.toString();
|
2827
|
+
}
|
2828
|
+
toJSON() {
|
2829
|
+
return this.$jazz.raw.toString();
|
2830
|
+
}
|
2831
|
+
[inspect2]() {
|
2832
|
+
return this.toJSON();
|
2833
|
+
}
|
2834
|
+
insertBefore(idx, text) {
|
2835
|
+
this.$jazz.raw.insertBefore(idx, text);
|
2836
|
+
}
|
2837
|
+
insertAfter(idx, text) {
|
2838
|
+
this.$jazz.raw.insertAfter(idx, text);
|
2839
|
+
}
|
2840
|
+
deleteRange(range) {
|
2841
|
+
this.$jazz.raw.deleteRange(range);
|
2842
|
+
}
|
2843
|
+
posBefore(idx) {
|
2844
|
+
return this.$jazz.raw.mapping.opIDbeforeIdx[idx];
|
2845
|
+
}
|
2846
|
+
posAfter(idx) {
|
2847
|
+
return this.$jazz.raw.mapping.opIDafterIdx[idx];
|
2848
|
+
}
|
2849
|
+
idxBefore(pos) {
|
2850
|
+
return this.$jazz.raw.mapping.idxBeforeOpID[stringifyOpID(pos)];
|
2851
|
+
}
|
2852
|
+
idxAfter(pos) {
|
2853
|
+
return this.$jazz.raw.mapping.idxAfterOpID[stringifyOpID(pos)];
|
2854
|
+
}
|
2855
|
+
/** @category Internals */
|
2856
|
+
static fromRaw(raw) {
|
2857
|
+
return new this({ fromRaw: raw });
|
2858
|
+
}
|
2859
|
+
/**
|
2860
|
+
* Load a `CoPlainText` with a given ID, as a given account.
|
2861
|
+
*
|
2862
|
+
* @category Subscription & Loading
|
2863
|
+
* @deprecated Use `co.plainText(...).load` instead.
|
2864
|
+
*/
|
2865
|
+
static load(id, options) {
|
2866
|
+
return loadCoValueWithoutMe(this, id, options);
|
2867
|
+
}
|
2868
|
+
static subscribe(id, ...args) {
|
2869
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
2870
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
2871
|
+
}
|
2872
|
+
/**
|
2873
|
+
* Allow CoPlainText to behave like a primitive string in most contexts (e.g.,
|
2874
|
+
* string concatenation, template literals, React rendering, etc.) by implementing
|
2875
|
+
* Symbol.toPrimitive. This eliminates the need to call .toString() explicitly.
|
2876
|
+
*
|
2877
|
+
* The 'hint' parameter indicates the preferred type of conversion:
|
2878
|
+
* - 'string': prefer string conversion
|
2879
|
+
* - 'number': prefer number conversion (attempt to parse the text as a number)
|
2880
|
+
* - 'default': usually treat as string
|
2881
|
+
*/
|
2882
|
+
[Symbol.toPrimitive](hint) {
|
2883
|
+
if (hint === "number") {
|
2884
|
+
return Number(this.$jazz.raw.toString());
|
2885
|
+
}
|
2886
|
+
return this.$jazz.raw.toString();
|
2887
|
+
}
|
2888
|
+
};
|
2889
|
+
var CoTextJazzApi = class extends CoValueJazzApi {
|
2890
|
+
constructor(coText, raw) {
|
2891
|
+
super(coText);
|
2892
|
+
this.coText = coText;
|
2893
|
+
this.raw = raw;
|
2894
|
+
}
|
2895
|
+
get id() {
|
2896
|
+
return this.raw.id;
|
2897
|
+
}
|
2898
|
+
get owner() {
|
2899
|
+
return getCoValueOwner(this.coText);
|
2900
|
+
}
|
2901
|
+
/**
|
2902
|
+
* Apply text, modifying the text in place. Calculates the diff and applies it to the CoValue.
|
2903
|
+
*
|
2904
|
+
* @category Mutation
|
2905
|
+
*/
|
2906
|
+
applyDiff(other) {
|
2907
|
+
const current = this.raw.toString();
|
2908
|
+
const currentGraphemes = this.raw.toGraphemes(current);
|
2909
|
+
const otherGraphemes = this.raw.toGraphemes(other);
|
2910
|
+
const patches = [...calcPatch2(currentGraphemes, otherGraphemes)];
|
2911
|
+
for (const [from, to, insert] of patches.reverse()) {
|
2912
|
+
if (to > from) {
|
2913
|
+
this.coText.deleteRange({ from, to });
|
2914
|
+
}
|
2915
|
+
if (insert.length > 0) {
|
2916
|
+
this.coText.insertBefore(from, this.raw.fromGraphemes(insert));
|
2917
|
+
}
|
2918
|
+
}
|
2919
|
+
}
|
2920
|
+
/**
|
2921
|
+
* Given an already loaded `CoPlainText`, subscribe to updates to the `CoPlainText` and ensure that the specified fields are loaded to the specified depth.
|
2922
|
+
*
|
2923
|
+
* Works like `CoPlainText.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
2924
|
+
*
|
2925
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
2926
|
+
*
|
2927
|
+
* @category Subscription & Loading
|
2928
|
+
**/
|
2929
|
+
subscribe(listener) {
|
2930
|
+
return subscribeToExistingCoValue(this.coText, {}, listener);
|
2931
|
+
}
|
2932
|
+
};
|
2933
|
+
|
2934
|
+
// src/tools/coValues/coRichText.ts
|
2935
|
+
var CoRichText = class extends CoPlainText {
|
2936
|
+
};
|
2937
|
+
|
2938
|
+
// src/tools/coValues/schemaUnion.ts
|
2939
|
+
var SchemaUnion = class _SchemaUnion extends CoValueBase {
|
2940
|
+
/**
|
2941
|
+
* Create a new union type from a discriminator function.
|
2942
|
+
*
|
2943
|
+
* The discriminator function receives the raw data and should return the appropriate concrete class to use for that data.
|
2944
|
+
*
|
2945
|
+
* When loading a SchemaUnion, the correct subclass will be instantiated based on the discriminator.
|
2946
|
+
*
|
2947
|
+
* @param discriminator - Function that determines which concrete type to use
|
2948
|
+
* @returns A new class that can create/load instances of the union type
|
2949
|
+
*
|
2950
|
+
* @example
|
2951
|
+
* ```ts
|
2952
|
+
* const WidgetUnion = SchemaUnion.Of<BaseWidget>((raw) => {
|
2953
|
+
* switch (raw.get("type")) {
|
2954
|
+
* case "button": return ButtonWidget;
|
2955
|
+
* case "slider": return SliderWidget;
|
2956
|
+
* default: throw new Error("Unknown widget type");
|
2957
|
+
* }
|
2958
|
+
* });
|
2959
|
+
*
|
2960
|
+
* const widget = await loadCoValue(WidgetUnion, id, me, {});
|
2961
|
+
*
|
2962
|
+
* // You can narrow the returned instance to a subclass by using `instanceof`
|
2963
|
+
* if (widget instanceof ButtonWidget) {
|
2964
|
+
* console.log(widget.label);
|
2965
|
+
* } else if (widget instanceof SliderWidget) {
|
2966
|
+
* console.log(widget.min, widget.max);
|
2967
|
+
* }
|
2968
|
+
* ```
|
2969
|
+
*
|
2970
|
+
* @category Declaration
|
2971
|
+
**/
|
2972
|
+
static Of(discriminator) {
|
2973
|
+
return class SchemaUnionClass extends _SchemaUnion {
|
2974
|
+
static create(init, owner) {
|
2975
|
+
const ResolvedClass = discriminator(new Map(Object.entries(init)));
|
2976
|
+
return ResolvedClass.create(init, owner);
|
2977
|
+
}
|
2978
|
+
static fromRaw(raw) {
|
2979
|
+
const ResolvedClass = discriminator(
|
2980
|
+
raw
|
2981
|
+
);
|
2982
|
+
return ResolvedClass.fromRaw(raw);
|
2983
|
+
}
|
2984
|
+
};
|
2985
|
+
}
|
2986
|
+
static create(init, owner) {
|
2987
|
+
throw new Error("Not implemented");
|
2988
|
+
}
|
2989
|
+
/**
|
2990
|
+
* Create an instance from raw data. This is called internally and should not be used directly.
|
2991
|
+
* Use {@link SchemaUnion.Of} to create a union type instead.
|
2992
|
+
*
|
2993
|
+
* @internal
|
2994
|
+
*/
|
2995
|
+
static fromRaw(raw) {
|
2996
|
+
throw new Error("Not implemented");
|
2997
|
+
}
|
2998
|
+
/**
|
2999
|
+
* Load a `SchemaUnion` with a given ID, as a given account.
|
3000
|
+
*
|
3001
|
+
* Note: The `resolve` option is not supported for `SchemaUnion`s due to https://github.com/garden-co/jazz/issues/2639
|
3002
|
+
*
|
3003
|
+
* @category Subscription & Loading
|
3004
|
+
*/
|
3005
|
+
static load(id, options) {
|
3006
|
+
return loadCoValueWithoutMe(this, id, options);
|
3007
|
+
}
|
3008
|
+
static subscribe(id, ...args) {
|
3009
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
3010
|
+
return subscribeToCoValueWithoutMe(this, id, options, listener);
|
3011
|
+
}
|
3012
|
+
};
|
3013
|
+
|
3014
|
+
// src/tools/implementation/anonymousJazzAgent.ts
|
3015
|
+
var _a;
|
3016
|
+
_a = TypeSym;
|
3017
|
+
var AnonymousJazzAgent2 = class {
|
3018
|
+
constructor(node) {
|
3019
|
+
this.node = node;
|
3020
|
+
this[_a] = "Anonymous";
|
3021
|
+
}
|
3022
|
+
};
|
3023
|
+
|
3024
|
+
// src/tools/implementation/activeAccountContext.ts
|
3025
|
+
var ActiveAccountContext = class {
|
3026
|
+
constructor() {
|
3027
|
+
this.activeAccount = null;
|
3028
|
+
this.guestMode = false;
|
3029
|
+
}
|
3030
|
+
set(account) {
|
3031
|
+
this.activeAccount = account;
|
3032
|
+
this.guestMode = false;
|
3033
|
+
}
|
3034
|
+
setGuestMode() {
|
3035
|
+
this.activeAccount = null;
|
3036
|
+
this.guestMode = true;
|
3037
|
+
}
|
3038
|
+
maybeGet() {
|
3039
|
+
return this.activeAccount;
|
3040
|
+
}
|
3041
|
+
get() {
|
3042
|
+
if (!this.activeAccount) {
|
3043
|
+
if (this.guestMode) {
|
3044
|
+
throw new Error(
|
3045
|
+
"Something that expects a full active account was called in guest mode."
|
3046
|
+
);
|
3047
|
+
}
|
3048
|
+
throw new Error("No active account");
|
3049
|
+
}
|
3050
|
+
return this.activeAccount;
|
3051
|
+
}
|
3052
|
+
};
|
3053
|
+
var activeAccountContext = new ActiveAccountContext();
|
3054
|
+
|
3055
|
+
// src/tools/implementation/refs.ts
|
3056
|
+
var Ref = class {
|
3057
|
+
constructor(id, controlledAccount, schema, parent) {
|
3058
|
+
this.id = id;
|
3059
|
+
this.controlledAccount = controlledAccount;
|
3060
|
+
this.schema = schema;
|
3061
|
+
this.parent = parent;
|
3062
|
+
if (!isRefEncoded(schema)) {
|
3063
|
+
throw new Error("Ref must be constructed with a ref schema");
|
3064
|
+
}
|
3065
|
+
}
|
3066
|
+
async load() {
|
3067
|
+
const subscriptionScope = getSubscriptionScope(this.parent);
|
3068
|
+
subscriptionScope.subscribeToId(this.id, this.schema);
|
3069
|
+
const node = subscriptionScope.childNodes.get(this.id);
|
3070
|
+
if (!node) {
|
3071
|
+
return null;
|
3072
|
+
}
|
3073
|
+
const value = node.value;
|
3074
|
+
if (value?.type === "loaded") {
|
3075
|
+
return value.value;
|
3076
|
+
} else {
|
3077
|
+
return new Promise((resolve) => {
|
3078
|
+
const unsubscribe = node.subscribe((value2) => {
|
3079
|
+
if (value2?.type === "loaded") {
|
3080
|
+
unsubscribe();
|
3081
|
+
resolve(value2.value);
|
3082
|
+
} else if (value2?.type === "unavailable") {
|
3083
|
+
unsubscribe();
|
3084
|
+
resolve(null);
|
3085
|
+
} else if (value2?.type === "unauthorized") {
|
3086
|
+
unsubscribe();
|
3087
|
+
resolve(null);
|
3088
|
+
}
|
3089
|
+
});
|
3090
|
+
});
|
3091
|
+
}
|
3092
|
+
}
|
3093
|
+
get value() {
|
3094
|
+
return accessChildById(this.parent, this.id, this.schema);
|
3095
|
+
}
|
3096
|
+
};
|
3097
|
+
function makeRefs(parent, getIdForKey, getKeysWithIds, controlledAccount, refSchemaForKey) {
|
3098
|
+
const refs = {};
|
3099
|
+
return new Proxy(refs, {
|
3100
|
+
get(_target, key) {
|
3101
|
+
if (key === Symbol.iterator) {
|
3102
|
+
return function* () {
|
3103
|
+
for (const key2 of getKeysWithIds()) {
|
3104
|
+
yield new Ref(
|
3105
|
+
getIdForKey(key2),
|
3106
|
+
controlledAccount,
|
3107
|
+
refSchemaForKey(key2),
|
3108
|
+
parent
|
3109
|
+
);
|
3110
|
+
}
|
3111
|
+
};
|
3112
|
+
}
|
3113
|
+
if (typeof key === "symbol") return void 0;
|
3114
|
+
if (key === "length") {
|
3115
|
+
return getKeysWithIds().length;
|
3116
|
+
}
|
3117
|
+
const id = getIdForKey(key);
|
3118
|
+
if (!id) return void 0;
|
3119
|
+
return new Ref(
|
3120
|
+
id,
|
3121
|
+
controlledAccount,
|
3122
|
+
refSchemaForKey(key),
|
3123
|
+
parent
|
3124
|
+
);
|
3125
|
+
},
|
3126
|
+
ownKeys() {
|
3127
|
+
return getKeysWithIds().map((key) => key.toString());
|
3128
|
+
},
|
3129
|
+
getOwnPropertyDescriptor(target, key) {
|
3130
|
+
const id = getIdForKey(key);
|
3131
|
+
if (id) {
|
3132
|
+
return {
|
3133
|
+
enumerable: true,
|
3134
|
+
configurable: true,
|
3135
|
+
writable: true
|
3136
|
+
};
|
3137
|
+
} else {
|
3138
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
3139
|
+
}
|
3140
|
+
}
|
3141
|
+
});
|
3142
|
+
}
|
3143
|
+
|
3144
|
+
// src/tools/implementation/schema.ts
|
3145
|
+
var Encoders = {
|
3146
|
+
Date: {
|
3147
|
+
encode: (value) => value.toISOString(),
|
3148
|
+
decode: (value) => new Date(value)
|
3149
|
+
},
|
3150
|
+
OptionalDate: {
|
3151
|
+
encode: (value) => value?.toISOString() || null,
|
3152
|
+
decode: (value) => value === null ? void 0 : new Date(value)
|
3153
|
+
}
|
3154
|
+
};
|
3155
|
+
var optional = {
|
3156
|
+
ref: optionalRef,
|
3157
|
+
json() {
|
3158
|
+
return { [SchemaInit]: "json" };
|
3159
|
+
},
|
3160
|
+
encoded(arg) {
|
3161
|
+
return { [SchemaInit]: { encoded: arg } };
|
3162
|
+
},
|
3163
|
+
string: {
|
3164
|
+
[SchemaInit]: "json"
|
3165
|
+
},
|
3166
|
+
number: {
|
3167
|
+
[SchemaInit]: "json"
|
3168
|
+
},
|
3169
|
+
boolean: {
|
3170
|
+
[SchemaInit]: "json"
|
3171
|
+
},
|
3172
|
+
null: {
|
3173
|
+
[SchemaInit]: "json"
|
3174
|
+
},
|
3175
|
+
Date: {
|
3176
|
+
[SchemaInit]: { encoded: Encoders.OptionalDate }
|
3177
|
+
},
|
3178
|
+
literal(..._lit) {
|
3179
|
+
return { [SchemaInit]: "json" };
|
3180
|
+
}
|
3181
|
+
};
|
3182
|
+
var coField = {
|
3183
|
+
string: {
|
3184
|
+
[SchemaInit]: "json"
|
3185
|
+
},
|
3186
|
+
number: {
|
3187
|
+
[SchemaInit]: "json"
|
3188
|
+
},
|
3189
|
+
boolean: {
|
3190
|
+
[SchemaInit]: "json"
|
3191
|
+
},
|
3192
|
+
null: {
|
3193
|
+
[SchemaInit]: "json"
|
3194
|
+
},
|
3195
|
+
Date: {
|
3196
|
+
[SchemaInit]: { encoded: Encoders.Date }
|
3197
|
+
},
|
3198
|
+
literal(..._lit) {
|
3199
|
+
return { [SchemaInit]: "json" };
|
3200
|
+
},
|
3201
|
+
json() {
|
3202
|
+
return { [SchemaInit]: "json" };
|
3203
|
+
},
|
3204
|
+
encoded(arg) {
|
3205
|
+
return { [SchemaInit]: { encoded: arg } };
|
3206
|
+
},
|
3207
|
+
ref,
|
3208
|
+
items: ItemsSym,
|
3209
|
+
optional
|
3210
|
+
};
|
3211
|
+
function optionalRef(arg) {
|
3212
|
+
return ref(arg, { optional: true });
|
3213
|
+
}
|
3214
|
+
function ref(arg, options) {
|
3215
|
+
return {
|
3216
|
+
[SchemaInit]: {
|
3217
|
+
ref: arg,
|
3218
|
+
optional: options?.optional || false
|
3219
|
+
}
|
3220
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
3221
|
+
};
|
3222
|
+
}
|
3223
|
+
function isRefEncoded(schema) {
|
3224
|
+
return typeof schema === "object" && "ref" in schema && "optional" in schema && typeof schema.ref === "function";
|
3225
|
+
}
|
3226
|
+
function instantiateRefEncodedFromRaw(schema, raw) {
|
3227
|
+
return isCoValueClass(schema.ref) ? schema.ref.fromRaw(raw) : schema.ref(
|
3228
|
+
raw
|
3229
|
+
).fromRaw(raw);
|
3230
|
+
}
|
3231
|
+
function instantiateRefEncodedWithInit(schema, init, parentOwner) {
|
3232
|
+
if (!isCoValueClass(schema.ref)) {
|
3233
|
+
throw Error(
|
3234
|
+
`Cannot automatically create CoValue from value: ${JSON.stringify(init)}. Use the CoValue schema's create() method instead.`
|
3235
|
+
);
|
3236
|
+
}
|
3237
|
+
const node = parentOwner.$jazz.localNode;
|
3238
|
+
const rawGroup = node.createGroup();
|
3239
|
+
const owner = new Group6({ fromRaw: rawGroup });
|
3240
|
+
owner.addMember(parentOwner);
|
3241
|
+
return schema.ref.create(init, owner);
|
3242
|
+
}
|
3243
|
+
|
3244
|
+
// src/tools/lib/migration.ts
|
3245
|
+
function applyCoValueMigrations(instance) {
|
3246
|
+
const node = instance.$jazz.raw.core.node;
|
3247
|
+
const migratedCoValues = node._migratedCoValues ??= /* @__PURE__ */ new Set();
|
3248
|
+
if ("migrate" in instance && typeof instance.migrate === "function" && instance[TypeSym] !== "Account" && !migratedCoValues.has(instance.$jazz.id)) {
|
3249
|
+
migratedCoValues.add(instance.$jazz.id);
|
3250
|
+
const result = instance.migrate?.(instance);
|
3251
|
+
if (result && "then" in result) {
|
3252
|
+
throw new Error("Migration function cannot be async");
|
3253
|
+
}
|
3254
|
+
}
|
3255
|
+
}
|
3256
|
+
|
3257
|
+
// src/tools/subscribe/CoValueCoreSubscription.ts
|
3258
|
+
var CoValueCoreSubscription = class {
|
3259
|
+
constructor(node, id, listener, skipRetry) {
|
3260
|
+
this.node = node;
|
3261
|
+
this.id = id;
|
3262
|
+
this.listener = listener;
|
3263
|
+
this.skipRetry = skipRetry;
|
3264
|
+
this._unsubscribe = () => {
|
3265
|
+
};
|
3266
|
+
this.unsubscribed = false;
|
3267
|
+
const entry = this.node.getCoValue(this.id);
|
3268
|
+
if (entry?.isAvailable()) {
|
3269
|
+
this.subscribe(entry.getCurrentContent());
|
3270
|
+
} else {
|
3271
|
+
this.node.loadCoValueCore(this.id, void 0, skipRetry).then((value) => {
|
3272
|
+
if (this.unsubscribed) return;
|
3273
|
+
if (value.isAvailable()) {
|
3274
|
+
this.subscribe(value.getCurrentContent());
|
3275
|
+
} else {
|
3276
|
+
this.subscribeToState();
|
3277
|
+
this.listener("unavailable");
|
3278
|
+
}
|
3279
|
+
}).catch((error) => {
|
3280
|
+
console.error("Unexpected error loading CoValue: ", error);
|
3281
|
+
this.listener("unavailable");
|
3282
|
+
});
|
3283
|
+
}
|
3284
|
+
}
|
3285
|
+
subscribeToState() {
|
3286
|
+
const entry = this.node.getCoValue(this.id);
|
3287
|
+
const handleStateChange = (core2, unsubFromStateChange2) => {
|
3288
|
+
if (this.unsubscribed) {
|
3289
|
+
unsubFromStateChange2();
|
3290
|
+
return;
|
3291
|
+
}
|
3292
|
+
if (core2.isAvailable()) {
|
3293
|
+
this.subscribe(core2.getCurrentContent());
|
3294
|
+
unsubFromStateChange2();
|
3295
|
+
}
|
3296
|
+
};
|
3297
|
+
const unsubFromStateChange = entry.subscribe(handleStateChange);
|
3298
|
+
this._unsubscribe = () => {
|
3299
|
+
unsubFromStateChange();
|
3300
|
+
};
|
3301
|
+
}
|
3302
|
+
subscribe(value) {
|
3303
|
+
if (this.unsubscribed) return;
|
3304
|
+
this._unsubscribe = value.subscribe((value2) => {
|
3305
|
+
this.listener(value2);
|
3306
|
+
});
|
3307
|
+
this.listener(value);
|
3308
|
+
}
|
3309
|
+
unsubscribe() {
|
3310
|
+
if (this.unsubscribed) return;
|
3311
|
+
this.unsubscribed = true;
|
3312
|
+
this._unsubscribe();
|
3313
|
+
}
|
3314
|
+
};
|
3315
|
+
|
3316
|
+
// src/tools/subscribe/JazzError.ts
|
3317
|
+
var JazzError = class _JazzError {
|
3318
|
+
constructor(id, type, issues) {
|
3319
|
+
this.id = id;
|
3320
|
+
this.type = type;
|
3321
|
+
this.issues = issues;
|
3322
|
+
}
|
3323
|
+
toString() {
|
3324
|
+
return this.issues.map((issue) => {
|
3325
|
+
let message = `${issue.message}`;
|
3326
|
+
if (this.id) {
|
3327
|
+
message += ` from ${this.id}`;
|
3328
|
+
}
|
3329
|
+
if (issue.path.length > 0) {
|
3330
|
+
message += ` on path ${issue.path.join(".")}`;
|
3331
|
+
}
|
3332
|
+
return message;
|
3333
|
+
}).join("\n");
|
3334
|
+
}
|
3335
|
+
prependPath(item) {
|
3336
|
+
if (this.issues.length === 0) {
|
3337
|
+
return this;
|
3338
|
+
}
|
3339
|
+
const issues = this.issues.map((issue) => {
|
3340
|
+
return {
|
3341
|
+
...issue,
|
3342
|
+
path: [item].concat(issue.path)
|
3343
|
+
};
|
3344
|
+
});
|
3345
|
+
return new _JazzError(this.id, this.type, issues);
|
3346
|
+
}
|
3347
|
+
};
|
3348
|
+
|
3349
|
+
// src/tools/subscribe/utils.ts
|
3350
|
+
import { RawAccount as RawAccount3 } from "cojson";
|
3351
|
+
|
3352
|
+
// src/tools/lib/cache.ts
|
3353
|
+
var weakMap = /* @__PURE__ */ new WeakMap();
|
3354
|
+
var coValuesCache = {
|
3355
|
+
get: (raw, compute) => {
|
3356
|
+
const cached = weakMap.get(raw);
|
3357
|
+
if (cached) {
|
3358
|
+
return cached;
|
3359
|
+
}
|
3360
|
+
const computed = compute();
|
3361
|
+
weakMap.set(raw, computed);
|
3362
|
+
return computed;
|
3363
|
+
}
|
3364
|
+
};
|
3365
|
+
|
3366
|
+
// src/tools/subscribe/utils.ts
|
3367
|
+
function myRoleForRawValue(raw) {
|
3368
|
+
const rawOwner = raw.group;
|
3369
|
+
const owner = coValuesCache.get(
|
3370
|
+
rawOwner,
|
3371
|
+
() => rawOwner instanceof RawAccount3 ? RegisteredSchemas["Account"].fromRaw(rawOwner) : RegisteredSchemas["Group"].fromRaw(rawOwner)
|
3372
|
+
);
|
3373
|
+
return accountOrGroupToGroup(owner).myRole();
|
3374
|
+
}
|
3375
|
+
function createCoValue(ref2, raw, subscriptionScope) {
|
3376
|
+
const freshValueInstance = instantiateRefEncodedFromRaw(ref2, raw);
|
3377
|
+
Object.defineProperty(freshValueInstance.$jazz, "_subscriptionScope", {
|
3378
|
+
value: subscriptionScope,
|
3379
|
+
writable: false,
|
3380
|
+
enumerable: false,
|
3381
|
+
configurable: false
|
3382
|
+
});
|
3383
|
+
return {
|
3384
|
+
type: "loaded",
|
3385
|
+
value: freshValueInstance,
|
3386
|
+
id: subscriptionScope.id
|
3387
|
+
};
|
3388
|
+
}
|
3389
|
+
|
3390
|
+
// src/tools/subscribe/SubscriptionScope.ts
|
3391
|
+
var SubscriptionScope = class _SubscriptionScope {
|
3392
|
+
constructor(node, resolve, id, schema, skipRetry = false, bestEffortResolution = false) {
|
3393
|
+
this.node = node;
|
3394
|
+
this.id = id;
|
3395
|
+
this.schema = schema;
|
3396
|
+
this.skipRetry = skipRetry;
|
3397
|
+
this.bestEffortResolution = bestEffortResolution;
|
3398
|
+
this.childNodes = /* @__PURE__ */ new Map();
|
3399
|
+
this.childValues = /* @__PURE__ */ new Map();
|
3400
|
+
this.childErrors = /* @__PURE__ */ new Map();
|
3401
|
+
this.validationErrors = /* @__PURE__ */ new Map();
|
3402
|
+
this.dirty = false;
|
3403
|
+
this.idsSubscribed = /* @__PURE__ */ new Set();
|
3404
|
+
this.autoloaded = /* @__PURE__ */ new Set();
|
3405
|
+
this.autoloadedKeys = /* @__PURE__ */ new Set();
|
3406
|
+
this.skipInvalidKeys = /* @__PURE__ */ new Set();
|
3407
|
+
this.totalValidTransactions = 0;
|
3408
|
+
this.migrated = false;
|
3409
|
+
this.migrating = false;
|
3410
|
+
this.silenceUpdates = false;
|
3411
|
+
this.handleChildUpdate = (id, value, key) => {
|
3412
|
+
if (value.type === "unloaded") {
|
3413
|
+
return;
|
3414
|
+
}
|
3415
|
+
this.childValues.set(id, value);
|
3416
|
+
if (value.type === "unavailable" || value.type === "unauthorized") {
|
3417
|
+
this.childErrors.set(id, value.prependPath(key ?? id));
|
3418
|
+
this.errorFromChildren = this.computeChildErrors();
|
3419
|
+
} else if (this.errorFromChildren && this.childErrors.has(id)) {
|
3420
|
+
this.childErrors.delete(id);
|
3421
|
+
this.errorFromChildren = this.computeChildErrors();
|
3422
|
+
}
|
3423
|
+
if (this.shouldSendUpdates()) {
|
3424
|
+
if (this.value.type === "loaded") {
|
3425
|
+
this.updateValue(
|
3426
|
+
createCoValue(this.schema, this.value.value.$jazz.raw, this)
|
3427
|
+
);
|
3428
|
+
}
|
3429
|
+
}
|
3430
|
+
this.triggerUpdate();
|
3431
|
+
};
|
3432
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
3433
|
+
this.resolve = resolve;
|
3434
|
+
this.value = { type: "unloaded", id };
|
3435
|
+
let lastUpdate;
|
3436
|
+
this.subscription = new CoValueCoreSubscription(
|
3437
|
+
node,
|
3438
|
+
id,
|
3439
|
+
(value) => {
|
3440
|
+
lastUpdate = value;
|
3441
|
+
if (skipRetry && value === "unavailable") {
|
3442
|
+
this.handleUpdate(value);
|
3443
|
+
this.destroy();
|
3444
|
+
return;
|
3445
|
+
}
|
3446
|
+
if (!this.migrated && value !== "unavailable") {
|
3447
|
+
if (this.migrating) {
|
3448
|
+
return;
|
3449
|
+
}
|
3450
|
+
this.migrating = true;
|
3451
|
+
applyCoValueMigrations(
|
3452
|
+
instantiateRefEncodedFromRaw(this.schema, value)
|
3453
|
+
);
|
3454
|
+
this.migrated = true;
|
3455
|
+
this.handleUpdate(lastUpdate);
|
3456
|
+
return;
|
3457
|
+
}
|
3458
|
+
this.handleUpdate(value);
|
3459
|
+
},
|
3460
|
+
skipRetry
|
3461
|
+
);
|
3462
|
+
}
|
3463
|
+
updateValue(value) {
|
3464
|
+
this.value = value;
|
3465
|
+
this.dirty = true;
|
3466
|
+
}
|
3467
|
+
handleUpdate(update) {
|
3468
|
+
if (update === "unavailable") {
|
3469
|
+
if (this.value.type === "unloaded") {
|
3470
|
+
this.updateValue(
|
3471
|
+
new JazzError(this.id, "unavailable", [
|
3472
|
+
{
|
3473
|
+
code: "unavailable",
|
3474
|
+
message: "The value is unavailable",
|
3475
|
+
params: {
|
3476
|
+
id: this.id
|
3477
|
+
},
|
3478
|
+
path: []
|
3479
|
+
}
|
3480
|
+
])
|
3481
|
+
);
|
3482
|
+
}
|
3483
|
+
this.triggerUpdate();
|
3484
|
+
return;
|
3485
|
+
}
|
3486
|
+
const ruleset = update.core.verified.header.ruleset;
|
3487
|
+
const hasAccess = ruleset.type !== "ownedByGroup" || myRoleForRawValue(update) !== void 0;
|
3488
|
+
if (!hasAccess) {
|
3489
|
+
if (this.value.type !== "unauthorized") {
|
3490
|
+
this.updateValue(
|
3491
|
+
new JazzError(this.id, "unauthorized", [
|
3492
|
+
{
|
3493
|
+
code: "unauthorized",
|
3494
|
+
message: `The current user (${this.node.getCurrentAgent().id}) is not authorized to access this value`,
|
3495
|
+
params: {
|
3496
|
+
id: this.id
|
3497
|
+
},
|
3498
|
+
path: []
|
3499
|
+
}
|
3500
|
+
])
|
3501
|
+
);
|
3502
|
+
this.triggerUpdate();
|
3503
|
+
}
|
3504
|
+
return;
|
3505
|
+
}
|
3506
|
+
this.silenceUpdates = true;
|
3507
|
+
if (this.value.type !== "loaded") {
|
3508
|
+
this.updateValue(createCoValue(this.schema, update, this));
|
3509
|
+
this.loadChildren();
|
3510
|
+
} else {
|
3511
|
+
const hasChanged = update.totalValidTransactions !== this.totalValidTransactions || // Checking the identity of the raw value makes us cover the cases where the group
|
3512
|
+
// has been updated and the coValues that don't update the totalValidTransactions value (e.g. FileStream)
|
3513
|
+
this.value.value.$jazz.raw !== update;
|
3514
|
+
if (this.loadChildren()) {
|
3515
|
+
this.updateValue(createCoValue(this.schema, update, this));
|
3516
|
+
} else if (hasChanged) {
|
3517
|
+
this.updateValue(createCoValue(this.schema, update, this));
|
3518
|
+
}
|
3519
|
+
}
|
3520
|
+
this.totalValidTransactions = update.totalValidTransactions;
|
3521
|
+
this.silenceUpdates = false;
|
3522
|
+
this.triggerUpdate();
|
3523
|
+
}
|
3524
|
+
computeChildErrors() {
|
3525
|
+
let issues = [];
|
3526
|
+
let errorType = "unavailable";
|
3527
|
+
if (this.childErrors.size === 0 && this.validationErrors.size === 0) {
|
3528
|
+
return void 0;
|
3529
|
+
}
|
3530
|
+
if (this.bestEffortResolution) {
|
3531
|
+
return void 0;
|
3532
|
+
}
|
3533
|
+
for (const [key, value] of this.childErrors.entries()) {
|
3534
|
+
if (this.autoloaded.has(key)) {
|
3535
|
+
continue;
|
3536
|
+
}
|
3537
|
+
if (this.skipInvalidKeys.has(key)) {
|
3538
|
+
continue;
|
3539
|
+
}
|
3540
|
+
errorType = value.type;
|
3541
|
+
if (value.issues) {
|
3542
|
+
issues.push(...value.issues);
|
3543
|
+
}
|
3544
|
+
}
|
3545
|
+
for (const [key, value] of this.validationErrors.entries()) {
|
3546
|
+
if (this.skipInvalidKeys.has(key)) {
|
3547
|
+
continue;
|
3548
|
+
}
|
3549
|
+
errorType = value.type;
|
3550
|
+
if (value.issues) {
|
3551
|
+
issues.push(...value.issues);
|
3552
|
+
}
|
3553
|
+
}
|
3554
|
+
if (issues.length) {
|
3555
|
+
return new JazzError(this.id, errorType, issues);
|
3556
|
+
}
|
3557
|
+
return void 0;
|
3558
|
+
}
|
3559
|
+
shouldSendUpdates() {
|
3560
|
+
if (this.value.type === "unloaded") return false;
|
3561
|
+
if (this.value.type !== "loaded") return true;
|
3562
|
+
if (this.isStreaming() && !this.isFileStream()) {
|
3563
|
+
return false;
|
3564
|
+
}
|
3565
|
+
for (const value of this.childValues.values()) {
|
3566
|
+
if (value.type === "unloaded" && !this.autoloaded.has(value.id)) {
|
3567
|
+
return false;
|
3568
|
+
}
|
3569
|
+
}
|
3570
|
+
return true;
|
3571
|
+
}
|
3572
|
+
getCurrentValue() {
|
3573
|
+
if (this.value.type === "unauthorized" || this.value.type === "unavailable") {
|
3574
|
+
console.error(this.value.toString());
|
3575
|
+
return null;
|
3576
|
+
}
|
3577
|
+
if (!this.shouldSendUpdates()) {
|
3578
|
+
return void 0;
|
3579
|
+
}
|
3580
|
+
if (this.errorFromChildren) {
|
3581
|
+
console.error(this.errorFromChildren.toString());
|
3582
|
+
return null;
|
3583
|
+
}
|
3584
|
+
if (this.value.type === "loaded") {
|
3585
|
+
return this.value.value;
|
3586
|
+
}
|
3587
|
+
return void 0;
|
3588
|
+
}
|
3589
|
+
isStreaming() {
|
3590
|
+
if (this.value.type !== "loaded") {
|
3591
|
+
return false;
|
3592
|
+
}
|
3593
|
+
return this.value.value.$jazz.raw.core.verified.isStreaming();
|
3594
|
+
}
|
3595
|
+
isFileStream() {
|
3596
|
+
if (this.value.type !== "loaded") {
|
3597
|
+
return false;
|
3598
|
+
}
|
3599
|
+
return this.value.value.$jazz.raw.core.verified.header.meta?.type === "binary";
|
3600
|
+
}
|
3601
|
+
triggerUpdate() {
|
3602
|
+
if (!this.shouldSendUpdates()) return;
|
3603
|
+
if (!this.dirty) return;
|
3604
|
+
if (this.subscribers.size === 0) return;
|
3605
|
+
if (this.silenceUpdates) return;
|
3606
|
+
const error = this.errorFromChildren;
|
3607
|
+
const value = this.value;
|
3608
|
+
if (error) {
|
3609
|
+
this.subscribers.forEach((listener) => listener(error));
|
3610
|
+
} else if (value.type !== "unloaded") {
|
3611
|
+
this.subscribers.forEach((listener) => listener(value));
|
3612
|
+
}
|
3613
|
+
this.dirty = false;
|
3614
|
+
}
|
3615
|
+
subscribe(listener) {
|
3616
|
+
this.subscribers.add(listener);
|
3617
|
+
return () => {
|
3618
|
+
this.subscribers.delete(listener);
|
3619
|
+
};
|
3620
|
+
}
|
3621
|
+
setListener(listener) {
|
3622
|
+
this.subscribers.add(listener);
|
3623
|
+
this.triggerUpdate();
|
3624
|
+
}
|
3625
|
+
subscribeToKey(key) {
|
3626
|
+
if (this.resolve === true || !this.resolve) {
|
3627
|
+
this.resolve = {};
|
3628
|
+
}
|
3629
|
+
if (!this.resolve.$each && !(key in this.resolve)) {
|
3630
|
+
const resolve = this.resolve;
|
3631
|
+
resolve[key] = true;
|
3632
|
+
this.autoloadedKeys.add(key);
|
3633
|
+
}
|
3634
|
+
if (this.value.type !== "loaded") {
|
3635
|
+
return;
|
3636
|
+
}
|
3637
|
+
const value = this.value.value;
|
3638
|
+
this.silenceUpdates = true;
|
3639
|
+
if (value[TypeSym] === "CoMap" || value[TypeSym] === "Account") {
|
3640
|
+
const map = value;
|
3641
|
+
this.loadCoMapKey(map, key, true);
|
3642
|
+
} else if (value[TypeSym] === "CoList") {
|
3643
|
+
const list = value;
|
3644
|
+
this.loadCoListKey(list, key, true);
|
3645
|
+
}
|
3646
|
+
this.silenceUpdates = false;
|
3647
|
+
}
|
3648
|
+
subscribeToId(id, descriptor) {
|
3649
|
+
if (this.idsSubscribed.has(id) || this.childValues.has(id)) {
|
3650
|
+
return;
|
3651
|
+
}
|
3652
|
+
this.idsSubscribed.add(id);
|
3653
|
+
this.autoloaded.add(id);
|
3654
|
+
this.silenceUpdates = true;
|
3655
|
+
this.childValues.set(id, { type: "unloaded", id });
|
3656
|
+
const child = new _SubscriptionScope(
|
3657
|
+
this.node,
|
3658
|
+
true,
|
3659
|
+
id,
|
3660
|
+
descriptor,
|
3661
|
+
this.skipRetry,
|
3662
|
+
this.bestEffortResolution
|
3663
|
+
);
|
3664
|
+
this.childNodes.set(id, child);
|
3665
|
+
child.setListener((value) => this.handleChildUpdate(id, value));
|
3666
|
+
this.silenceUpdates = false;
|
3667
|
+
}
|
3668
|
+
loadChildren() {
|
3669
|
+
const { resolve } = this;
|
3670
|
+
if (this.value.type !== "loaded") {
|
3671
|
+
return false;
|
3672
|
+
}
|
3673
|
+
const value = this.value.value;
|
3674
|
+
const depth = typeof resolve !== "object" || resolve === null ? {} : resolve;
|
3675
|
+
let hasChanged = false;
|
3676
|
+
const idsToLoad = new Set(this.idsSubscribed);
|
3677
|
+
const coValueType = value[TypeSym];
|
3678
|
+
if (Object.keys(depth).length > 0) {
|
3679
|
+
if (coValueType === "CoMap" || coValueType === "Account" || coValueType === "Group") {
|
3680
|
+
const map = value;
|
3681
|
+
const keys = "$each" in depth ? map.$jazz.raw.keys() : Object.keys(depth);
|
3682
|
+
for (const key of keys) {
|
3683
|
+
const id = this.loadCoMapKey(map, key, depth[key] ?? depth.$each);
|
3684
|
+
if (id) {
|
3685
|
+
idsToLoad.add(id);
|
3686
|
+
}
|
3687
|
+
}
|
3688
|
+
} else if (value[TypeSym] === "CoList") {
|
3689
|
+
const list = value;
|
3690
|
+
const descriptor = list.$jazz.getItemsDescriptor();
|
3691
|
+
if (descriptor && isRefEncoded(descriptor)) {
|
3692
|
+
list.$jazz.raw.processNewTransactions();
|
3693
|
+
const entries = list.$jazz.raw.entries();
|
3694
|
+
const keys = "$each" in depth ? Object.keys(entries) : Object.keys(depth);
|
3695
|
+
for (const key of keys) {
|
3696
|
+
const id = this.loadCoListKey(list, key, depth[key] ?? depth.$each);
|
3697
|
+
if (id) {
|
3698
|
+
idsToLoad.add(id);
|
3699
|
+
}
|
3700
|
+
}
|
3701
|
+
}
|
3702
|
+
} else if (value[TypeSym] === "CoStream") {
|
3703
|
+
const stream = value;
|
3704
|
+
const descriptor = stream.$jazz.getItemsDescriptor();
|
3705
|
+
if (descriptor && isRefEncoded(descriptor)) {
|
3706
|
+
for (const session of stream.$jazz.raw.sessions()) {
|
3707
|
+
const values = stream.$jazz.raw.items[session] ?? [];
|
3708
|
+
for (const [i, item] of values.entries()) {
|
3709
|
+
const key = `${session}/${i}`;
|
3710
|
+
if (!depth.$each && !depth[key]) {
|
3711
|
+
continue;
|
3712
|
+
}
|
3713
|
+
const id = item.value;
|
3714
|
+
if (id) {
|
3715
|
+
idsToLoad.add(id);
|
3716
|
+
this.loadChildNode(id, depth[key] ?? depth.$each, descriptor);
|
3717
|
+
this.validationErrors.delete(key);
|
3718
|
+
} else if (!descriptor.optional) {
|
3719
|
+
this.validationErrors.set(
|
3720
|
+
key,
|
3721
|
+
new JazzError(void 0, "unavailable", [
|
3722
|
+
{
|
3723
|
+
code: "validationError",
|
3724
|
+
message: `The ref on position ${key} requested on ${stream.constructor.name} is missing`,
|
3725
|
+
params: {},
|
3726
|
+
path: [key]
|
3727
|
+
}
|
3728
|
+
])
|
3729
|
+
);
|
3730
|
+
}
|
3731
|
+
}
|
3732
|
+
}
|
3733
|
+
}
|
3734
|
+
}
|
3735
|
+
}
|
3736
|
+
this.errorFromChildren = this.computeChildErrors();
|
3737
|
+
for (const id of this.childNodes.keys()) {
|
3738
|
+
if (!idsToLoad.has(id)) {
|
3739
|
+
hasChanged = true;
|
3740
|
+
const childNode = this.childNodes.get(id);
|
3741
|
+
if (childNode) {
|
3742
|
+
childNode.destroy();
|
3743
|
+
}
|
3744
|
+
this.childNodes.delete(id);
|
3745
|
+
this.childValues.delete(id);
|
3746
|
+
}
|
3747
|
+
}
|
3748
|
+
return hasChanged;
|
3749
|
+
}
|
3750
|
+
loadCoMapKey(map, key, depth) {
|
3751
|
+
if (key === "$onError") {
|
3752
|
+
return void 0;
|
3753
|
+
}
|
3754
|
+
const id = map.$jazz.raw.get(key);
|
3755
|
+
const descriptor = map.$jazz.getDescriptor(key);
|
3756
|
+
if (!descriptor) {
|
3757
|
+
this.childErrors.set(
|
3758
|
+
key,
|
3759
|
+
new JazzError(void 0, "unavailable", [
|
3760
|
+
{
|
3761
|
+
code: "validationError",
|
3762
|
+
message: `The ref ${key} requested on ${map.constructor.name} is not defined in the schema`,
|
3763
|
+
params: {},
|
3764
|
+
path: [key]
|
3765
|
+
}
|
3766
|
+
])
|
3767
|
+
);
|
3768
|
+
return void 0;
|
3769
|
+
}
|
3770
|
+
if (isRefEncoded(descriptor)) {
|
3771
|
+
if (id) {
|
3772
|
+
this.loadChildNode(id, depth, descriptor, key);
|
3773
|
+
this.validationErrors.delete(key);
|
3774
|
+
return id;
|
3775
|
+
} else if (!descriptor.optional) {
|
3776
|
+
this.validationErrors.set(
|
3777
|
+
key,
|
3778
|
+
new JazzError(void 0, "unavailable", [
|
3779
|
+
{
|
3780
|
+
code: "validationError",
|
3781
|
+
message: `The ref ${key} requested on ${map.constructor.name} is missing`,
|
3782
|
+
params: {},
|
3783
|
+
path: [key]
|
3784
|
+
}
|
3785
|
+
])
|
3786
|
+
);
|
3787
|
+
}
|
3788
|
+
}
|
3789
|
+
return void 0;
|
3790
|
+
}
|
3791
|
+
loadCoListKey(list, key, depth) {
|
3792
|
+
const descriptor = list.$jazz.getItemsDescriptor();
|
3793
|
+
if (!descriptor || !isRefEncoded(descriptor)) {
|
3794
|
+
return void 0;
|
3795
|
+
}
|
3796
|
+
const entries = list.$jazz.raw.entries();
|
3797
|
+
const entry = entries[Number(key)];
|
3798
|
+
if (!entry) {
|
3799
|
+
return void 0;
|
3800
|
+
}
|
3801
|
+
const id = entry.value;
|
3802
|
+
if (id) {
|
3803
|
+
this.loadChildNode(id, depth, descriptor, key);
|
3804
|
+
this.validationErrors.delete(key);
|
3805
|
+
return id;
|
3806
|
+
} else if (!descriptor.optional) {
|
3807
|
+
this.validationErrors.set(
|
3808
|
+
key,
|
3809
|
+
new JazzError(void 0, "unavailable", [
|
3810
|
+
{
|
3811
|
+
code: "validationError",
|
3812
|
+
message: `The ref on position ${key} requested on ${list.constructor.name} is missing`,
|
3813
|
+
params: {},
|
3814
|
+
path: [key]
|
3815
|
+
}
|
3816
|
+
])
|
3817
|
+
);
|
3818
|
+
}
|
3819
|
+
return void 0;
|
3820
|
+
}
|
3821
|
+
loadChildNode(id, query, descriptor, key) {
|
3822
|
+
if (this.childValues.has(id)) {
|
3823
|
+
return;
|
3824
|
+
}
|
3825
|
+
if (key && this.autoloadedKeys.has(key)) {
|
3826
|
+
this.autoloaded.add(id);
|
3827
|
+
}
|
3828
|
+
const skipInvalid = typeof query === "object" && query.$onError === null;
|
3829
|
+
if (skipInvalid) {
|
3830
|
+
if (key) {
|
3831
|
+
this.skipInvalidKeys.add(key);
|
3832
|
+
}
|
3833
|
+
this.skipInvalidKeys.add(id);
|
3834
|
+
}
|
3835
|
+
const resolve = typeof query === "object" && query !== null ? { ...query } : query;
|
3836
|
+
this.childValues.set(id, { type: "unloaded", id });
|
3837
|
+
const child = new _SubscriptionScope(
|
3838
|
+
this.node,
|
3839
|
+
resolve,
|
3840
|
+
id,
|
3841
|
+
descriptor,
|
3842
|
+
this.skipRetry,
|
3843
|
+
this.bestEffortResolution
|
3844
|
+
);
|
3845
|
+
this.childNodes.set(id, child);
|
3846
|
+
child.setListener((value) => this.handleChildUpdate(id, value, key));
|
3847
|
+
}
|
3848
|
+
destroy() {
|
3849
|
+
this.subscription.unsubscribe();
|
3850
|
+
this.subscribers.clear();
|
3851
|
+
this.childNodes.forEach((child) => child.destroy());
|
3852
|
+
}
|
3853
|
+
};
|
3854
|
+
|
3855
|
+
// src/tools/subscribe/index.ts
|
3856
|
+
function getSubscriptionScope(value) {
|
3857
|
+
const subscriptionScope = value.$jazz._subscriptionScope;
|
3858
|
+
if (subscriptionScope) {
|
3859
|
+
return subscriptionScope;
|
3860
|
+
}
|
3861
|
+
const node = value.$jazz.raw.core.node;
|
3862
|
+
const resolve = true;
|
3863
|
+
const id = value.$jazz.id;
|
3864
|
+
const newSubscriptionScope = new SubscriptionScope(node, resolve, id, {
|
3865
|
+
ref: value.constructor,
|
3866
|
+
optional: false
|
3867
|
+
});
|
3868
|
+
Object.defineProperty(value.$jazz, "_subscriptionScope", {
|
3869
|
+
value: subscriptionScope,
|
3870
|
+
writable: false,
|
3871
|
+
enumerable: false,
|
3872
|
+
configurable: false
|
3873
|
+
});
|
3874
|
+
return newSubscriptionScope;
|
3875
|
+
}
|
3876
|
+
function accessChildByKey(parent, childId, key) {
|
3877
|
+
const subscriptionScope = getSubscriptionScope(parent);
|
3878
|
+
if (!subscriptionScope.childValues.has(childId)) {
|
3879
|
+
subscriptionScope.subscribeToKey(key);
|
3880
|
+
}
|
3881
|
+
const value = subscriptionScope.childValues.get(childId);
|
3882
|
+
if (value?.type === "loaded") {
|
3883
|
+
return value.value;
|
3884
|
+
} else {
|
3885
|
+
return null;
|
3886
|
+
}
|
3887
|
+
}
|
3888
|
+
function accessChildById(parent, childId, schema) {
|
3889
|
+
const subscriptionScope = getSubscriptionScope(parent);
|
3890
|
+
subscriptionScope.subscribeToId(childId, schema);
|
3891
|
+
const value = subscriptionScope.childValues.get(childId);
|
3892
|
+
if (value?.type === "loaded") {
|
3893
|
+
return value.value;
|
3894
|
+
} else {
|
3895
|
+
return null;
|
3896
|
+
}
|
3897
|
+
}
|
3898
|
+
|
3899
|
+
// src/tools/implementation/createContext.ts
|
3900
|
+
import {
|
3901
|
+
LocalNode as LocalNode3
|
3902
|
+
} from "cojson";
|
3903
|
+
|
3904
|
+
// src/tools/implementation/schemaUtils.ts
|
3905
|
+
function removeGetters(obj) {
|
3906
|
+
const result = {};
|
3907
|
+
for (const key of Object.keys(obj)) {
|
3908
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
|
3909
|
+
if (!descriptor?.get) {
|
3910
|
+
result[key] = obj[key];
|
3911
|
+
}
|
3912
|
+
}
|
3913
|
+
return result;
|
3914
|
+
}
|
3915
|
+
|
3916
|
+
// src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts
|
3917
|
+
var CoDiscriminatedUnionSchema = class {
|
3918
|
+
constructor(coreSchema, coValueClass) {
|
3919
|
+
this.coValueClass = coValueClass;
|
3920
|
+
this.collaborative = true;
|
3921
|
+
this.builtin = "CoDiscriminatedUnion";
|
3922
|
+
this.getDefinition = coreSchema.getDefinition;
|
3923
|
+
}
|
3924
|
+
load(id, options) {
|
3925
|
+
return this.coValueClass.load(id, options);
|
3926
|
+
}
|
3927
|
+
subscribe(id, options, listener) {
|
3928
|
+
return this.coValueClass.subscribe(id, options, listener);
|
3929
|
+
}
|
3930
|
+
getCoValueClass() {
|
3931
|
+
return this.coValueClass;
|
3932
|
+
}
|
3933
|
+
optional() {
|
3934
|
+
return coOptionalDefiner(this);
|
3935
|
+
}
|
3936
|
+
};
|
3937
|
+
|
3938
|
+
// src/tools/implementation/zodSchema/schemaTypes/CoOptionalSchema.ts
|
3939
|
+
var CoOptionalSchema = class {
|
3940
|
+
constructor(innerType) {
|
3941
|
+
this.innerType = innerType;
|
3942
|
+
this.collaborative = true;
|
3943
|
+
this.builtin = "CoOptional";
|
3944
|
+
this.getDefinition = () => ({
|
3945
|
+
innerType: this.innerType
|
3946
|
+
});
|
3947
|
+
}
|
3948
|
+
getCoValueClass() {
|
3949
|
+
return this.innerType.getCoValueClass();
|
3950
|
+
}
|
3951
|
+
};
|
3952
|
+
|
3953
|
+
// src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts
|
3954
|
+
var RichTextSchema = class {
|
3955
|
+
constructor(coValueClass) {
|
3956
|
+
this.coValueClass = coValueClass;
|
3957
|
+
this.collaborative = true;
|
3958
|
+
this.builtin = "CoRichText";
|
3959
|
+
}
|
3960
|
+
create(text, options) {
|
3961
|
+
return this.coValueClass.create(text, options);
|
3962
|
+
}
|
3963
|
+
load(id, options) {
|
3964
|
+
return this.coValueClass.load(id, options);
|
3965
|
+
}
|
3966
|
+
subscribe(...args) {
|
3967
|
+
return this.coValueClass.subscribe(...args);
|
3968
|
+
}
|
3969
|
+
getCoValueClass() {
|
3970
|
+
return this.coValueClass;
|
3971
|
+
}
|
3972
|
+
optional() {
|
3973
|
+
return coOptionalDefiner(this);
|
3974
|
+
}
|
3975
|
+
};
|
3976
|
+
|
3977
|
+
// src/tools/implementation/zodSchema/zodReExport.ts
|
3978
|
+
import {
|
3979
|
+
object as zodObject,
|
3980
|
+
strictObject as zodStrictObject
|
3981
|
+
} from "zod/v4";
|
3982
|
+
import {
|
3983
|
+
string,
|
3984
|
+
number,
|
3985
|
+
boolean,
|
3986
|
+
templateLiteral,
|
3987
|
+
json,
|
3988
|
+
date,
|
3989
|
+
emoji,
|
3990
|
+
base64,
|
3991
|
+
base64url,
|
3992
|
+
nanoid,
|
3993
|
+
cuid,
|
3994
|
+
cuid2,
|
3995
|
+
ulid,
|
3996
|
+
ipv4,
|
3997
|
+
ipv6,
|
3998
|
+
email,
|
3999
|
+
url,
|
4000
|
+
uuid,
|
4001
|
+
literal,
|
4002
|
+
enum as enum2,
|
4003
|
+
cidrv4,
|
4004
|
+
cidrv6,
|
4005
|
+
iso,
|
4006
|
+
int32,
|
4007
|
+
union,
|
4008
|
+
discriminatedUnion,
|
4009
|
+
int,
|
4010
|
+
optional as optional2,
|
4011
|
+
array,
|
4012
|
+
tuple,
|
4013
|
+
z
|
4014
|
+
} from "zod/v4";
|
4015
|
+
|
4016
|
+
// src/tools/implementation/zodSchema/zodCo.ts
|
4017
|
+
var isZodV4Schema = (schema) => {
|
4018
|
+
return typeof schema === "object" && schema !== null && "_zod" in schema;
|
4019
|
+
};
|
4020
|
+
var isValidShape = (shape) => {
|
4021
|
+
return Object.values(removeGetters(shape)).every(
|
4022
|
+
(schema) => isZodV4Schema(schema) || isAnyCoValueSchema(schema) || isCoValueClass(schema)
|
4023
|
+
);
|
4024
|
+
};
|
4025
|
+
var validateCoMapShape = (shape) => {
|
4026
|
+
if (isAnyCoValueSchema(shape)) {
|
4027
|
+
throw new Error(
|
4028
|
+
"co.map() expects an object as its argument, not a CoValue schema"
|
4029
|
+
);
|
4030
|
+
} else if (!isValidShape(shape)) {
|
4031
|
+
throw new Error(
|
4032
|
+
"co.map() supports only Zod v4 schemas and CoValue schemas"
|
4033
|
+
);
|
4034
|
+
}
|
4035
|
+
};
|
4036
|
+
var coMapDefiner = (shape) => {
|
4037
|
+
validateCoMapShape(shape);
|
4038
|
+
const coreSchema = createCoreCoMapSchema(shape);
|
4039
|
+
return hydrateCoreCoValueSchema(coreSchema);
|
4040
|
+
};
|
4041
|
+
var coFileStreamDefiner = () => {
|
4042
|
+
const coreSchema = createCoreFileStreamSchema();
|
4043
|
+
return hydrateCoreCoValueSchema(coreSchema);
|
4044
|
+
};
|
4045
|
+
var coOptionalDefiner = (schema) => {
|
4046
|
+
return new CoOptionalSchema(schema);
|
4047
|
+
};
|
4048
|
+
|
4049
|
+
// src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts
|
4050
|
+
function createCoreCoMapSchema(shape, catchAll) {
|
4051
|
+
return {
|
4052
|
+
collaborative: true,
|
4053
|
+
builtin: "CoMap",
|
4054
|
+
shape,
|
4055
|
+
catchAll,
|
4056
|
+
getDefinition: () => ({
|
4057
|
+
get shape() {
|
4058
|
+
return shape;
|
4059
|
+
},
|
4060
|
+
get catchall() {
|
4061
|
+
return catchAll;
|
4062
|
+
},
|
4063
|
+
get discriminatorMap() {
|
4064
|
+
const propValues = {};
|
4065
|
+
for (const key in removeGetters(shape)) {
|
4066
|
+
if (isAnyCoValueSchema(shape[key])) {
|
4067
|
+
continue;
|
4068
|
+
}
|
4069
|
+
const field = shape[key]._zod;
|
4070
|
+
if (field.values) {
|
4071
|
+
propValues[key] ??= /* @__PURE__ */ new Set();
|
4072
|
+
for (const v of field.values) propValues[key].add(v);
|
4073
|
+
}
|
4074
|
+
}
|
4075
|
+
return propValues;
|
4076
|
+
}
|
4077
|
+
})
|
4078
|
+
};
|
4079
|
+
}
|
4080
|
+
function enrichCoMapSchema(schema, coValueClass) {
|
4081
|
+
const coValueSchema = Object.assign(schema, {
|
4082
|
+
create: (...args) => {
|
4083
|
+
return coValueClass.create(...args);
|
4084
|
+
},
|
4085
|
+
load: (...args) => {
|
4086
|
+
return coValueClass.load(...args);
|
4087
|
+
},
|
4088
|
+
subscribe: (...args) => {
|
4089
|
+
return coValueClass.subscribe(...args);
|
4090
|
+
},
|
4091
|
+
findUnique: (...args) => {
|
4092
|
+
return coValueClass.findUnique(...args);
|
4093
|
+
},
|
4094
|
+
upsertUnique: (...args) => {
|
4095
|
+
return coValueClass.upsertUnique(...args);
|
4096
|
+
},
|
4097
|
+
loadUnique: (...args) => {
|
4098
|
+
return coValueClass.loadUnique(...args);
|
4099
|
+
},
|
4100
|
+
catchall: (catchAll) => {
|
4101
|
+
const schemaWithCatchAll = createCoreCoMapSchema(
|
4102
|
+
coValueSchema.getDefinition().shape,
|
4103
|
+
catchAll
|
4104
|
+
);
|
4105
|
+
return hydrateCoreCoValueSchema(schemaWithCatchAll);
|
4106
|
+
},
|
4107
|
+
withMigration: (migration) => {
|
4108
|
+
coValueClass.prototype.migrate = migration;
|
4109
|
+
return coValueSchema;
|
4110
|
+
},
|
4111
|
+
getCoValueClass: () => {
|
4112
|
+
return coValueClass;
|
4113
|
+
},
|
4114
|
+
optional: () => {
|
4115
|
+
return coOptionalDefiner(coValueSchema);
|
4116
|
+
},
|
4117
|
+
pick: (keys) => {
|
4118
|
+
const keysSet = new Set(Object.keys(keys));
|
4119
|
+
const pickedShape = {};
|
4120
|
+
for (const [key, value] of Object.entries(coValueSchema.shape)) {
|
4121
|
+
if (keysSet.has(key)) {
|
4122
|
+
pickedShape[key] = value;
|
4123
|
+
}
|
4124
|
+
}
|
4125
|
+
return coMapDefiner(pickedShape);
|
4126
|
+
},
|
4127
|
+
partial: () => {
|
4128
|
+
const partialShape = {};
|
4129
|
+
for (const [key, value] of Object.entries(coValueSchema.shape)) {
|
4130
|
+
if (isAnyCoValueSchema(value)) {
|
4131
|
+
partialShape[key] = coOptionalDefiner(value);
|
4132
|
+
} else {
|
4133
|
+
partialShape[key] = z.optional(coValueSchema.shape[key]);
|
4134
|
+
}
|
4135
|
+
}
|
4136
|
+
const partialCoMapSchema = coMapDefiner(partialShape);
|
4137
|
+
if (coValueSchema.catchAll) {
|
4138
|
+
return partialCoMapSchema.catchall(
|
4139
|
+
coValueSchema.catchAll
|
4140
|
+
);
|
4141
|
+
}
|
4142
|
+
return partialCoMapSchema;
|
4143
|
+
}
|
4144
|
+
});
|
4145
|
+
return coValueSchema;
|
4146
|
+
}
|
4147
|
+
|
4148
|
+
// src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts
|
4149
|
+
var CoListSchema = class {
|
4150
|
+
constructor(element, coValueClass) {
|
4151
|
+
this.element = element;
|
4152
|
+
this.coValueClass = coValueClass;
|
4153
|
+
this.collaborative = true;
|
4154
|
+
this.builtin = "CoList";
|
4155
|
+
}
|
4156
|
+
create(items, options) {
|
4157
|
+
return this.coValueClass.create(items, options);
|
4158
|
+
}
|
4159
|
+
load(id, options) {
|
4160
|
+
return this.coValueClass.load(id, options);
|
4161
|
+
}
|
4162
|
+
subscribe(id, options, listener) {
|
4163
|
+
return this.coValueClass.subscribe(id, options, listener);
|
4164
|
+
}
|
4165
|
+
getCoValueClass() {
|
4166
|
+
return this.coValueClass;
|
4167
|
+
}
|
4168
|
+
/** @deprecated Use `CoList.upsertUnique` and `CoList.loadUnique` instead. */
|
4169
|
+
findUnique(unique, ownerID, as) {
|
4170
|
+
return this.coValueClass.findUnique(unique, ownerID, as);
|
4171
|
+
}
|
4172
|
+
upsertUnique(options) {
|
4173
|
+
return this.coValueClass.upsertUnique(options);
|
4174
|
+
}
|
4175
|
+
loadUnique(unique, ownerID, options) {
|
4176
|
+
return this.coValueClass.loadUnique(unique, ownerID, options);
|
4177
|
+
}
|
4178
|
+
optional() {
|
4179
|
+
return coOptionalDefiner(this);
|
4180
|
+
}
|
4181
|
+
};
|
4182
|
+
|
4183
|
+
// src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts
|
4184
|
+
var CoFeedSchema = class {
|
4185
|
+
constructor(element, coValueClass) {
|
4186
|
+
this.element = element;
|
4187
|
+
this.coValueClass = coValueClass;
|
4188
|
+
this.collaborative = true;
|
4189
|
+
this.builtin = "CoFeed";
|
4190
|
+
}
|
4191
|
+
create(init, options) {
|
4192
|
+
return this.coValueClass.create(init, options);
|
4193
|
+
}
|
4194
|
+
load(id, options) {
|
4195
|
+
return this.coValueClass.load(id, options);
|
4196
|
+
}
|
4197
|
+
subscribe(...args) {
|
4198
|
+
return this.coValueClass.subscribe(...args);
|
4199
|
+
}
|
4200
|
+
getCoValueClass() {
|
4201
|
+
return this.coValueClass;
|
4202
|
+
}
|
4203
|
+
optional() {
|
4204
|
+
return coOptionalDefiner(this);
|
4205
|
+
}
|
4206
|
+
};
|
4207
|
+
|
4208
|
+
// src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts
|
4209
|
+
var PlainTextSchema = class {
|
4210
|
+
constructor(coValueClass) {
|
4211
|
+
this.coValueClass = coValueClass;
|
4212
|
+
this.collaborative = true;
|
4213
|
+
this.builtin = "CoPlainText";
|
4214
|
+
}
|
4215
|
+
create(text, options) {
|
4216
|
+
return this.coValueClass.create(text, options);
|
4217
|
+
}
|
4218
|
+
load(id, options) {
|
4219
|
+
return this.coValueClass.load(id, options);
|
4220
|
+
}
|
4221
|
+
subscribe(...args) {
|
4222
|
+
return this.coValueClass.subscribe(...args);
|
4223
|
+
}
|
4224
|
+
fromRaw(raw) {
|
4225
|
+
return this.coValueClass.fromRaw(raw);
|
4226
|
+
}
|
4227
|
+
getCoValueClass() {
|
4228
|
+
return this.coValueClass;
|
4229
|
+
}
|
4230
|
+
optional() {
|
4231
|
+
return coOptionalDefiner(this);
|
4232
|
+
}
|
4233
|
+
};
|
4234
|
+
|
4235
|
+
// src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts
|
4236
|
+
function createCoreFileStreamSchema() {
|
4237
|
+
return {
|
4238
|
+
collaborative: true,
|
4239
|
+
builtin: "FileStream"
|
4240
|
+
};
|
4241
|
+
}
|
4242
|
+
var FileStreamSchema = class {
|
4243
|
+
constructor(coValueClass) {
|
4244
|
+
this.coValueClass = coValueClass;
|
4245
|
+
this.collaborative = true;
|
4246
|
+
this.builtin = "FileStream";
|
4247
|
+
}
|
4248
|
+
create(options) {
|
4249
|
+
return this.coValueClass.create(options);
|
4250
|
+
}
|
4251
|
+
createFromBlob(blob, options) {
|
4252
|
+
return this.coValueClass.createFromBlob(blob, options);
|
4253
|
+
}
|
4254
|
+
createFromArrayBuffer(...args) {
|
4255
|
+
return this.coValueClass.createFromArrayBuffer(...args);
|
4256
|
+
}
|
4257
|
+
loadAsBlob(id, options) {
|
4258
|
+
return this.coValueClass.loadAsBlob(id, options);
|
4259
|
+
}
|
4260
|
+
load(id, options) {
|
4261
|
+
return this.coValueClass.load(id, options);
|
4262
|
+
}
|
4263
|
+
subscribe(...args) {
|
4264
|
+
return this.coValueClass.subscribe(...args);
|
4265
|
+
}
|
4266
|
+
getCoValueClass() {
|
4267
|
+
return this.coValueClass;
|
4268
|
+
}
|
4269
|
+
optional() {
|
4270
|
+
return coOptionalDefiner(this);
|
4271
|
+
}
|
4272
|
+
};
|
4273
|
+
|
4274
|
+
// src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts
|
4275
|
+
function enrichAccountSchema(schema, coValueClass) {
|
4276
|
+
const enrichedSchema = Object.assign(schema, {
|
4277
|
+
create: (...args) => {
|
4278
|
+
return coValueClass.create(...args);
|
4279
|
+
},
|
4280
|
+
createAs: (...args) => {
|
4281
|
+
return coValueClass.createAs(...args);
|
4282
|
+
},
|
4283
|
+
getMe: (...args) => {
|
4284
|
+
return coValueClass.getMe(...args);
|
4285
|
+
},
|
4286
|
+
load: (...args) => {
|
4287
|
+
return coValueClass.load(...args);
|
4288
|
+
},
|
4289
|
+
subscribe: (...args) => {
|
4290
|
+
return coValueClass.subscribe(...args);
|
4291
|
+
},
|
4292
|
+
fromRaw: (...args) => {
|
4293
|
+
return coValueClass.fromRaw(...args);
|
4294
|
+
},
|
4295
|
+
withMigration: (migration) => {
|
4296
|
+
coValueClass.prototype.migrate = async function(creationProps) {
|
4297
|
+
await migration(this, creationProps);
|
4298
|
+
};
|
4299
|
+
return enrichedSchema;
|
4300
|
+
},
|
4301
|
+
getCoValueClass: () => {
|
4302
|
+
return coValueClass;
|
4303
|
+
}
|
4304
|
+
});
|
4305
|
+
return enrichedSchema;
|
4306
|
+
}
|
4307
|
+
|
4308
|
+
// src/tools/implementation/zodSchema/unionUtils.ts
|
4309
|
+
function schemaUnionDiscriminatorFor(schema) {
|
4310
|
+
if (isUnionOfCoMapsDeeply(schema)) {
|
4311
|
+
const definition = schema.getDefinition();
|
4312
|
+
const { discriminatorMap, discriminator, options } = definition;
|
4313
|
+
const field = discriminatorMap[discriminator];
|
4314
|
+
if (!field) {
|
4315
|
+
throw new Error(
|
4316
|
+
"co.discriminatedUnion() of collaborative types with non-existent discriminator key is not supported"
|
4317
|
+
);
|
4318
|
+
}
|
4319
|
+
for (const value of field) {
|
4320
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
4321
|
+
throw new Error(
|
4322
|
+
"co.discriminatedUnion() of collaborative types with non-string or non-number discriminator value is not supported"
|
4323
|
+
);
|
4324
|
+
}
|
4325
|
+
}
|
4326
|
+
const availableOptions = [];
|
4327
|
+
for (const option of options) {
|
4328
|
+
if (option.builtin === "CoMap") {
|
4329
|
+
availableOptions.push(option);
|
4330
|
+
} else if (option.builtin === "CoDiscriminatedUnion") {
|
4331
|
+
for (const subOption of option.getDefinition().options) {
|
4332
|
+
if (!options.includes(subOption)) {
|
4333
|
+
options.push(subOption);
|
4334
|
+
}
|
4335
|
+
}
|
4336
|
+
} else {
|
4337
|
+
throw new Error(
|
4338
|
+
"Unsupported zod type in co.discriminatedUnion() of collaborative types"
|
4339
|
+
);
|
4340
|
+
}
|
4341
|
+
}
|
4342
|
+
const determineSchema = (discriminable) => {
|
4343
|
+
for (const option of availableOptions) {
|
4344
|
+
let match = true;
|
4345
|
+
for (const key of Object.keys(discriminatorMap)) {
|
4346
|
+
const discriminatorDef = option.getDefinition().shape[key];
|
4347
|
+
const discriminatorValue = discriminable.get(key);
|
4348
|
+
if (discriminatorValue && typeof discriminatorValue === "object") {
|
4349
|
+
throw new Error("Discriminator must be a primitive value");
|
4350
|
+
}
|
4351
|
+
if (!discriminatorDef) {
|
4352
|
+
if (key === discriminator) {
|
4353
|
+
match = false;
|
4354
|
+
break;
|
4355
|
+
} else {
|
4356
|
+
continue;
|
4357
|
+
}
|
4358
|
+
}
|
4359
|
+
if (discriminatorDef._zod?.def.type !== "literal") {
|
4360
|
+
break;
|
4361
|
+
}
|
4362
|
+
const literalDef = discriminatorDef._zod.def;
|
4363
|
+
if (!Array.from(literalDef.values).includes(discriminatorValue)) {
|
4364
|
+
match = false;
|
4365
|
+
break;
|
4366
|
+
}
|
4367
|
+
}
|
4368
|
+
if (match) {
|
4369
|
+
const coValueSchema = hydrateCoreCoValueSchema(option);
|
4370
|
+
return coValueSchema.getCoValueClass();
|
4371
|
+
}
|
4372
|
+
}
|
4373
|
+
throw new Error(
|
4374
|
+
"co.discriminatedUnion() of collaborative types with no matching discriminator value found"
|
4375
|
+
);
|
4376
|
+
};
|
4377
|
+
return determineSchema;
|
4378
|
+
} else {
|
4379
|
+
throw new Error(
|
4380
|
+
"co.discriminatedUnion() of non-collaborative types is not supported"
|
4381
|
+
);
|
4382
|
+
}
|
4383
|
+
}
|
4384
|
+
function isUnionOfCoMapsDeeply(schema) {
|
4385
|
+
return schema.getDefinition().options.every(isCoMapOrUnionOfCoMapsDeeply);
|
4386
|
+
}
|
4387
|
+
function isCoMapOrUnionOfCoMapsDeeply(schema) {
|
4388
|
+
if (schema.builtin === "CoMap") {
|
4389
|
+
return true;
|
4390
|
+
} else if (schema.builtin === "CoDiscriminatedUnion") {
|
4391
|
+
return schema.getDefinition().options.every(isCoMapOrUnionOfCoMapsDeeply);
|
4392
|
+
} else {
|
4393
|
+
return false;
|
4394
|
+
}
|
4395
|
+
}
|
4396
|
+
function isUnionOfPrimitivesDeeply(schema) {
|
4397
|
+
if (schema instanceof z.core.$ZodUnion) {
|
4398
|
+
return schema._zod.def.options.every(isUnionOfPrimitivesDeeply);
|
4399
|
+
} else {
|
4400
|
+
return !isAnyCoValueSchema(schema);
|
4401
|
+
}
|
4402
|
+
}
|
4403
|
+
|
4404
|
+
// src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts
|
4405
|
+
function schemaFieldToCoFieldDef(schema) {
|
4406
|
+
if (isCoValueClass(schema)) {
|
4407
|
+
return coField.ref(schema);
|
4408
|
+
} else if (isCoValueSchema(schema)) {
|
4409
|
+
if (schema.builtin === "CoOptional") {
|
4410
|
+
return coField.ref(schema.getCoValueClass(), {
|
4411
|
+
optional: true
|
4412
|
+
});
|
4413
|
+
}
|
4414
|
+
return coField.ref(schema.getCoValueClass());
|
4415
|
+
} else {
|
4416
|
+
if ("_zod" in schema) {
|
4417
|
+
const zodSchemaDef = schema._zod.def;
|
4418
|
+
if (zodSchemaDef.type === "optional" || zodSchemaDef.type === "nullable") {
|
4419
|
+
const inner = zodSchemaDef.innerType;
|
4420
|
+
const coFieldDef = schemaFieldToCoFieldDef(inner);
|
4421
|
+
if (zodSchemaDef.type === "nullable" && coFieldDef === coField.optional.Date) {
|
4422
|
+
throw new Error("Nullable z.date() is not supported");
|
4423
|
+
}
|
4424
|
+
return coFieldDef;
|
4425
|
+
} else if (zodSchemaDef.type === "string") {
|
4426
|
+
return coField.string;
|
4427
|
+
} else if (zodSchemaDef.type === "number") {
|
4428
|
+
return coField.number;
|
4429
|
+
} else if (zodSchemaDef.type === "boolean") {
|
4430
|
+
return coField.boolean;
|
4431
|
+
} else if (zodSchemaDef.type === "null") {
|
4432
|
+
return coField.null;
|
4433
|
+
} else if (zodSchemaDef.type === "enum") {
|
4434
|
+
return coField.string;
|
4435
|
+
} else if (zodSchemaDef.type === "readonly") {
|
4436
|
+
return schemaFieldToCoFieldDef(
|
4437
|
+
schema.def.innerType
|
4438
|
+
);
|
4439
|
+
} else if (zodSchemaDef.type === "date") {
|
4440
|
+
return coField.optional.Date;
|
4441
|
+
} else if (zodSchemaDef.type === "template_literal") {
|
4442
|
+
return coField.string;
|
4443
|
+
} else if (zodSchemaDef.type === "lazy") {
|
4444
|
+
return schemaFieldToCoFieldDef(
|
4445
|
+
schema.unwrap()
|
4446
|
+
);
|
4447
|
+
} else if (zodSchemaDef.type === "default" || zodSchemaDef.type === "catch") {
|
4448
|
+
console.warn(
|
4449
|
+
"z.default()/z.catch() are not supported in collaborative schemas. They will be ignored."
|
4450
|
+
);
|
4451
|
+
return schemaFieldToCoFieldDef(
|
4452
|
+
schema.def.innerType
|
4453
|
+
);
|
4454
|
+
} else if (zodSchemaDef.type === "literal") {
|
4455
|
+
if (zodSchemaDef.values.some((literal2) => typeof literal2 === "undefined")) {
|
4456
|
+
throw new Error("z.literal() with undefined is not supported");
|
4457
|
+
}
|
4458
|
+
if (zodSchemaDef.values.some((literal2) => literal2 === null)) {
|
4459
|
+
throw new Error("z.literal() with null is not supported");
|
4460
|
+
}
|
4461
|
+
if (zodSchemaDef.values.some((literal2) => typeof literal2 === "bigint")) {
|
4462
|
+
throw new Error("z.literal() with bigint is not supported");
|
4463
|
+
}
|
4464
|
+
return coField.literal(
|
4465
|
+
...zodSchemaDef.values
|
4466
|
+
);
|
4467
|
+
} else if (zodSchemaDef.type === "object" || zodSchemaDef.type === "array" || zodSchemaDef.type === "tuple") {
|
4468
|
+
return coField.json();
|
4469
|
+
} else if (zodSchemaDef.type === "union") {
|
4470
|
+
if (isUnionOfPrimitivesDeeply(schema)) {
|
4471
|
+
return coField.json();
|
4472
|
+
} else {
|
4473
|
+
throw new Error(
|
4474
|
+
"z.union()/z.discriminatedUnion() of collaborative types is not supported. Use co.discriminatedUnion() instead."
|
4475
|
+
);
|
4476
|
+
}
|
4477
|
+
} else {
|
4478
|
+
throw new Error(
|
4479
|
+
`Unsupported zod type: ${schema._zod?.def?.type || JSON.stringify(schema)}`
|
4480
|
+
);
|
4481
|
+
}
|
4482
|
+
} else {
|
4483
|
+
throw new Error(`Unsupported zod type: ${schema}`);
|
4484
|
+
}
|
4485
|
+
}
|
4486
|
+
}
|
4487
|
+
|
4488
|
+
// src/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.ts
|
4489
|
+
function isAnyCoValueSchema(schema) {
|
4490
|
+
return typeof schema === "object" && schema !== null && "collaborative" in schema && schema.collaborative === true;
|
4491
|
+
}
|
4492
|
+
function isCoValueSchema(schema) {
|
4493
|
+
return isAnyCoValueSchema(schema) && "getCoValueClass" in schema;
|
4494
|
+
}
|
4495
|
+
function hydrateCoreCoValueSchema(schema) {
|
4496
|
+
if (isCoValueSchema(schema)) {
|
4497
|
+
return schema;
|
4498
|
+
}
|
4499
|
+
if (schema.builtin === "CoOptional") {
|
4500
|
+
throw new Error(
|
4501
|
+
`co.optional() of collaborative types is not supported as top-level schema: ${JSON.stringify(schema)}`
|
4502
|
+
);
|
4503
|
+
} else if (schema.builtin === "CoMap" || schema.builtin === "Account") {
|
4504
|
+
const def = schema.getDefinition();
|
4505
|
+
const ClassToExtend = schema.builtin === "Account" ? Account : CoMap;
|
4506
|
+
const coValueClass = class ZCoMap extends ClassToExtend {
|
4507
|
+
constructor(options) {
|
4508
|
+
super(options);
|
4509
|
+
for (const [fieldName, fieldType] of Object.entries(def.shape)) {
|
4510
|
+
this[fieldName] = schemaFieldToCoFieldDef(
|
4511
|
+
fieldType
|
4512
|
+
);
|
4513
|
+
}
|
4514
|
+
if (def.catchall) {
|
4515
|
+
this[coField.items] = schemaFieldToCoFieldDef(
|
4516
|
+
def.catchall
|
4517
|
+
);
|
4518
|
+
}
|
4519
|
+
}
|
4520
|
+
};
|
4521
|
+
const coValueSchema = ClassToExtend === Account ? enrichAccountSchema(schema, coValueClass) : enrichCoMapSchema(schema, coValueClass);
|
4522
|
+
return coValueSchema;
|
4523
|
+
} else if (schema.builtin === "CoList") {
|
4524
|
+
const element = schema.element;
|
4525
|
+
const coValueClass = class ZCoList extends CoList {
|
4526
|
+
constructor(options) {
|
4527
|
+
super(options);
|
4528
|
+
this[coField.items] = schemaFieldToCoFieldDef(
|
4529
|
+
element
|
4530
|
+
);
|
4531
|
+
}
|
4532
|
+
};
|
4533
|
+
const coValueSchema = new CoListSchema(element, coValueClass);
|
4534
|
+
return coValueSchema;
|
4535
|
+
} else if (schema.builtin === "CoFeed") {
|
4536
|
+
const coValueClass = CoFeed.Of(
|
4537
|
+
schemaFieldToCoFieldDef(schema.element)
|
4538
|
+
);
|
4539
|
+
const coValueSchema = new CoFeedSchema(schema.element, coValueClass);
|
4540
|
+
return coValueSchema;
|
4541
|
+
} else if (schema.builtin === "FileStream") {
|
4542
|
+
const coValueClass = FileStream;
|
4543
|
+
return new FileStreamSchema(coValueClass);
|
4544
|
+
} else if (schema.builtin === "CoPlainText") {
|
4545
|
+
const coValueClass = CoPlainText;
|
4546
|
+
return new PlainTextSchema(coValueClass);
|
4547
|
+
} else if (schema.builtin === "CoRichText") {
|
4548
|
+
const coValueClass = CoRichText;
|
4549
|
+
return new RichTextSchema(coValueClass);
|
4550
|
+
} else if (schema.builtin === "CoDiscriminatedUnion") {
|
4551
|
+
const coValueClass = SchemaUnion.Of(schemaUnionDiscriminatorFor(schema));
|
4552
|
+
const coValueSchema = new CoDiscriminatedUnionSchema(schema, coValueClass);
|
4553
|
+
return coValueSchema;
|
4554
|
+
} else {
|
4555
|
+
const notReachable = schema;
|
4556
|
+
throw new Error(
|
4557
|
+
`Unsupported zod CoValue type for top-level schema: ${JSON.stringify(notReachable, void 0, 2)}`
|
4558
|
+
);
|
4559
|
+
}
|
4560
|
+
}
|
4561
|
+
function coValueClassFromCoValueClassOrSchema(schema) {
|
4562
|
+
if (isCoValueClass(schema)) {
|
4563
|
+
return schema;
|
4564
|
+
} else if (isCoValueSchema(schema)) {
|
4565
|
+
return schema.getCoValueClass();
|
4566
|
+
}
|
4567
|
+
throw new Error(`Unsupported schema: ${JSON.stringify(schema)}`);
|
4568
|
+
}
|
4569
|
+
|
4570
|
+
// src/tools/coValues/extensions/imageDef.ts
|
4571
|
+
var ImageDefinitionBase = coMapDefiner({
|
4572
|
+
original: coFileStreamDefiner(),
|
4573
|
+
originalSize: z.tuple([z.number(), z.number()]),
|
4574
|
+
placeholderDataURL: z.string().optional(),
|
4575
|
+
progressive: z.boolean()
|
4576
|
+
}).catchall(coFileStreamDefiner());
|
4577
|
+
|
4578
|
+
// src/tools/implementation/ContextManager.ts
|
4579
|
+
import { cojsonInternals as cojsonInternals5 } from "cojson";
|
4580
|
+
import { PureJSCrypto } from "cojson/dist/crypto/PureJSCrypto";
|
4581
|
+
|
4582
|
+
// src/tools/implementation/devtoolsFormatters.ts
|
4583
|
+
globalThis.devtoolsFormatters = [
|
4584
|
+
{
|
4585
|
+
header: (object) => {
|
4586
|
+
if (object[TypeSym] === "CoMap") {
|
4587
|
+
return ["div", {}, ["span", {}, object.constructor.name]];
|
4588
|
+
} else if (object[TypeSym] === "CoList") {
|
4589
|
+
return [
|
4590
|
+
"div",
|
4591
|
+
{},
|
4592
|
+
["span", {}, object.constructor.name + "(" + object.length + ") "]
|
4593
|
+
];
|
4594
|
+
} else if (object[TypeSym] === "Account") {
|
4595
|
+
return [
|
4596
|
+
"div",
|
4597
|
+
{},
|
4598
|
+
[
|
4599
|
+
"span",
|
4600
|
+
{},
|
4601
|
+
object.constructor.name + "(" + object.$jazz.refs.profile.value?.name + (object.isMe ? " ME" : "") + ")"
|
4602
|
+
]
|
4603
|
+
];
|
4604
|
+
} else {
|
4605
|
+
return null;
|
4606
|
+
}
|
4607
|
+
},
|
4608
|
+
hasBody: function() {
|
4609
|
+
return true;
|
4610
|
+
},
|
4611
|
+
body: function(object) {
|
4612
|
+
if (object[TypeSym] === "CoMap" || object[TypeSym] === "Account") {
|
4613
|
+
return [
|
4614
|
+
"div",
|
4615
|
+
{ style: "margin-left: 15px" },
|
4616
|
+
["div", "id: ", ["object", { object: object.id }]],
|
4617
|
+
...Object.entries(object).map(([k, v]) => [
|
4618
|
+
"div",
|
4619
|
+
{ style: "white-space: nowrap;" },
|
4620
|
+
["span", { style: "font-weight: bold; opacity: 0.6" }, k, ": "],
|
4621
|
+
["object", { object: v }],
|
4622
|
+
...typeof object._schema[k] === "function" ? v === null ? [
|
4623
|
+
[
|
4624
|
+
"span",
|
4625
|
+
{ style: "opacity: 0.5" },
|
4626
|
+
` (pending ${object._schema[k].name} `,
|
4627
|
+
["object", { object: object.$jazz.refs[k] }],
|
4628
|
+
")"
|
4629
|
+
]
|
4630
|
+
] : [] : []
|
4631
|
+
])
|
4632
|
+
];
|
4633
|
+
} else if (object[TypeSym] === "CoList") {
|
4634
|
+
return [
|
4635
|
+
"div",
|
4636
|
+
{ style: "margin-left: 15px" },
|
4637
|
+
["div", "id: ", ["object", { object: object.id }]],
|
4638
|
+
...object.map((v, i) => [
|
4639
|
+
"div",
|
4640
|
+
{ style: "white-space: nowrap;" },
|
4641
|
+
["span", { style: "font-weight: bold; opacity: 0.6" }, i, ": "],
|
4642
|
+
["object", { object: v }],
|
4643
|
+
...typeof object._schema[ItemsSym] === "function" ? v === null ? [
|
4644
|
+
[
|
4645
|
+
"span",
|
4646
|
+
{ style: "opacity: 0.5" },
|
4647
|
+
` (pending ${object._schema[ItemsSym].name} `,
|
4648
|
+
["object", { object: object.$jazz.refs[i] }],
|
4649
|
+
")"
|
4650
|
+
]
|
4651
|
+
] : [] : []
|
4652
|
+
])
|
4653
|
+
];
|
4654
|
+
}
|
4655
|
+
}
|
4656
|
+
}
|
4657
|
+
];
|
4658
|
+
|
30
4659
|
// src/react-core/hooks.ts
|
31
4660
|
function useJazzContext() {
|
32
4661
|
const value = useContext(JazzContext);
|
@@ -68,7 +4697,7 @@ function useIsAuthenticated() {
|
|
68
4697
|
() => authSecretStorage.isAuthenticated
|
69
4698
|
);
|
70
4699
|
}
|
71
|
-
function useCoValueSubscription(
|
4700
|
+
function useCoValueSubscription(Schema4, id, options) {
|
72
4701
|
const contextManager = useJazzContextManager();
|
73
4702
|
const createSubscription = () => {
|
74
4703
|
if (!id) {
|
@@ -76,16 +4705,16 @@ function useCoValueSubscription(Schema, id, options) {
|
|
76
4705
|
subscription: null,
|
77
4706
|
contextManager,
|
78
4707
|
id,
|
79
|
-
Schema
|
4708
|
+
Schema: Schema4
|
80
4709
|
};
|
81
4710
|
}
|
82
4711
|
const node = contextManager.getCurrentValue().node;
|
83
|
-
const subscription2 = new
|
4712
|
+
const subscription2 = new SubscriptionScope2(
|
84
4713
|
node,
|
85
4714
|
options?.resolve ?? true,
|
86
4715
|
id,
|
87
4716
|
{
|
88
|
-
ref:
|
4717
|
+
ref: coValueClassFromCoValueClassOrSchema2(Schema4),
|
89
4718
|
optional: true
|
90
4719
|
}
|
91
4720
|
);
|
@@ -93,12 +4722,12 @@ function useCoValueSubscription(Schema, id, options) {
|
|
93
4722
|
subscription: subscription2,
|
94
4723
|
contextManager,
|
95
4724
|
id,
|
96
|
-
Schema
|
4725
|
+
Schema: Schema4
|
97
4726
|
};
|
98
4727
|
};
|
99
4728
|
const [subscription, setSubscription] = React.useState(createSubscription);
|
100
4729
|
React.useLayoutEffect(() => {
|
101
|
-
if (subscription.contextManager !== contextManager || subscription.id !== id || subscription.Schema !==
|
4730
|
+
if (subscription.contextManager !== contextManager || subscription.id !== id || subscription.Schema !== Schema4) {
|
102
4731
|
subscription.subscription?.destroy();
|
103
4732
|
setSubscription(createSubscription());
|
104
4733
|
}
|
@@ -106,11 +4735,11 @@ function useCoValueSubscription(Schema, id, options) {
|
|
106
4735
|
subscription.subscription?.destroy();
|
107
4736
|
setSubscription(createSubscription());
|
108
4737
|
});
|
109
|
-
}, [
|
4738
|
+
}, [Schema4, id, contextManager]);
|
110
4739
|
return subscription.subscription;
|
111
4740
|
}
|
112
|
-
function useCoState(
|
113
|
-
const subscription = useCoValueSubscription(
|
4741
|
+
function useCoState(Schema4, id, options) {
|
4742
|
+
const subscription = useCoValueSubscription(Schema4, id, options);
|
114
4743
|
const value = React.useSyncExternalStore(
|
115
4744
|
React.useCallback(
|
116
4745
|
(callback) => {
|
@@ -127,11 +4756,11 @@ function useCoState(Schema, id, options) {
|
|
127
4756
|
);
|
128
4757
|
return value;
|
129
4758
|
}
|
130
|
-
function useAccountSubscription(
|
4759
|
+
function useAccountSubscription(Schema4, options) {
|
131
4760
|
const contextManager = useJazzContextManager();
|
132
4761
|
const createSubscription = () => {
|
133
4762
|
const agent = getCurrentAccountFromContextManager(contextManager);
|
134
|
-
if (agent
|
4763
|
+
if (agent[TypeSym] === "Anonymous") {
|
135
4764
|
return {
|
136
4765
|
subscription: null,
|
137
4766
|
contextManager,
|
@@ -140,19 +4769,24 @@ function useAccountSubscription(Schema, options) {
|
|
140
4769
|
}
|
141
4770
|
const resolve = options?.resolve ?? true;
|
142
4771
|
const node = contextManager.getCurrentValue().node;
|
143
|
-
const subscription2 = new
|
144
|
-
|
145
|
-
|
146
|
-
|
4772
|
+
const subscription2 = new SubscriptionScope2(
|
4773
|
+
node,
|
4774
|
+
resolve,
|
4775
|
+
agent.$jazz.id,
|
4776
|
+
{
|
4777
|
+
ref: coValueClassFromCoValueClassOrSchema2(Schema4),
|
4778
|
+
optional: true
|
4779
|
+
}
|
4780
|
+
);
|
147
4781
|
return {
|
148
4782
|
subscription: subscription2,
|
149
4783
|
contextManager,
|
150
|
-
Schema
|
4784
|
+
Schema: Schema4
|
151
4785
|
};
|
152
4786
|
};
|
153
4787
|
const [subscription, setSubscription] = React.useState(createSubscription);
|
154
4788
|
React.useLayoutEffect(() => {
|
155
|
-
if (subscription.contextManager !== contextManager || subscription.Schema !==
|
4789
|
+
if (subscription.contextManager !== contextManager || subscription.Schema !== Schema4) {
|
156
4790
|
subscription.subscription?.destroy();
|
157
4791
|
setSubscription(createSubscription());
|
158
4792
|
}
|
@@ -160,12 +4794,12 @@ function useAccountSubscription(Schema, options) {
|
|
160
4794
|
subscription.subscription?.destroy();
|
161
4795
|
setSubscription(createSubscription());
|
162
4796
|
});
|
163
|
-
}, [
|
4797
|
+
}, [Schema4, contextManager]);
|
164
4798
|
return subscription.subscription;
|
165
4799
|
}
|
166
|
-
function useAccount(
|
4800
|
+
function useAccount(AccountSchema2 = Account13, options) {
|
167
4801
|
const contextManager = useJazzContextManager();
|
168
|
-
const subscription = useAccountSubscription(
|
4802
|
+
const subscription = useAccountSubscription(AccountSchema2, options);
|
169
4803
|
const agent = getCurrentAccountFromContextManager(contextManager);
|
170
4804
|
const value = React.useSyncExternalStore(
|
171
4805
|
React.useCallback(
|
@@ -297,4 +4931,5 @@ export {
|
|
297
4931
|
useJazzContextManager,
|
298
4932
|
usePassphraseAuth
|
299
4933
|
};
|
4934
|
+
/* istanbul ignore file -- @preserve */
|
300
4935
|
//# sourceMappingURL=index.js.map
|