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
@@ -8,10 +8,12 @@ import {
|
|
8
8
|
type RawCoMap,
|
9
9
|
cojsonInternals,
|
10
10
|
} from "cojson";
|
11
|
-
import
|
11
|
+
import {
|
12
12
|
AnonymousJazzAgent,
|
13
|
+
CoFieldInit,
|
13
14
|
CoValue,
|
14
15
|
CoValueClass,
|
16
|
+
getCoValueOwner,
|
15
17
|
Group,
|
16
18
|
ID,
|
17
19
|
PartialOnUndefined,
|
@@ -24,10 +26,12 @@ import type {
|
|
24
26
|
Simplify,
|
25
27
|
SubscribeListenerOptions,
|
26
28
|
SubscribeRestArgs,
|
29
|
+
TypeSym,
|
27
30
|
} from "../internal.js";
|
28
31
|
import {
|
29
32
|
Account,
|
30
33
|
CoValueBase,
|
34
|
+
CoValueJazzApi,
|
31
35
|
ItemsSym,
|
32
36
|
Ref,
|
33
37
|
RegisteredSchemas,
|
@@ -57,6 +61,14 @@ type CoMapEdit<V> = {
|
|
57
61
|
|
58
62
|
type LastAndAllCoMapEdits<V> = CoMapEdit<V> & { all: CoMapEdit<V>[] };
|
59
63
|
|
64
|
+
type CoMapEdits<M extends CoMap> = {
|
65
|
+
[Key in CoKeys<M>]?: LastAndAllCoMapEdits<M[Key]>;
|
66
|
+
};
|
67
|
+
|
68
|
+
type CoMapFieldSchema = {
|
69
|
+
[key: string]: Schema;
|
70
|
+
} & { [ItemsSym]?: Schema };
|
71
|
+
|
60
72
|
/**
|
61
73
|
* CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
|
62
74
|
*
|
@@ -91,196 +103,44 @@ type LastAndAllCoMapEdits<V> = CoMapEdit<V> & { all: CoMapEdit<V>[] };
|
|
91
103
|
* @category CoValues
|
92
104
|
* */
|
93
105
|
export class CoMap extends CoValueBase implements CoValue {
|
94
|
-
/**
|
95
|
-
* The ID of this `CoMap`
|
96
|
-
* @category Content */
|
97
|
-
declare id: ID<this>;
|
98
106
|
/** @category Type Helpers */
|
99
|
-
declare
|
107
|
+
declare [TypeSym]: "CoMap";
|
100
108
|
static {
|
101
|
-
this.prototype
|
102
|
-
}
|
103
|
-
/** @category Internals */
|
104
|
-
declare _raw: RawCoMap;
|
105
|
-
|
106
|
-
/** @internal */
|
107
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
108
|
-
static _schema: any;
|
109
|
-
/** @internal */
|
110
|
-
get _schema() {
|
111
|
-
return (this.constructor as typeof CoMap)._schema as {
|
112
|
-
[key: string]: Schema;
|
113
|
-
} & { [ItemsSym]?: Schema };
|
109
|
+
this.prototype[TypeSym] = "CoMap";
|
114
110
|
}
|
115
111
|
|
116
112
|
/**
|
117
|
-
*
|
118
|
-
*/
|
119
|
-
get _createdAt() {
|
120
|
-
return this._raw.earliestTxMadeAt ?? Number.MAX_SAFE_INTEGER;
|
121
|
-
}
|
122
|
-
|
123
|
-
/**
|
124
|
-
* The timestamp of the last updated time of the CoMap
|
125
|
-
*/
|
126
|
-
get _lastUpdatedAt() {
|
127
|
-
return this._raw.latestTxMadeAt;
|
128
|
-
}
|
129
|
-
|
130
|
-
/**
|
131
|
-
* If property `prop` is a `coField.ref(...)`, you can use `coMaps._refs.prop` to access
|
132
|
-
* the `Ref` instead of the potentially loaded/null value.
|
133
|
-
*
|
134
|
-
* This allows you to always get the ID or load the value manually.
|
135
|
-
*
|
136
|
-
* @example
|
137
|
-
* ```ts
|
138
|
-
* person._refs.pet.id; // => ID<Animal>
|
139
|
-
* person._refs.pet.value;
|
140
|
-
* // => Animal | null
|
141
|
-
* const pet = await person._refs.pet.load();
|
142
|
-
* ```
|
113
|
+
* Jazz methods for CoMaps are inside this property.
|
143
114
|
*
|
144
|
-
*
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
? Key
|
150
|
-
: never]?: RefIfCoValue<this[Key]>;
|
151
|
-
} & {
|
152
|
-
[Key in CoKeys<this> as this[Key] extends undefined
|
153
|
-
? never
|
154
|
-
: this[Key] extends CoValue
|
155
|
-
? Key
|
156
|
-
: never]: RefIfCoValue<this[Key]>;
|
157
|
-
}
|
158
|
-
> {
|
159
|
-
return makeRefs<CoKeys<this>>(
|
160
|
-
this,
|
161
|
-
(key) => this._raw.get(key as string) as unknown as ID<CoValue>,
|
162
|
-
() => {
|
163
|
-
const keys = this._raw.keys().filter((key) => {
|
164
|
-
const descriptor = this.getDescriptor(key as string);
|
165
|
-
return (
|
166
|
-
descriptor && descriptor !== "json" && isRefEncoded(descriptor)
|
167
|
-
);
|
168
|
-
}) as CoKeys<this>[];
|
169
|
-
|
170
|
-
return keys;
|
171
|
-
},
|
172
|
-
this._loadedAs,
|
173
|
-
(key) => this.getDescriptor(key as string) as RefEncoded<CoValue>,
|
174
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
175
|
-
) as any;
|
176
|
-
}
|
115
|
+
* This allows CoMaps to be used as plain objects while still having
|
116
|
+
* access to Jazz methods, and also doesn't limit which key names can be
|
117
|
+
* used inside CoMaps.
|
118
|
+
*/
|
119
|
+
declare $jazz: CoMapJazzApi<this>;
|
177
120
|
|
178
121
|
/** @internal */
|
179
|
-
|
180
|
-
target: CoMap,
|
181
|
-
rawEdit: {
|
182
|
-
by: RawAccountID | AgentID;
|
183
|
-
tx: CojsonInternalTypes.TransactionID;
|
184
|
-
at: Date;
|
185
|
-
value?: JsonValue | undefined;
|
186
|
-
},
|
187
|
-
descriptor: Schema,
|
188
|
-
key: string,
|
189
|
-
) {
|
190
|
-
return {
|
191
|
-
value:
|
192
|
-
descriptor === "json"
|
193
|
-
? rawEdit.value
|
194
|
-
: "encoded" in descriptor
|
195
|
-
? rawEdit.value === null || rawEdit.value === undefined
|
196
|
-
? rawEdit.value
|
197
|
-
: descriptor.encoded.decode(rawEdit.value)
|
198
|
-
: accessChildById(target, rawEdit.value as string, descriptor),
|
199
|
-
ref:
|
200
|
-
descriptor !== "json" && isRefEncoded(descriptor)
|
201
|
-
? new Ref(
|
202
|
-
rawEdit.value as ID<CoValue>,
|
203
|
-
target._loadedAs,
|
204
|
-
descriptor,
|
205
|
-
target,
|
206
|
-
)
|
207
|
-
: undefined,
|
208
|
-
get by() {
|
209
|
-
return (
|
210
|
-
rawEdit.by &&
|
211
|
-
accessChildById(target, rawEdit.by, {
|
212
|
-
ref: Account,
|
213
|
-
optional: false,
|
214
|
-
})
|
215
|
-
);
|
216
|
-
},
|
217
|
-
madeAt: rawEdit.at,
|
218
|
-
key,
|
219
|
-
};
|
220
|
-
}
|
221
|
-
|
222
|
-
/** @category Collaboration */
|
223
|
-
get _edits() {
|
224
|
-
const map = this;
|
225
|
-
return new Proxy(
|
226
|
-
{},
|
227
|
-
{
|
228
|
-
get(_target, key) {
|
229
|
-
const rawEdit = map._raw.lastEditAt(key as string);
|
230
|
-
if (!rawEdit) return undefined;
|
231
|
-
|
232
|
-
const descriptor = map.getDescriptor(key as string);
|
233
|
-
|
234
|
-
if (!descriptor) return undefined;
|
235
|
-
|
236
|
-
return {
|
237
|
-
...map.getEditFromRaw(map, rawEdit, descriptor, key as string),
|
238
|
-
get all() {
|
239
|
-
return [...map._raw.editsAt(key as string)].map((rawEdit) =>
|
240
|
-
map.getEditFromRaw(map, rawEdit, descriptor, key as string),
|
241
|
-
);
|
242
|
-
},
|
243
|
-
};
|
244
|
-
},
|
245
|
-
ownKeys(_target) {
|
246
|
-
return map._raw.keys();
|
247
|
-
},
|
248
|
-
getOwnPropertyDescriptor(target, key) {
|
249
|
-
return {
|
250
|
-
value: Reflect.get(target, key),
|
251
|
-
writable: false,
|
252
|
-
enumerable: true,
|
253
|
-
configurable: true,
|
254
|
-
};
|
255
|
-
},
|
256
|
-
},
|
257
|
-
) as {
|
258
|
-
[Key in CoKeys<this>]?: LastAndAllCoMapEdits<this[Key]>;
|
259
|
-
};
|
260
|
-
}
|
122
|
+
static _schema: CoMapFieldSchema;
|
261
123
|
|
262
124
|
/** @internal */
|
263
|
-
constructor(
|
264
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
265
|
-
options: { fromRaw: RawCoMap } | undefined,
|
266
|
-
) {
|
125
|
+
constructor(options: { fromRaw: RawCoMap } | undefined) {
|
267
126
|
super();
|
268
127
|
|
128
|
+
const proxy = new Proxy(this, CoMapProxyHandler as ProxyHandler<this>);
|
129
|
+
|
269
130
|
if (options) {
|
270
131
|
if ("fromRaw" in options) {
|
271
132
|
Object.defineProperties(this, {
|
272
|
-
|
273
|
-
value:
|
133
|
+
$jazz: {
|
134
|
+
value: new CoMapJazzApi(proxy, () => options.fromRaw),
|
274
135
|
enumerable: false,
|
275
136
|
},
|
276
|
-
_raw: { value: options.fromRaw, enumerable: false },
|
277
137
|
});
|
278
138
|
} else {
|
279
139
|
throw new Error("Invalid CoMap constructor arguments");
|
280
140
|
}
|
281
141
|
}
|
282
142
|
|
283
|
-
return
|
143
|
+
return proxy;
|
284
144
|
}
|
285
145
|
|
286
146
|
/**
|
@@ -300,13 +160,15 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
300
160
|
* ```
|
301
161
|
*
|
302
162
|
* @category Creation
|
163
|
+
*
|
164
|
+
* @deprecated Use `co.map(...).create`.
|
303
165
|
**/
|
304
166
|
static create<M extends CoMap>(
|
305
167
|
this: CoValueClass<M>,
|
306
|
-
init: Simplify<
|
168
|
+
init: Simplify<CoMapInit_DEPRECATED<M>>,
|
307
169
|
options?:
|
308
170
|
| {
|
309
|
-
owner
|
171
|
+
owner?: Account | Group;
|
310
172
|
unique?: CoValueUniqueness["uniqueness"];
|
311
173
|
}
|
312
174
|
| Account
|
@@ -314,7 +176,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
314
176
|
) {
|
315
177
|
const instance = new this();
|
316
178
|
|
317
|
-
return
|
179
|
+
return CoMap._createCoMap(instance, init, options);
|
318
180
|
}
|
319
181
|
|
320
182
|
/**
|
@@ -323,25 +185,22 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
323
185
|
*/
|
324
186
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
325
187
|
toJSON(_key?: string, processedValues?: ID<CoValue>[]): any {
|
326
|
-
const result = {
|
327
|
-
id: this.id,
|
328
|
-
_type: this._type,
|
329
|
-
} as Record<string, any>;
|
188
|
+
const result = {} as Record<string, any>;
|
330
189
|
|
331
|
-
for (const key of this.
|
190
|
+
for (const key of this.$jazz.raw.keys()) {
|
332
191
|
const tKey = key as CoKeys<this>;
|
333
|
-
const descriptor = this.getDescriptor(tKey);
|
192
|
+
const descriptor = this.$jazz.getDescriptor(tKey);
|
334
193
|
|
335
194
|
if (!descriptor) {
|
336
195
|
continue;
|
337
196
|
}
|
338
197
|
|
339
198
|
if (descriptor == "json" || "encoded" in descriptor) {
|
340
|
-
result[key] = this.
|
199
|
+
result[key] = this.$jazz.raw.get(key);
|
341
200
|
} else if (isRefEncoded(descriptor)) {
|
342
|
-
const id = this.
|
201
|
+
const id = this.$jazz.raw.get(key) as ID<CoValue>;
|
343
202
|
|
344
|
-
if (processedValues?.includes(id) || id === this.id) {
|
203
|
+
if (processedValues?.includes(id) || id === this.$jazz.id) {
|
345
204
|
result[key] = { _circular: id };
|
346
205
|
continue;
|
347
206
|
}
|
@@ -356,7 +215,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
356
215
|
) {
|
357
216
|
const jsonedRef = ref.toJSON(tKey, [
|
358
217
|
...(processedValues || []),
|
359
|
-
this.id,
|
218
|
+
this.$jazz.id,
|
360
219
|
]);
|
361
220
|
result[key] = jsonedRef;
|
362
221
|
}
|
@@ -372,41 +231,45 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
372
231
|
return this.toJSON();
|
373
232
|
}
|
374
233
|
|
375
|
-
|
376
|
-
|
234
|
+
/**
|
235
|
+
* @internal
|
236
|
+
*/
|
237
|
+
static _createCoMap<M extends CoMap>(
|
238
|
+
instance: M,
|
239
|
+
init: Simplify<CoMapInit_DEPRECATED<M>>,
|
377
240
|
options?:
|
378
241
|
| {
|
379
|
-
owner
|
242
|
+
owner?: Account | Group;
|
380
243
|
unique?: CoValueUniqueness["uniqueness"];
|
381
244
|
}
|
382
245
|
| Account
|
383
246
|
| Group,
|
384
|
-
):
|
247
|
+
): M {
|
385
248
|
const { owner, uniqueness } = parseCoValueCreateOptions(options);
|
386
|
-
const raw = this.rawFromInit(init, owner, uniqueness);
|
387
249
|
|
388
|
-
Object.defineProperties(
|
389
|
-
|
390
|
-
value: raw
|
250
|
+
Object.defineProperties(instance, {
|
251
|
+
$jazz: {
|
252
|
+
value: new CoMapJazzApi(instance, () => raw),
|
391
253
|
enumerable: false,
|
392
254
|
},
|
393
|
-
_raw: { value: raw, enumerable: false },
|
394
255
|
});
|
395
256
|
|
396
|
-
|
257
|
+
const raw = CoMap.rawFromInit(instance, init, owner, uniqueness);
|
258
|
+
|
259
|
+
return instance;
|
397
260
|
}
|
398
261
|
|
399
262
|
/**
|
400
263
|
* Create a new `RawCoMap` from an initialization object
|
401
264
|
* @internal
|
402
265
|
*/
|
403
|
-
|
404
|
-
|
405
|
-
init: Simplify<
|
406
|
-
owner:
|
266
|
+
static rawFromInit<M extends CoMap, Fields extends object>(
|
267
|
+
instance: M,
|
268
|
+
init: Simplify<CoMapInit_DEPRECATED<Fields>> | undefined,
|
269
|
+
owner: Group,
|
407
270
|
uniqueness?: CoValueUniqueness,
|
408
271
|
) {
|
409
|
-
const rawOwner = owner.
|
272
|
+
const rawOwner = owner.$jazz.raw;
|
410
273
|
|
411
274
|
const rawInit = {} as {
|
412
275
|
[key in keyof Fields]: JsonValue | undefined;
|
@@ -416,7 +279,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
416
279
|
for (const key of Object.keys(init) as (keyof Fields)[]) {
|
417
280
|
const initValue = init[key as keyof typeof init];
|
418
281
|
|
419
|
-
const descriptor =
|
282
|
+
const descriptor = instance.$jazz.getDescriptor(key as string);
|
420
283
|
|
421
284
|
if (!descriptor) {
|
422
285
|
continue;
|
@@ -426,14 +289,14 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
426
289
|
rawInit[key] = initValue as JsonValue;
|
427
290
|
} else if (isRefEncoded(descriptor)) {
|
428
291
|
if (initValue != null) {
|
429
|
-
let refId = (initValue as unknown as CoValue)
|
292
|
+
let refId = (initValue as unknown as CoValue).$jazz?.id;
|
430
293
|
if (!refId) {
|
431
294
|
const coValue = instantiateRefEncodedWithInit(
|
432
295
|
descriptor,
|
433
296
|
initValue,
|
434
297
|
owner,
|
435
298
|
);
|
436
|
-
refId = coValue.id;
|
299
|
+
refId = coValue.$jazz.id;
|
437
300
|
}
|
438
301
|
rawInit[key] = refId;
|
439
302
|
}
|
@@ -448,10 +311,6 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
448
311
|
return rawOwner.createMap(rawInit, null, "private", uniqueness);
|
449
312
|
}
|
450
313
|
|
451
|
-
getDescriptor(key: string) {
|
452
|
-
return this._schema?.[key] || this._schema?.[ItemsSym];
|
453
|
-
}
|
454
|
-
|
455
314
|
/**
|
456
315
|
* Declare a Record-like CoMap schema, by extending `CoMap.Record(...)` and passing the value schema using `co`. Keys are always `string`.
|
457
316
|
*
|
@@ -500,6 +359,8 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
500
359
|
* ```
|
501
360
|
*
|
502
361
|
* @category Subscription & Loading
|
362
|
+
*
|
363
|
+
* @deprecated Use `co.map(...).load` instead.
|
503
364
|
*/
|
504
365
|
static load<M extends CoMap, const R extends RefsToResolve<M> = true>(
|
505
366
|
this: CoValueClass<M>,
|
@@ -539,6 +400,8 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
539
400
|
* ```
|
540
401
|
*
|
541
402
|
* @category Subscription & Loading
|
403
|
+
*
|
404
|
+
* @deprecated Use `co.map(...).subscribe` instead.
|
542
405
|
*/
|
543
406
|
static subscribe<M extends CoMap, const R extends RefsToResolve<M> = true>(
|
544
407
|
this: CoValueClass<M>,
|
@@ -589,7 +452,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
589
452
|
uniqueness: unique,
|
590
453
|
};
|
591
454
|
const crypto =
|
592
|
-
as
|
455
|
+
as[TypeSym] === "Anonymous" ? as.node.crypto : as.$jazz.localNode.crypto;
|
593
456
|
return cojsonInternals.idforHeader(header, crypto) as ID<M>;
|
594
457
|
}
|
595
458
|
|
@@ -615,6 +478,8 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
615
478
|
* @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.
|
616
479
|
* @returns Either an existing & modified CoMap, or a new initialised CoMap if none exists.
|
617
480
|
* @category Subscription & Loading
|
481
|
+
*
|
482
|
+
* @deprecated Use `co.map(...).upsertUnique` instead.
|
618
483
|
*/
|
619
484
|
static async upsertUnique<
|
620
485
|
M extends CoMap,
|
@@ -622,7 +487,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
622
487
|
>(
|
623
488
|
this: CoValueClass<M>,
|
624
489
|
options: {
|
625
|
-
value: Simplify<
|
490
|
+
value: Simplify<CoMapInit_DEPRECATED<M>>;
|
626
491
|
unique: CoValueUniqueness["uniqueness"];
|
627
492
|
owner: Account | Group;
|
628
493
|
resolve?: RefsToResolveStrict<M, R>;
|
@@ -630,27 +495,29 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
630
495
|
): Promise<Resolved<M, R> | null> {
|
631
496
|
const mapId = CoMap._findUnique(
|
632
497
|
options.unique,
|
633
|
-
options.owner.id,
|
634
|
-
options.owner.
|
498
|
+
options.owner.$jazz.id,
|
499
|
+
options.owner.$jazz.loadedAs,
|
635
500
|
);
|
636
501
|
let map: Resolved<M, R> | null = await loadCoValueWithoutMe(this, mapId, {
|
637
502
|
...options,
|
638
|
-
loadAs: options.owner.
|
503
|
+
loadAs: options.owner.$jazz.loadedAs,
|
639
504
|
skipRetry: true,
|
640
505
|
});
|
641
506
|
if (!map) {
|
642
507
|
const instance = new this();
|
643
|
-
map =
|
508
|
+
map = CoMap._createCoMap(instance, options.value, {
|
644
509
|
owner: options.owner,
|
645
510
|
unique: options.unique,
|
646
511
|
}) as Resolved<M, R>;
|
647
512
|
} else {
|
648
|
-
(map as M).applyDiff(
|
513
|
+
(map as M).$jazz.applyDiff(
|
514
|
+
options.value as unknown as Partial<CoMapInit<M>>,
|
515
|
+
);
|
649
516
|
}
|
650
517
|
|
651
518
|
return await loadCoValueWithoutMe(this, mapId, {
|
652
519
|
...options,
|
653
|
-
loadAs: options.owner.
|
520
|
+
loadAs: options.owner.$jazz.loadedAs,
|
654
521
|
skipRetry: true,
|
655
522
|
});
|
656
523
|
}
|
@@ -661,6 +528,8 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
661
528
|
* @param ownerID The ID of the owner of the CoMap.
|
662
529
|
* @param options Additional options for loading the CoMap.
|
663
530
|
* @returns The loaded CoMap, or null if unavailable.
|
531
|
+
*
|
532
|
+
* @deprecated Use `co.map(...).loadUnique` instead.
|
664
533
|
*/
|
665
534
|
static loadUnique<M extends CoMap, const R extends RefsToResolve<M> = true>(
|
666
535
|
this: CoValueClass<M>,
|
@@ -677,48 +546,100 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
677
546
|
{ ...options, skipRetry: true },
|
678
547
|
);
|
679
548
|
}
|
549
|
+
}
|
550
|
+
|
551
|
+
/**
|
552
|
+
* Contains CoMap Jazz methods that are part of the {@link CoMap.$jazz`} property.
|
553
|
+
*/
|
554
|
+
class CoMapJazzApi<M extends CoMap> extends CoValueJazzApi<M> {
|
555
|
+
constructor(
|
556
|
+
private coMap: M,
|
557
|
+
private getRaw: () => RawCoMap,
|
558
|
+
) {
|
559
|
+
super(coMap);
|
560
|
+
}
|
680
561
|
|
681
562
|
/**
|
682
|
-
*
|
563
|
+
* The ID of this `CoMap`
|
564
|
+
* @category Content
|
565
|
+
*/
|
566
|
+
get id(): ID<M> {
|
567
|
+
return this.raw.id;
|
568
|
+
}
|
569
|
+
|
570
|
+
get owner(): Group {
|
571
|
+
return getCoValueOwner(this.coMap);
|
572
|
+
}
|
573
|
+
|
574
|
+
/**
|
575
|
+
* Set a value on the CoMap
|
683
576
|
*
|
684
|
-
*
|
577
|
+
* @param key The key to set
|
578
|
+
* @param value The value to set
|
685
579
|
*
|
686
|
-
* @category
|
580
|
+
* @category Content
|
687
581
|
*/
|
688
|
-
|
689
|
-
this
|
690
|
-
|
691
|
-
|
692
|
-
|
582
|
+
set<K extends CoKeys<M>>(key: K, value: CoFieldInit<M[K]>): void {
|
583
|
+
const descriptor = this.getDescriptor(key as string);
|
584
|
+
|
585
|
+
if (!descriptor) {
|
586
|
+
throw Error(`Cannot set unknown key ${key}`);
|
587
|
+
}
|
588
|
+
|
589
|
+
let refId = (value as CoValue)?.$jazz?.id;
|
590
|
+
if (descriptor === "json") {
|
591
|
+
this.raw.set(key, value as JsonValue | undefined);
|
592
|
+
} else if ("encoded" in descriptor) {
|
593
|
+
this.raw.set(key, descriptor.encoded.encode(value));
|
594
|
+
} else if (isRefEncoded(descriptor)) {
|
595
|
+
if (value === undefined) {
|
596
|
+
if (!descriptor.optional) {
|
597
|
+
throw Error(`Cannot set required reference ${key} to undefined`);
|
598
|
+
}
|
599
|
+
this.raw.set(key, null);
|
600
|
+
} else {
|
601
|
+
if (!refId) {
|
602
|
+
const coValue = instantiateRefEncodedWithInit(
|
603
|
+
descriptor,
|
604
|
+
value,
|
605
|
+
this.owner,
|
606
|
+
);
|
607
|
+
refId = coValue.$jazz.id;
|
608
|
+
}
|
609
|
+
this.raw.set(key, refId);
|
610
|
+
}
|
611
|
+
}
|
693
612
|
}
|
694
613
|
|
695
614
|
/**
|
696
|
-
*
|
615
|
+
* Delete a value from a CoMap.
|
697
616
|
*
|
698
|
-
*
|
617
|
+
* For record-like CoMaps (created with `co.record`), any string key can be deleted.
|
618
|
+
* For struct-like CoMaps (created with `co.map`), only optional properties can be deleted.
|
699
619
|
*
|
700
|
-
*
|
620
|
+
* @param key The key to delete
|
701
621
|
*
|
702
|
-
* @category
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
subscribe<M extends CoMap, const R extends RefsToResolve<M> = true>(
|
709
|
-
this: M,
|
710
|
-
options: { resolve?: RefsToResolveStrict<M, R> },
|
711
|
-
listener: (value: Resolved<M, R>, unsubscribe: () => void) => void,
|
712
|
-
): () => void;
|
713
|
-
subscribe<M extends CoMap, const R extends RefsToResolve<M>>(
|
714
|
-
this: M,
|
715
|
-
...args: SubscribeRestArgs<M, R>
|
716
|
-
): () => void {
|
717
|
-
const { options, listener } = parseSubscribeRestArgs(args);
|
718
|
-
return subscribeToExistingCoValue<M, R>(this, options, listener);
|
622
|
+
* @category Content
|
623
|
+
*/
|
624
|
+
delete(
|
625
|
+
key: OptionalCoKeys<M> | (string extends keyof M ? string : never),
|
626
|
+
): void {
|
627
|
+
this.raw.delete(key);
|
719
628
|
}
|
720
629
|
|
721
|
-
|
630
|
+
/**
|
631
|
+
* Modify the `CoMap` to match another map.
|
632
|
+
*
|
633
|
+
* The new values are assigned to the CoMap, overwriting existing values
|
634
|
+
* when the property already exists.
|
635
|
+
*
|
636
|
+
* @param newValues - The new values to apply to the CoMap. For collaborative values,
|
637
|
+
* both CoValues and JSON values are supported.
|
638
|
+
* @returns The modified CoMap.
|
639
|
+
*
|
640
|
+
* @category Content
|
641
|
+
*/
|
642
|
+
applyDiff(newValues: Partial<CoMapInit<M>>): M {
|
722
643
|
for (const key in newValues) {
|
723
644
|
if (Object.prototype.hasOwnProperty.call(newValues, key)) {
|
724
645
|
const tKey = key as keyof typeof newValues & keyof this;
|
@@ -727,24 +648,64 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
727
648
|
if (!descriptor) continue;
|
728
649
|
|
729
650
|
const newValue = newValues[tKey];
|
730
|
-
const currentValue =
|
651
|
+
const currentValue = this.coMap[tKey];
|
731
652
|
|
732
653
|
if (descriptor === "json" || "encoded" in descriptor) {
|
733
654
|
if (currentValue !== newValue) {
|
734
|
-
|
735
|
-
(this as any)[tKey] = newValue;
|
655
|
+
this.set(tKey as any, newValue as CoFieldInit<M[keyof M]>);
|
736
656
|
}
|
737
657
|
} else if (isRefEncoded(descriptor)) {
|
738
|
-
const currentId = (currentValue as CoValue | undefined)
|
739
|
-
|
658
|
+
const currentId = (currentValue as CoValue | undefined)?.$jazz.id;
|
659
|
+
let newId = (newValue as CoValue | undefined)?.$jazz?.id;
|
740
660
|
if (currentId !== newId) {
|
741
|
-
|
742
|
-
(this as any)[tKey] = newValue;
|
661
|
+
this.set(tKey as any, newValue as CoFieldInit<M[keyof M]>);
|
743
662
|
}
|
744
663
|
}
|
745
664
|
}
|
746
665
|
}
|
747
|
-
return this;
|
666
|
+
return this.coMap;
|
667
|
+
}
|
668
|
+
|
669
|
+
/**
|
670
|
+
* Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth.
|
671
|
+
*
|
672
|
+
* Works like `CoMap.load()`, but you don't need to pass the ID or the account to load as again.
|
673
|
+
*
|
674
|
+
* @category Subscription & Loading
|
675
|
+
*/
|
676
|
+
ensureLoaded<Map extends CoMap, const R extends RefsToResolve<Map>>(
|
677
|
+
this: CoMapJazzApi<Map>,
|
678
|
+
options: {
|
679
|
+
resolve: RefsToResolveStrict<Map, R>;
|
680
|
+
},
|
681
|
+
): Promise<Resolved<Map, R>> {
|
682
|
+
return ensureCoValueLoaded(this.coMap, options);
|
683
|
+
}
|
684
|
+
|
685
|
+
/**
|
686
|
+
* Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth.
|
687
|
+
*
|
688
|
+
* Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
689
|
+
*
|
690
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
691
|
+
*
|
692
|
+
* @category Subscription & Loading
|
693
|
+
**/
|
694
|
+
subscribe<Map extends CoMap, const R extends RefsToResolve<Map> = true>(
|
695
|
+
this: CoMapJazzApi<Map>,
|
696
|
+
listener: (value: Resolved<Map, R>, unsubscribe: () => void) => void,
|
697
|
+
): () => void;
|
698
|
+
subscribe<Map extends CoMap, const R extends RefsToResolve<Map> = true>(
|
699
|
+
this: CoMapJazzApi<Map>,
|
700
|
+
options: { resolve?: RefsToResolveStrict<Map, R> },
|
701
|
+
listener: (value: Resolved<Map, R>, unsubscribe: () => void) => void,
|
702
|
+
): () => void;
|
703
|
+
subscribe<Map extends CoMap, const R extends RefsToResolve<Map>>(
|
704
|
+
this: CoMapJazzApi<Map>,
|
705
|
+
...args: SubscribeRestArgs<Map, R>
|
706
|
+
): () => void {
|
707
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
708
|
+
return subscribeToExistingCoValue(this.coMap, options, listener);
|
748
709
|
}
|
749
710
|
|
750
711
|
/**
|
@@ -752,8 +713,134 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
752
713
|
*
|
753
714
|
* @category Subscription & Loading
|
754
715
|
*/
|
755
|
-
waitForSync(options?: { timeout?: number }) {
|
756
|
-
|
716
|
+
async waitForSync(options?: { timeout?: number }): Promise<void> {
|
717
|
+
await this.raw.core.waitForSync(options);
|
718
|
+
}
|
719
|
+
|
720
|
+
/**
|
721
|
+
* Get the descriptor for a given key
|
722
|
+
* @internal
|
723
|
+
*/
|
724
|
+
getDescriptor(key: string): Schema | undefined {
|
725
|
+
return this.schema?.[key] || this.schema?.[ItemsSym];
|
726
|
+
}
|
727
|
+
|
728
|
+
/**
|
729
|
+
* If property `prop` is a `coField.ref(...)`, you can use `coMap.$jazz.refs.prop` to access
|
730
|
+
* the `Ref` instead of the potentially loaded/null value.
|
731
|
+
*
|
732
|
+
* This allows you to always get the ID or load the value manually.
|
733
|
+
*
|
734
|
+
* @example
|
735
|
+
* ```ts
|
736
|
+
* person.$jazz.refs.pet.id; // => ID<Animal>
|
737
|
+
* person.$jazz.refs.pet.value;
|
738
|
+
* // => Animal | null
|
739
|
+
* const pet = await person.$jazz.refs.pet.load();
|
740
|
+
* ```
|
741
|
+
*
|
742
|
+
* @category Content
|
743
|
+
**/
|
744
|
+
get refs(): Simplify<
|
745
|
+
{
|
746
|
+
[Key in CoKeys<M> as NonNullable<M[Key]> extends CoValue
|
747
|
+
? Key
|
748
|
+
: never]?: RefIfCoValue<M[Key]>;
|
749
|
+
} & {
|
750
|
+
[Key in CoKeys<M> as M[Key] extends undefined
|
751
|
+
? never
|
752
|
+
: M[Key] extends CoValue
|
753
|
+
? Key
|
754
|
+
: never]: RefIfCoValue<M[Key]>;
|
755
|
+
}
|
756
|
+
> {
|
757
|
+
return makeRefs<CoKeys<this>>(
|
758
|
+
this.coMap,
|
759
|
+
(key) => this.raw.get(key as string) as unknown as ID<CoValue>,
|
760
|
+
() => {
|
761
|
+
const keys = this.raw.keys().filter((key) => {
|
762
|
+
const descriptor = this.getDescriptor(key as string);
|
763
|
+
return (
|
764
|
+
descriptor && descriptor !== "json" && isRefEncoded(descriptor)
|
765
|
+
);
|
766
|
+
}) as CoKeys<this>[];
|
767
|
+
|
768
|
+
return keys;
|
769
|
+
},
|
770
|
+
this.loadedAs,
|
771
|
+
(key) => this.getDescriptor(key as string) as RefEncoded<CoValue>,
|
772
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
773
|
+
) as any;
|
774
|
+
}
|
775
|
+
|
776
|
+
/**
|
777
|
+
* Get the edits made to the CoMap.
|
778
|
+
*
|
779
|
+
* @category Collaboration
|
780
|
+
*/
|
781
|
+
getEdits(): CoMapEdits<M> {
|
782
|
+
const map = this.coMap;
|
783
|
+
return new Proxy(
|
784
|
+
{},
|
785
|
+
{
|
786
|
+
get(_target, key) {
|
787
|
+
const rawEdit = map.$jazz.raw.lastEditAt(key as string);
|
788
|
+
if (!rawEdit) return undefined;
|
789
|
+
|
790
|
+
const descriptor = map.$jazz.getDescriptor(key as string);
|
791
|
+
|
792
|
+
if (!descriptor) return undefined;
|
793
|
+
|
794
|
+
return {
|
795
|
+
...getEditFromRaw(map, rawEdit, descriptor, key as string),
|
796
|
+
get all() {
|
797
|
+
return [...map.$jazz.raw.editsAt(key as string)].map((rawEdit) =>
|
798
|
+
getEditFromRaw(map, rawEdit, descriptor, key as string),
|
799
|
+
);
|
800
|
+
},
|
801
|
+
};
|
802
|
+
},
|
803
|
+
ownKeys(_target) {
|
804
|
+
return map.$jazz.raw.keys();
|
805
|
+
},
|
806
|
+
getOwnPropertyDescriptor(target, key) {
|
807
|
+
return {
|
808
|
+
value: Reflect.get(target, key),
|
809
|
+
writable: false,
|
810
|
+
enumerable: true,
|
811
|
+
configurable: true,
|
812
|
+
};
|
813
|
+
},
|
814
|
+
},
|
815
|
+
);
|
816
|
+
}
|
817
|
+
|
818
|
+
/** @internal */
|
819
|
+
override get raw() {
|
820
|
+
return this.getRaw();
|
821
|
+
}
|
822
|
+
|
823
|
+
/**
|
824
|
+
* The timestamp of the creation time of the CoMap
|
825
|
+
*
|
826
|
+
* @category Content
|
827
|
+
*/
|
828
|
+
get createdAt(): number {
|
829
|
+
return this.raw.earliestTxMadeAt ?? Number.MAX_SAFE_INTEGER;
|
830
|
+
}
|
831
|
+
|
832
|
+
/**
|
833
|
+
* The timestamp of the last updated time of the CoMap
|
834
|
+
*
|
835
|
+
* @category Content
|
836
|
+
*/
|
837
|
+
get lastUpdatedAt(): number {
|
838
|
+
return this.raw.latestTxMadeAt;
|
839
|
+
}
|
840
|
+
|
841
|
+
/** @internal */
|
842
|
+
get schema(): CoMapFieldSchema {
|
843
|
+
return (this.coMap.constructor as typeof CoMap)._schema;
|
757
844
|
}
|
758
845
|
}
|
759
846
|
|
@@ -762,6 +849,20 @@ export type CoKeys<Map extends object> = Exclude<
|
|
762
849
|
keyof CoMap
|
763
850
|
>;
|
764
851
|
|
852
|
+
/**
|
853
|
+
* Extract keys of properties that are required
|
854
|
+
*/
|
855
|
+
export type RequiredCoKeys<Map extends object> = {
|
856
|
+
[K in CoKeys<Map>]: undefined extends Map[K] ? never : K;
|
857
|
+
}[CoKeys<Map>];
|
858
|
+
|
859
|
+
/**
|
860
|
+
* Extract keys of properties that can be undefined
|
861
|
+
*/
|
862
|
+
export type OptionalCoKeys<Map extends object> = {
|
863
|
+
[K in CoKeys<Map>]: undefined extends Map[K] ? K : never;
|
864
|
+
}[CoKeys<Map>];
|
865
|
+
|
765
866
|
/**
|
766
867
|
* Force required ref fields to be non nullable
|
767
868
|
*
|
@@ -793,10 +894,16 @@ type ForceRequiredRef<V> = V extends InstanceType<CoValueClass> | null
|
|
793
894
|
? V | null
|
794
895
|
: V;
|
795
896
|
|
796
|
-
export type
|
897
|
+
export type CoMapInit_DEPRECATED<Map extends object> = PartialOnUndefined<{
|
797
898
|
[Key in CoKeys<Map>]: ForceRequiredRef<Map[Key]>;
|
798
899
|
}>;
|
799
900
|
|
901
|
+
export type CoMapInit<Map extends object> = {
|
902
|
+
[K in RequiredCoKeys<Map>]: CoFieldInit<Map[K]>;
|
903
|
+
} & {
|
904
|
+
[K in OptionalCoKeys<Map>]?: CoFieldInit<Map[K]> | undefined;
|
905
|
+
};
|
906
|
+
|
800
907
|
// TODO: cache handlers per descriptor for performance?
|
801
908
|
const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
802
909
|
get(target, key, receiver) {
|
@@ -809,13 +916,13 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
809
916
|
return undefined;
|
810
917
|
}
|
811
918
|
|
812
|
-
const descriptor = target.getDescriptor(key as string);
|
919
|
+
const descriptor = target.$jazz.getDescriptor(key as string);
|
813
920
|
|
814
921
|
if (!descriptor) {
|
815
922
|
return undefined;
|
816
923
|
}
|
817
924
|
|
818
|
-
const raw = target.
|
925
|
+
const raw = target.$jazz.raw.get(key);
|
819
926
|
|
820
927
|
if (descriptor === "json") {
|
821
928
|
return raw;
|
@@ -830,7 +937,7 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
830
937
|
},
|
831
938
|
set(target, key, value, receiver) {
|
832
939
|
if (
|
833
|
-
|
940
|
+
typeof key === "string" &&
|
834
941
|
typeof value === "object" &&
|
835
942
|
value !== null &&
|
836
943
|
SchemaInit in value
|
@@ -840,33 +947,12 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
840
947
|
return true;
|
841
948
|
}
|
842
949
|
|
843
|
-
const descriptor = target.getDescriptor(key as string);
|
950
|
+
const descriptor = target.$jazz.getDescriptor(key as string);
|
844
951
|
|
845
952
|
if (!descriptor) return false;
|
846
953
|
|
847
954
|
if (typeof key === "string") {
|
848
|
-
|
849
|
-
target._raw.set(key, value);
|
850
|
-
} else if ("encoded" in descriptor) {
|
851
|
-
target._raw.set(key, descriptor.encoded.encode(value));
|
852
|
-
} else if (isRefEncoded(descriptor)) {
|
853
|
-
if (value === undefined) {
|
854
|
-
if (descriptor.optional) {
|
855
|
-
target._raw.set(key, null);
|
856
|
-
} else {
|
857
|
-
throw new Error(
|
858
|
-
`Cannot set required reference ${key} to undefined`,
|
859
|
-
);
|
860
|
-
}
|
861
|
-
} else if (value?.id) {
|
862
|
-
target._raw.set(key, value.id);
|
863
|
-
} else {
|
864
|
-
throw new Error(
|
865
|
-
`Cannot set reference ${key} to a non-CoValue. Got ${value}`,
|
866
|
-
);
|
867
|
-
}
|
868
|
-
}
|
869
|
-
return true;
|
955
|
+
throw Error("Cannot update a CoMap directly. Use `$jazz.set` instead.");
|
870
956
|
} else {
|
871
957
|
return Reflect.set(target, key, value, receiver);
|
872
958
|
}
|
@@ -888,7 +974,7 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
888
974
|
ownKeys(target) {
|
889
975
|
const keys = Reflect.ownKeys(target).filter((k) => k !== ItemsSym);
|
890
976
|
|
891
|
-
for (const key of target.
|
977
|
+
for (const key of target.$jazz.raw.keys()) {
|
892
978
|
if (!keys.includes(key)) {
|
893
979
|
keys.push(key);
|
894
980
|
}
|
@@ -900,9 +986,9 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
900
986
|
if (key in target) {
|
901
987
|
return Reflect.getOwnPropertyDescriptor(target, key);
|
902
988
|
} else {
|
903
|
-
const descriptor = target.getDescriptor(key as string);
|
989
|
+
const descriptor = target.$jazz.getDescriptor(key as string);
|
904
990
|
|
905
|
-
if (descriptor || key in target.
|
991
|
+
if (descriptor || key in target.$jazz.raw.latest) {
|
906
992
|
return {
|
907
993
|
enumerable: true,
|
908
994
|
configurable: true,
|
@@ -912,20 +998,24 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
912
998
|
}
|
913
999
|
},
|
914
1000
|
has(target, key) {
|
915
|
-
|
1001
|
+
// The `has` trap can be called when defining properties during CoMap creation
|
1002
|
+
// when using the class-based syntax. In that case, $jazz may not yet be initialized,
|
1003
|
+
// as it's defined afterwards in the create method.
|
1004
|
+
const descriptor = target.$jazz?.getDescriptor(key as string);
|
916
1005
|
|
917
|
-
if (target
|
918
|
-
return target.
|
1006
|
+
if (target.$jazz?.raw && typeof key === "string" && descriptor) {
|
1007
|
+
return target.$jazz.raw.get(key) !== undefined;
|
919
1008
|
} else {
|
920
1009
|
return Reflect.has(target, key);
|
921
1010
|
}
|
922
1011
|
},
|
923
1012
|
deleteProperty(target, key) {
|
924
|
-
const descriptor = target.getDescriptor(key as string);
|
1013
|
+
const descriptor = target.$jazz.getDescriptor(key as string);
|
925
1014
|
|
926
1015
|
if (typeof key === "string" && descriptor) {
|
927
|
-
|
928
|
-
|
1016
|
+
throw Error(
|
1017
|
+
"Cannot delete a CoMap property directly. Use `$jazz.delete` instead.",
|
1018
|
+
);
|
929
1019
|
} else {
|
930
1020
|
return Reflect.deleteProperty(target, key);
|
931
1021
|
}
|
@@ -933,3 +1023,47 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
933
1023
|
};
|
934
1024
|
|
935
1025
|
RegisteredSchemas["CoMap"] = CoMap;
|
1026
|
+
|
1027
|
+
/** @internal */
|
1028
|
+
function getEditFromRaw(
|
1029
|
+
target: CoMap,
|
1030
|
+
rawEdit: {
|
1031
|
+
by: RawAccountID | AgentID;
|
1032
|
+
tx: CojsonInternalTypes.TransactionID;
|
1033
|
+
at: Date;
|
1034
|
+
value?: JsonValue | undefined;
|
1035
|
+
},
|
1036
|
+
descriptor: Schema,
|
1037
|
+
key: string,
|
1038
|
+
) {
|
1039
|
+
return {
|
1040
|
+
value:
|
1041
|
+
descriptor === "json"
|
1042
|
+
? rawEdit.value
|
1043
|
+
: "encoded" in descriptor
|
1044
|
+
? rawEdit.value === null || rawEdit.value === undefined
|
1045
|
+
? rawEdit.value
|
1046
|
+
: descriptor.encoded.decode(rawEdit.value)
|
1047
|
+
: accessChildById(target, rawEdit.value as string, descriptor),
|
1048
|
+
ref:
|
1049
|
+
descriptor !== "json" && isRefEncoded(descriptor)
|
1050
|
+
? new Ref(
|
1051
|
+
rawEdit.value as ID<CoValue>,
|
1052
|
+
target.$jazz.loadedAs,
|
1053
|
+
descriptor,
|
1054
|
+
target,
|
1055
|
+
)
|
1056
|
+
: undefined,
|
1057
|
+
get by() {
|
1058
|
+
return (
|
1059
|
+
rawEdit.by &&
|
1060
|
+
accessChildById(target, rawEdit.by, {
|
1061
|
+
ref: Account,
|
1062
|
+
optional: false,
|
1063
|
+
})
|
1064
|
+
);
|
1065
|
+
},
|
1066
|
+
madeAt: rawEdit.at,
|
1067
|
+
key,
|
1068
|
+
};
|
1069
|
+
}
|