jazz-tools 0.17.13 → 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 +49 -49
- package/CHANGELOG.md +42 -0
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-SFP5PBPX.js → chunk-HJ3GTGY7.js} +1325 -1001
- 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 +47 -10
- 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 +154 -74
- 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 +368 -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-SFP5PBPX.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
@@ -1,11 +1,13 @@
|
|
1
|
-
import type {
|
2
|
-
import {
|
1
|
+
import type { CoValueUniqueness, JsonValue, RawCoID, RawCoList } from "cojson";
|
2
|
+
import { cojsonInternals } from "cojson";
|
3
3
|
import { calcPatch } from "fast-myers-diff";
|
4
|
-
import
|
4
|
+
import {
|
5
5
|
Account,
|
6
|
+
CoFieldInit,
|
6
7
|
CoValue,
|
7
8
|
CoValueClass,
|
8
|
-
|
9
|
+
CoValueJazzApi,
|
10
|
+
getCoValueOwner,
|
9
11
|
Group,
|
10
12
|
ID,
|
11
13
|
RefEncoded,
|
@@ -16,18 +18,16 @@ import type {
|
|
16
18
|
SchemaFor,
|
17
19
|
SubscribeListenerOptions,
|
18
20
|
SubscribeRestArgs,
|
21
|
+
TypeSym,
|
19
22
|
} from "../internal.js";
|
20
23
|
import {
|
21
24
|
AnonymousJazzAgent,
|
22
25
|
ItemsSym,
|
23
26
|
Ref,
|
24
|
-
RegisteredSchemas,
|
25
27
|
SchemaInit,
|
26
28
|
accessChildByKey,
|
27
29
|
activeAccountContext,
|
28
30
|
coField,
|
29
|
-
coValueClassFromCoValueClassOrSchema,
|
30
|
-
coValuesCache,
|
31
31
|
ensureCoValueLoaded,
|
32
32
|
inspect,
|
33
33
|
instantiateRefEncodedWithInit,
|
@@ -46,19 +46,28 @@ import {
|
|
46
46
|
* @categoryDescription Content
|
47
47
|
* You can access items on a `CoList` as if they were normal items on a plain array, using `[]` notation, etc.
|
48
48
|
*
|
49
|
-
*
|
49
|
+
* All readonly array methods are available on `CoList`. You can also use the `.$jazz` API to mutate the CoList.
|
50
|
+
*
|
51
|
+
* ```ts
|
52
|
+
* const colorList = ColorList.create(["red", "green", "blue"]);
|
53
|
+
* ```
|
50
54
|
*
|
51
55
|
* ```ts
|
52
56
|
* colorList[0];
|
53
|
-
* colorList
|
54
|
-
* colorList.push("Kawazaki Green");
|
55
|
-
* colorList.splice(1, 1);
|
57
|
+
* colorList.$jazz.set(3, "yellow");
|
58
|
+
* colorList.$jazz.push("Kawazaki Green");
|
59
|
+
* colorList.$jazz.splice(1, 1);
|
56
60
|
* ```
|
57
61
|
*
|
58
62
|
* @category CoValues
|
59
63
|
*/
|
60
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
61
|
-
export class CoList<out Item = any>
|
65
|
+
export class CoList<out Item = any>
|
66
|
+
extends Array<Item>
|
67
|
+
implements ReadonlyArray<Item>, CoValue
|
68
|
+
{
|
69
|
+
declare $jazz: CoListJazzApi<this>;
|
70
|
+
|
62
71
|
/**
|
63
72
|
* Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
|
64
73
|
*
|
@@ -88,129 +97,37 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
88
97
|
throw new Error("Can't use Array.of with CoLists");
|
89
98
|
}
|
90
99
|
|
91
|
-
/**
|
92
|
-
* The ID of this `CoList`
|
93
|
-
* @category Content */
|
94
|
-
declare id: ID<this>;
|
95
100
|
/** @category Type Helpers */
|
96
|
-
declare
|
101
|
+
declare [TypeSym]: "CoList";
|
97
102
|
static {
|
98
|
-
this.prototype
|
103
|
+
this.prototype[TypeSym] = "CoList";
|
99
104
|
}
|
100
|
-
/** @category Internals */
|
101
|
-
declare _raw: RawCoList;
|
102
|
-
/** @category Internals */
|
103
|
-
declare _instanceID: string;
|
104
105
|
|
105
106
|
/** @internal This is only a marker type and doesn't exist at runtime */
|
106
107
|
[ItemsSym]!: Item;
|
107
108
|
/** @internal */
|
108
109
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
109
110
|
static _schema: any;
|
110
|
-
/** @internal */
|
111
|
-
get _schema(): {
|
112
|
-
[ItemsSym]: SchemaFor<Item> | any;
|
113
|
-
} {
|
114
|
-
return (this.constructor as typeof CoList)._schema;
|
115
|
-
}
|
116
|
-
|
117
|
-
/** @category Collaboration */
|
118
|
-
get _owner(): Account | Group {
|
119
|
-
return this._raw.group instanceof RawAccount
|
120
|
-
? coValueClassFromCoValueClassOrSchema(
|
121
|
-
RegisteredSchemas["Account"],
|
122
|
-
).fromRaw(this._raw.group)
|
123
|
-
: RegisteredSchemas["Group"].fromRaw(this._raw.group);
|
124
|
-
}
|
125
|
-
|
126
|
-
/**
|
127
|
-
* If a `CoList`'s items are a `coField.ref(...)`, you can use `coList._refs[i]` to access
|
128
|
-
* the `Ref` instead of the potentially loaded/null value.
|
129
|
-
*
|
130
|
-
* This allows you to always get the ID or load the value manually.
|
131
|
-
*
|
132
|
-
* @example
|
133
|
-
* ```ts
|
134
|
-
* animals._refs[0].id; // => ID<Animal>
|
135
|
-
* animals._refs[0].value;
|
136
|
-
* // => Animal | null
|
137
|
-
* const animal = await animals._refs[0].load();
|
138
|
-
* ```
|
139
|
-
*
|
140
|
-
* @category Content
|
141
|
-
**/
|
142
|
-
get _refs(): {
|
143
|
-
[idx: number]: Exclude<Item, null> extends CoValue
|
144
|
-
? Ref<Exclude<Item, null>>
|
145
|
-
: never;
|
146
|
-
} & {
|
147
|
-
length: number;
|
148
|
-
[Symbol.iterator](): IterableIterator<
|
149
|
-
Exclude<Item, null> extends CoValue ? Ref<Exclude<Item, null>> : never
|
150
|
-
>;
|
151
|
-
} {
|
152
|
-
return makeRefs<number>(
|
153
|
-
this,
|
154
|
-
(idx) => this._raw.get(idx) as unknown as ID<CoValue>,
|
155
|
-
() => Array.from({ length: this._raw.entries().length }, (_, idx) => idx),
|
156
|
-
this._loadedAs,
|
157
|
-
(_idx) => this._schema[ItemsSym] as RefEncoded<CoValue>,
|
158
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
159
|
-
) as any;
|
160
|
-
}
|
161
|
-
|
162
|
-
get _edits(): {
|
163
|
-
[idx: number]: {
|
164
|
-
value?: Item;
|
165
|
-
ref?: Item extends CoValue ? Ref<Item> : never;
|
166
|
-
by: Account | null;
|
167
|
-
madeAt: Date;
|
168
|
-
};
|
169
|
-
} {
|
170
|
-
throw new Error("Not implemented");
|
171
|
-
}
|
172
|
-
|
173
|
-
get _loadedAs() {
|
174
|
-
const agent = this._raw.core.node.getCurrentAgent();
|
175
|
-
|
176
|
-
if (agent instanceof ControlledAccount) {
|
177
|
-
return coValuesCache.get(agent.account, () =>
|
178
|
-
coValueClassFromCoValueClassOrSchema(
|
179
|
-
RegisteredSchemas["Account"],
|
180
|
-
).fromRaw(agent.account),
|
181
|
-
);
|
182
|
-
}
|
183
|
-
|
184
|
-
return new AnonymousJazzAgent(this._raw.core.node);
|
185
|
-
}
|
186
111
|
|
187
112
|
static get [Symbol.species]() {
|
188
113
|
return Array;
|
189
114
|
}
|
190
115
|
|
191
|
-
getItemsDescriptor() {
|
192
|
-
return this._schema?.[ItemsSym];
|
193
|
-
}
|
194
|
-
|
195
116
|
constructor(options: { fromRaw: RawCoList } | undefined) {
|
196
117
|
super();
|
197
118
|
|
198
|
-
|
199
|
-
value: `instance-${Math.random().toString(36).slice(2)}`,
|
200
|
-
enumerable: false,
|
201
|
-
});
|
119
|
+
const proxy = new Proxy(this, CoListProxyHandler as ProxyHandler<this>);
|
202
120
|
|
203
121
|
if (options && "fromRaw" in options) {
|
204
122
|
Object.defineProperties(this, {
|
205
|
-
|
206
|
-
value: options.fromRaw
|
123
|
+
$jazz: {
|
124
|
+
value: new CoListJazzApi(proxy, () => options.fromRaw),
|
207
125
|
enumerable: false,
|
208
126
|
},
|
209
|
-
_raw: { value: options.fromRaw, enumerable: false },
|
210
127
|
});
|
211
128
|
}
|
212
129
|
|
213
|
-
return
|
130
|
+
return proxy;
|
214
131
|
}
|
215
132
|
|
216
133
|
/**
|
@@ -233,6 +150,7 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
233
150
|
* ```
|
234
151
|
*
|
235
152
|
* @category Creation
|
153
|
+
* @deprecated Use `co.list(...).create` instead.
|
236
154
|
**/
|
237
155
|
static create<L extends CoList>(
|
238
156
|
this: CoValueClass<L>,
|
@@ -246,159 +164,41 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
246
164
|
| Group,
|
247
165
|
) {
|
248
166
|
const { owner, uniqueness } = parseCoValueCreateOptions(options);
|
249
|
-
const instance = new this(
|
250
|
-
const raw = owner._raw.createList(
|
251
|
-
toRawItems(items, instance._schema[ItemsSym], owner),
|
252
|
-
null,
|
253
|
-
"private",
|
254
|
-
uniqueness,
|
255
|
-
);
|
167
|
+
const instance = new this();
|
256
168
|
|
257
169
|
Object.defineProperties(instance, {
|
258
|
-
|
259
|
-
value: raw
|
170
|
+
$jazz: {
|
171
|
+
value: new CoListJazzApi(instance, () => raw),
|
260
172
|
enumerable: false,
|
261
173
|
},
|
262
|
-
_raw: { value: raw, enumerable: false },
|
263
174
|
});
|
264
175
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
push(...items: Item[]): number {
|
269
|
-
this._raw.appendItems(
|
270
|
-
toRawItems(items, this._schema[ItemsSym], this._owner),
|
271
|
-
undefined,
|
176
|
+
const raw = owner.$jazz.raw.createList(
|
177
|
+
toRawItems(items, instance.$jazz.schema[ItemsSym], owner),
|
178
|
+
null,
|
272
179
|
"private",
|
180
|
+
uniqueness,
|
273
181
|
);
|
274
182
|
|
275
|
-
return
|
276
|
-
}
|
277
|
-
|
278
|
-
unshift(...items: Item[]): number {
|
279
|
-
for (const item of toRawItems(
|
280
|
-
items as Item[],
|
281
|
-
this._schema[ItemsSym],
|
282
|
-
this._owner,
|
283
|
-
)) {
|
284
|
-
this._raw.prepend(item);
|
285
|
-
}
|
286
|
-
|
287
|
-
return this._raw.entries().length;
|
288
|
-
}
|
289
|
-
|
290
|
-
pop(): Item | undefined {
|
291
|
-
const last = this[this.length - 1];
|
292
|
-
|
293
|
-
this._raw.delete(this.length - 1);
|
294
|
-
|
295
|
-
return last;
|
296
|
-
}
|
297
|
-
|
298
|
-
shift(): Item | undefined {
|
299
|
-
const first = this[0];
|
300
|
-
|
301
|
-
this._raw.delete(0);
|
302
|
-
|
303
|
-
return first;
|
304
|
-
}
|
305
|
-
|
306
|
-
/**
|
307
|
-
* Splice the `CoList` at a given index.
|
308
|
-
*
|
309
|
-
* @param start - The index to start the splice.
|
310
|
-
* @param deleteCount - The number of items to delete.
|
311
|
-
* @param items - The items to insert.
|
312
|
-
*/
|
313
|
-
splice(start: number, deleteCount: number, ...items: Item[]): Item[] {
|
314
|
-
const deleted = this.slice(start, start + deleteCount);
|
315
|
-
|
316
|
-
for (
|
317
|
-
let idxToDelete = start + deleteCount - 1;
|
318
|
-
idxToDelete >= start;
|
319
|
-
idxToDelete--
|
320
|
-
) {
|
321
|
-
this._raw.delete(idxToDelete);
|
322
|
-
}
|
323
|
-
|
324
|
-
const rawItems = toRawItems(
|
325
|
-
items as Item[],
|
326
|
-
this._schema[ItemsSym],
|
327
|
-
this._owner,
|
328
|
-
);
|
329
|
-
|
330
|
-
// If there are no items to insert, return the deleted items
|
331
|
-
if (rawItems.length === 0) {
|
332
|
-
return deleted;
|
333
|
-
}
|
334
|
-
|
335
|
-
// Fast path for single item insertion
|
336
|
-
if (rawItems.length === 1) {
|
337
|
-
const item = rawItems[0];
|
338
|
-
if (item === undefined) return deleted;
|
339
|
-
if (start === 0) {
|
340
|
-
this._raw.prepend(item);
|
341
|
-
} else {
|
342
|
-
this._raw.append(item, Math.max(start - 1, 0));
|
343
|
-
}
|
344
|
-
return deleted;
|
345
|
-
}
|
346
|
-
|
347
|
-
// Handle multiple items
|
348
|
-
if (start === 0) {
|
349
|
-
// Iterate in reverse order without creating a new array
|
350
|
-
for (let i = rawItems.length - 1; i >= 0; i--) {
|
351
|
-
const item = rawItems[i];
|
352
|
-
if (item === undefined) continue;
|
353
|
-
this._raw.prepend(item);
|
354
|
-
}
|
355
|
-
} else {
|
356
|
-
let appendAfter = Math.max(start - 1, 0);
|
357
|
-
for (const item of rawItems) {
|
358
|
-
if (item === undefined) continue;
|
359
|
-
this._raw.append(item, appendAfter);
|
360
|
-
appendAfter++;
|
361
|
-
}
|
362
|
-
}
|
363
|
-
|
364
|
-
return deleted;
|
365
|
-
}
|
366
|
-
|
367
|
-
/**
|
368
|
-
* Modify the `CoList` to match another list, where the changes are managed internally.
|
369
|
-
*
|
370
|
-
* @param result - The resolved list of items.
|
371
|
-
*/
|
372
|
-
applyDiff(result: Item[]) {
|
373
|
-
const current = this._raw.asArray() as Item[];
|
374
|
-
const comparator = isRefEncoded(this._schema[ItemsSym])
|
375
|
-
? (aIdx: number, bIdx: number) => {
|
376
|
-
return (
|
377
|
-
(current[aIdx] as CoValue)?.id === (result[bIdx] as CoValue)?.id
|
378
|
-
);
|
379
|
-
}
|
380
|
-
: undefined;
|
381
|
-
|
382
|
-
const patches = [...calcPatch(current, result, comparator)];
|
383
|
-
for (const [from, to, insert] of patches.reverse()) {
|
384
|
-
this.splice(from, to - from, ...insert);
|
385
|
-
}
|
183
|
+
return instance;
|
386
184
|
}
|
387
185
|
|
388
186
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
389
187
|
toJSON(_key?: string, seenAbove?: ID<CoValue>[]): any[] {
|
390
|
-
const itemDescriptor = this.
|
188
|
+
const itemDescriptor = this.$jazz.schema[ItemsSym] as Schema;
|
391
189
|
if (itemDescriptor === "json") {
|
392
|
-
return this.
|
190
|
+
return this.$jazz.raw.asArray();
|
393
191
|
} else if ("encoded" in itemDescriptor) {
|
394
|
-
return this.
|
192
|
+
return this.$jazz.raw
|
193
|
+
.asArray()
|
194
|
+
.map((e) => itemDescriptor.encoded.encode(e));
|
395
195
|
} else if (isRefEncoded(itemDescriptor)) {
|
396
196
|
return this.map((item, idx) =>
|
397
|
-
seenAbove?.includes((item as CoValue)
|
398
|
-
? { _circular: (item as CoValue).id }
|
197
|
+
seenAbove?.includes((item as CoValue)?.$jazz.id)
|
198
|
+
? { _circular: (item as CoValue).$jazz.id }
|
399
199
|
: (item as unknown as CoValue)?.toJSON(idx + "", [
|
400
200
|
...(seenAbove || []),
|
401
|
-
this.id,
|
201
|
+
this.$jazz.id,
|
402
202
|
]),
|
403
203
|
);
|
404
204
|
} else {
|
@@ -422,7 +222,7 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
422
222
|
static schema<V extends CoList>(
|
423
223
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
424
224
|
this: { new (...args: any): V } & typeof CoList,
|
425
|
-
def: { [ItemsSym]: V["
|
225
|
+
def: { [ItemsSym]: V["$jazz"]["schema"][ItemsSym] },
|
426
226
|
) {
|
427
227
|
this._schema ||= {};
|
428
228
|
Object.assign(this._schema, def);
|
@@ -449,6 +249,7 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
449
249
|
* ```
|
450
250
|
*
|
451
251
|
* @category Subscription & Loading
|
252
|
+
* @deprecated Use `co.list(...).load` instead.
|
452
253
|
*/
|
453
254
|
static load<L extends CoList, const R extends RefsToResolve<L> = true>(
|
454
255
|
this: CoValueClass<L>,
|
@@ -488,6 +289,7 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
488
289
|
* ```
|
489
290
|
*
|
490
291
|
* @category Subscription & Loading
|
292
|
+
* @deprecated Use `co.list(...).subscribe` instead.
|
491
293
|
*/
|
492
294
|
static subscribe<L extends CoList, const R extends RefsToResolve<L> = true>(
|
493
295
|
this: CoValueClass<L>,
|
@@ -509,53 +311,6 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
509
311
|
return subscribeToCoValueWithoutMe<L, R>(this, id, options, listener);
|
510
312
|
}
|
511
313
|
|
512
|
-
/**
|
513
|
-
* Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
|
514
|
-
*
|
515
|
-
* Works like `CoList.load()`, but you don't need to pass the ID or the account to load as again.
|
516
|
-
*
|
517
|
-
* @category Subscription & Loading
|
518
|
-
*/
|
519
|
-
ensureLoaded<L extends CoList, const R extends RefsToResolve<L>>(
|
520
|
-
this: L,
|
521
|
-
options: { resolve: RefsToResolveStrict<L, R> },
|
522
|
-
): Promise<Resolved<L, R>> {
|
523
|
-
return ensureCoValueLoaded(this, options);
|
524
|
-
}
|
525
|
-
|
526
|
-
/**
|
527
|
-
* Given an already loaded `CoList`, subscribe to updates to the `CoList` and ensure that items are loaded to the specified depth.
|
528
|
-
*
|
529
|
-
* Works like `CoList.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
530
|
-
*
|
531
|
-
* Returns an unsubscribe function that you should call when you no longer need updates.
|
532
|
-
*
|
533
|
-
* @category Subscription & Loading
|
534
|
-
**/
|
535
|
-
subscribe<L extends CoList, const R extends RefsToResolve<L> = true>(
|
536
|
-
this: L,
|
537
|
-
listener: (value: Resolved<L, R>, unsubscribe: () => void) => void,
|
538
|
-
): () => void;
|
539
|
-
subscribe<L extends CoList, const R extends RefsToResolve<L> = true>(
|
540
|
-
this: L,
|
541
|
-
options: { resolve?: RefsToResolveStrict<L, R> },
|
542
|
-
listener: (value: Resolved<L, R>, unsubscribe: () => void) => void,
|
543
|
-
): () => void;
|
544
|
-
subscribe<L extends CoList, const R extends RefsToResolve<L>>(
|
545
|
-
this: L,
|
546
|
-
...args: SubscribeRestArgs<L, R>
|
547
|
-
): () => void {
|
548
|
-
const { options, listener } = parseSubscribeRestArgs(args);
|
549
|
-
return subscribeToExistingCoValue(this, options, listener);
|
550
|
-
}
|
551
|
-
|
552
|
-
/** @category Type Helpers */
|
553
|
-
castAs<Cl extends CoValueClass & CoValueFromRaw<CoValue>>(
|
554
|
-
cl: Cl,
|
555
|
-
): InstanceType<Cl> {
|
556
|
-
return cl.fromRaw(this._raw) as InstanceType<Cl>;
|
557
|
-
}
|
558
|
-
|
559
314
|
/** @deprecated Use `CoList.upsertUnique` and `CoList.loadUnique` instead. */
|
560
315
|
static findUnique<L extends CoList>(
|
561
316
|
this: CoValueClass<L>,
|
@@ -585,7 +340,7 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
585
340
|
uniqueness: unique,
|
586
341
|
};
|
587
342
|
const crypto =
|
588
|
-
as
|
343
|
+
as[TypeSym] === "Anonymous" ? as.node.crypto : as.$jazz.localNode.crypto;
|
589
344
|
return cojsonInternals.idforHeader(header, crypto) as ID<L>;
|
590
345
|
}
|
591
346
|
|
@@ -623,12 +378,12 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
623
378
|
): Promise<Resolved<L, R> | null> {
|
624
379
|
const listId = CoList._findUnique(
|
625
380
|
options.unique,
|
626
|
-
options.owner.id,
|
627
|
-
options.owner.
|
381
|
+
options.owner.$jazz.id,
|
382
|
+
options.owner.$jazz.loadedAs,
|
628
383
|
);
|
629
384
|
let list: Resolved<L, R> | null = await loadCoValueWithoutMe(this, listId, {
|
630
385
|
...options,
|
631
|
-
loadAs: options.owner.
|
386
|
+
loadAs: options.owner.$jazz.loadedAs,
|
632
387
|
skipRetry: true,
|
633
388
|
});
|
634
389
|
if (!list) {
|
@@ -637,12 +392,12 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
637
392
|
unique: options.unique,
|
638
393
|
}) as Resolved<L, R>;
|
639
394
|
} else {
|
640
|
-
(list as L).applyDiff(options.value);
|
395
|
+
(list as L).$jazz.applyDiff(options.value);
|
641
396
|
}
|
642
397
|
|
643
398
|
return await loadCoValueWithoutMe(this, listId, {
|
644
399
|
...options,
|
645
|
-
loadAs: options.owner.
|
400
|
+
loadAs: options.owner.$jazz.loadedAs,
|
646
401
|
skipRetry: true,
|
647
402
|
});
|
648
403
|
}
|
@@ -670,13 +425,453 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
670
425
|
);
|
671
426
|
}
|
672
427
|
|
428
|
+
// Override mutation methods defined on Array, as CoLists aren't meant to be mutated directly
|
429
|
+
/**
|
430
|
+
* @deprecated Use `.$jazz.push` instead.
|
431
|
+
*/
|
432
|
+
override push(...items: never): never {
|
433
|
+
throw new Error(
|
434
|
+
"Cannot mutate a CoList directly. Use `.$jazz.push` instead.",
|
435
|
+
);
|
436
|
+
}
|
437
|
+
/**
|
438
|
+
* @deprecated Use `.$jazz.unshift` instead.
|
439
|
+
*/
|
440
|
+
override unshift(...items: never): number {
|
441
|
+
throw new Error(
|
442
|
+
"Cannot mutate a CoList directly. Use `.$jazz.unshift` instead.",
|
443
|
+
);
|
444
|
+
}
|
445
|
+
/**
|
446
|
+
* @deprecated Use `.$jazz.pop` instead.
|
447
|
+
*/
|
448
|
+
// @ts-expect-error
|
449
|
+
override pop(value: never): never {
|
450
|
+
throw new Error(
|
451
|
+
"Cannot mutate a CoList directly. Use `.$jazz.pop` instead.",
|
452
|
+
);
|
453
|
+
}
|
454
|
+
/**
|
455
|
+
* @deprecated Use `.$jazz.shift` instead.
|
456
|
+
*/
|
457
|
+
// @ts-expect-error
|
458
|
+
override shift(value: never): never {
|
459
|
+
throw new Error(
|
460
|
+
"Cannot mutate a CoList directly. Use `.$jazz.shift` instead.",
|
461
|
+
);
|
462
|
+
}
|
463
|
+
/**
|
464
|
+
* @deprecated Use `.$jazz.splice` instead.
|
465
|
+
*/
|
466
|
+
override splice(start: never, deleteCount: never, ...items: never): never {
|
467
|
+
throw new Error(
|
468
|
+
"Cannot mutate a CoList directly. Use `.$jazz.splice` instead.",
|
469
|
+
);
|
470
|
+
}
|
471
|
+
/**
|
472
|
+
* @deprecated Use `.$jazz.set` instead.
|
473
|
+
*/
|
474
|
+
override copyWithin(target: never, start: never, end: never): never {
|
475
|
+
throw new Error(
|
476
|
+
"Cannot mutate a CoList directly. Use `.$jazz.set` instead.",
|
477
|
+
);
|
478
|
+
}
|
479
|
+
/**
|
480
|
+
* @deprecated Use `.$jazz.set` instead.
|
481
|
+
*/
|
482
|
+
override fill(value: never, start?: never, end?: never): never {
|
483
|
+
throw new Error(
|
484
|
+
"Cannot mutate a CoList directly. Use `.$jazz.set` instead.",
|
485
|
+
);
|
486
|
+
}
|
487
|
+
/**
|
488
|
+
* @deprecated Use `.toReversed` if you want a reversed copy, or `.$jazz.set` to mutate the CoList.
|
489
|
+
*/
|
490
|
+
// @ts-expect-error
|
491
|
+
override reverse(value: never): never {
|
492
|
+
throw new Error(
|
493
|
+
"Cannot mutate a CoList directly. Use `.toReversed` if you want a reversed copy, or `.$jazz.set` to mutate the CoList.",
|
494
|
+
);
|
495
|
+
}
|
496
|
+
/**
|
497
|
+
* @deprecated Use `.toSorted()` if you want a sorted copy, or `.$jazz.set` to mutate the CoList.
|
498
|
+
*/
|
499
|
+
override sort(compareFn?: never): never {
|
500
|
+
throw new Error(
|
501
|
+
"Cannot mutate a CoList directly. Use `.toSorted` if you want a sorted copy, or `.$jazz.set` to mutate the CoList.",
|
502
|
+
);
|
503
|
+
}
|
504
|
+
}
|
505
|
+
|
506
|
+
/** @internal */
|
507
|
+
type CoListItem<L> = L extends CoList<unknown> ? L[number] : never;
|
508
|
+
|
509
|
+
export class CoListJazzApi<L extends CoList> extends CoValueJazzApi<L> {
|
510
|
+
constructor(
|
511
|
+
private coList: L,
|
512
|
+
private getRaw: () => RawCoList,
|
513
|
+
) {
|
514
|
+
super(coList);
|
515
|
+
}
|
516
|
+
|
517
|
+
/**
|
518
|
+
* The ID of this `CoList`
|
519
|
+
* @category Content
|
520
|
+
*/
|
521
|
+
get id(): ID<L> {
|
522
|
+
return this.raw.id;
|
523
|
+
}
|
524
|
+
|
525
|
+
/** @category Collaboration */
|
526
|
+
get owner(): Group {
|
527
|
+
return getCoValueOwner(this.coList);
|
528
|
+
}
|
529
|
+
|
530
|
+
set(index: number, value: CoFieldInit<CoListItem<L>>): void {
|
531
|
+
const itemDescriptor = this.schema[ItemsSym];
|
532
|
+
const rawValue = toRawItems([value], itemDescriptor, this.owner)[0]!;
|
533
|
+
if (rawValue === null && !itemDescriptor.optional) {
|
534
|
+
throw new Error(`Cannot set required reference ${index} to undefined`);
|
535
|
+
}
|
536
|
+
this.raw.replace(index, rawValue);
|
537
|
+
}
|
538
|
+
|
539
|
+
/**
|
540
|
+
* Appends new elements to the end of an array, and returns the new length of the array.
|
541
|
+
* @param items New elements to add to the array.
|
542
|
+
*
|
543
|
+
* @category Content
|
544
|
+
*/
|
545
|
+
push(...items: CoFieldInit<CoListItem<L>>[]): number {
|
546
|
+
this.raw.appendItems(
|
547
|
+
toRawItems(items, this.schema[ItemsSym], this.owner),
|
548
|
+
undefined,
|
549
|
+
"private",
|
550
|
+
);
|
551
|
+
|
552
|
+
return this.raw.entries().length;
|
553
|
+
}
|
554
|
+
|
555
|
+
/**
|
556
|
+
* Inserts new elements at the start of an array, and returns the new length of the array.
|
557
|
+
* @param items Elements to insert at the start of the array.
|
558
|
+
*
|
559
|
+
* @category Content
|
560
|
+
*/
|
561
|
+
unshift(...items: CoFieldInit<CoListItem<L>>[]): number {
|
562
|
+
for (const item of toRawItems(
|
563
|
+
items as CoFieldInit<CoListItem<L>>[],
|
564
|
+
this.schema[ItemsSym],
|
565
|
+
this.owner,
|
566
|
+
)) {
|
567
|
+
this.raw.prepend(item);
|
568
|
+
}
|
569
|
+
|
570
|
+
return this.raw.entries().length;
|
571
|
+
}
|
572
|
+
|
573
|
+
/**
|
574
|
+
* Removes the last element from an array and returns it.
|
575
|
+
* If the array is empty, undefined is returned and the array is not modified.
|
576
|
+
*
|
577
|
+
* @category Content
|
578
|
+
*/
|
579
|
+
pop(): CoListItem<L> | undefined {
|
580
|
+
const last = this.coList[this.coList.length - 1];
|
581
|
+
|
582
|
+
this.raw.delete(this.coList.length - 1);
|
583
|
+
|
584
|
+
return last;
|
585
|
+
}
|
586
|
+
|
587
|
+
/**
|
588
|
+
* Removes the first element from an array and returns it.
|
589
|
+
* If the array is empty, undefined is returned and the array is not modified.
|
590
|
+
*
|
591
|
+
* @category Content
|
592
|
+
*/
|
593
|
+
shift(): CoListItem<L> | undefined {
|
594
|
+
const first = this.coList[0];
|
595
|
+
|
596
|
+
this.raw.delete(0);
|
597
|
+
|
598
|
+
return first;
|
599
|
+
}
|
600
|
+
|
601
|
+
/**
|
602
|
+
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
|
603
|
+
* @param start The zero-based location in the array from which to start removing elements.
|
604
|
+
* @param deleteCount The number of elements to remove.
|
605
|
+
* @param items Elements to insert into the array in place of the deleted elements.
|
606
|
+
* @returns An array containing the elements that were deleted.
|
607
|
+
*
|
608
|
+
* @category Content
|
609
|
+
*/
|
610
|
+
splice(
|
611
|
+
start: number,
|
612
|
+
deleteCount: number,
|
613
|
+
...items: CoFieldInit<CoListItem<L>>[]
|
614
|
+
): CoListItem<L>[] {
|
615
|
+
const deleted = this.coList.slice(start, start + deleteCount);
|
616
|
+
|
617
|
+
for (
|
618
|
+
let idxToDelete = start + deleteCount - 1;
|
619
|
+
idxToDelete >= start;
|
620
|
+
idxToDelete--
|
621
|
+
) {
|
622
|
+
this.raw.delete(idxToDelete);
|
623
|
+
}
|
624
|
+
|
625
|
+
const rawItems = toRawItems(
|
626
|
+
items as CoListItem<L>[],
|
627
|
+
this.schema[ItemsSym],
|
628
|
+
this.owner,
|
629
|
+
);
|
630
|
+
|
631
|
+
// If there are no items to insert, return the deleted items
|
632
|
+
if (rawItems.length === 0) {
|
633
|
+
return deleted;
|
634
|
+
}
|
635
|
+
|
636
|
+
// Fast path for single item insertion
|
637
|
+
if (rawItems.length === 1) {
|
638
|
+
const item = rawItems[0];
|
639
|
+
if (item === undefined) return deleted;
|
640
|
+
if (start === 0) {
|
641
|
+
this.raw.prepend(item);
|
642
|
+
} else {
|
643
|
+
this.raw.append(item, Math.max(start - 1, 0));
|
644
|
+
}
|
645
|
+
return deleted;
|
646
|
+
}
|
647
|
+
|
648
|
+
// Handle multiple items
|
649
|
+
if (start === 0) {
|
650
|
+
// Iterate in reverse order without creating a new array
|
651
|
+
for (let i = rawItems.length - 1; i >= 0; i--) {
|
652
|
+
const item = rawItems[i];
|
653
|
+
if (item === undefined) continue;
|
654
|
+
this.raw.prepend(item);
|
655
|
+
}
|
656
|
+
} else {
|
657
|
+
let appendAfter = Math.max(start - 1, 0);
|
658
|
+
for (const item of rawItems) {
|
659
|
+
if (item === undefined) continue;
|
660
|
+
this.raw.append(item, appendAfter);
|
661
|
+
appendAfter++;
|
662
|
+
}
|
663
|
+
}
|
664
|
+
|
665
|
+
return deleted;
|
666
|
+
}
|
667
|
+
|
668
|
+
/**
|
669
|
+
* Removes the elements at the specified indices from the array.
|
670
|
+
* @param indices The indices of the elements to remove.
|
671
|
+
* @returns The removed elements.
|
672
|
+
*
|
673
|
+
* @category Content
|
674
|
+
*/
|
675
|
+
remove(...indices: number[]): CoListItem<L>[];
|
676
|
+
/**
|
677
|
+
* Removes the elements matching the predicate from the array.
|
678
|
+
* @param predicate The predicate to match the elements to remove.
|
679
|
+
* @returns The removed elements.
|
680
|
+
*
|
681
|
+
* @category Content
|
682
|
+
*/
|
683
|
+
remove(
|
684
|
+
predicate: (item: CoListItem<L>, index: number, coList: L) => boolean,
|
685
|
+
): CoListItem<L>[];
|
686
|
+
remove(
|
687
|
+
...args: (
|
688
|
+
| number
|
689
|
+
| ((item: CoListItem<L>, index: number, coList: L) => boolean)
|
690
|
+
)[]
|
691
|
+
): CoListItem<L>[] {
|
692
|
+
const predicate = args[0] instanceof Function ? args[0] : undefined;
|
693
|
+
let indices: number[] = [];
|
694
|
+
if (predicate) {
|
695
|
+
for (let i = 0; i < this.coList.length; i++) {
|
696
|
+
if (predicate(this.coList[i], i, this.coList)) {
|
697
|
+
indices.push(i);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
} else {
|
701
|
+
indices = (args as number[])
|
702
|
+
.filter((index) => index >= 0 && index < this.coList.length)
|
703
|
+
.sort((a, b) => a - b);
|
704
|
+
}
|
705
|
+
const deletedItems = indices.map((index) => this.coList[index]);
|
706
|
+
for (const index of indices.reverse()) {
|
707
|
+
this.raw.delete(index);
|
708
|
+
}
|
709
|
+
return deletedItems;
|
710
|
+
}
|
711
|
+
|
712
|
+
/**
|
713
|
+
* Retains only the elements matching the predicate from the array.
|
714
|
+
* @param predicate The predicate to match the elements to retain.
|
715
|
+
* @returns The removed elements.
|
716
|
+
*
|
717
|
+
* @category Content
|
718
|
+
*/
|
719
|
+
retain(
|
720
|
+
predicate: (item: CoListItem<L>, index: number, coList: L) => boolean,
|
721
|
+
): CoListItem<L>[] {
|
722
|
+
return this.remove((...args) => !predicate(...args));
|
723
|
+
}
|
724
|
+
|
725
|
+
/**
|
726
|
+
* Modify the `CoList` to match another list, where the changes are managed internally.
|
727
|
+
*
|
728
|
+
* Changes are detected using `Object.is` for non-collaborative values and `$jazz.id` for collaborative values.
|
729
|
+
*
|
730
|
+
* @param result - The resolved list of items. For collaborative values, both CoValues and JSON values are supported.
|
731
|
+
* @returns The modified CoList.
|
732
|
+
*
|
733
|
+
* @category Content
|
734
|
+
*/
|
735
|
+
applyDiff(result: CoFieldInit<CoListItem<L>>[]): L {
|
736
|
+
const current = this.raw.asArray() as CoFieldInit<CoListItem<L>>[];
|
737
|
+
const comparator = isRefEncoded(this.schema[ItemsSym])
|
738
|
+
? (aIdx: number, bIdx: number) => {
|
739
|
+
const oldCoValueId = (current[aIdx] as CoValue)?.$jazz?.id;
|
740
|
+
const newCoValueId = (result[bIdx] as CoValue)?.$jazz?.id;
|
741
|
+
const isSame =
|
742
|
+
!!oldCoValueId && !!newCoValueId && oldCoValueId === newCoValueId;
|
743
|
+
return isSame;
|
744
|
+
}
|
745
|
+
: undefined;
|
746
|
+
|
747
|
+
const patches = [...calcPatch(current, result, comparator)];
|
748
|
+
for (const [from, to, insert] of patches.reverse()) {
|
749
|
+
this.splice(from, to - from, ...insert);
|
750
|
+
}
|
751
|
+
return this.coList;
|
752
|
+
}
|
753
|
+
|
754
|
+
/**
|
755
|
+
* Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
|
756
|
+
*
|
757
|
+
* Works like `CoList.load()`, but you don't need to pass the ID or the account to load as again.
|
758
|
+
*
|
759
|
+
* @category Subscription & Loading
|
760
|
+
*/
|
761
|
+
ensureLoaded<L extends CoList, const R extends RefsToResolve<L>>(
|
762
|
+
this: CoListJazzApi<L>,
|
763
|
+
options: { resolve: RefsToResolveStrict<L, R> },
|
764
|
+
): Promise<Resolved<L, R>> {
|
765
|
+
return ensureCoValueLoaded(this.coList, options);
|
766
|
+
}
|
767
|
+
|
768
|
+
/**
|
769
|
+
* Given an already loaded `CoList`, subscribe to updates to the `CoList` and ensure that items are loaded to the specified depth.
|
770
|
+
*
|
771
|
+
* Works like `CoList.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
772
|
+
*
|
773
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
774
|
+
*
|
775
|
+
* @category Subscription & Loading
|
776
|
+
**/
|
777
|
+
subscribe<L extends CoList, const R extends RefsToResolve<L> = true>(
|
778
|
+
this: CoListJazzApi<L>,
|
779
|
+
listener: (value: Resolved<L, R>, unsubscribe: () => void) => void,
|
780
|
+
): () => void;
|
781
|
+
subscribe<L extends CoList, const R extends RefsToResolve<L> = true>(
|
782
|
+
this: CoListJazzApi<L>,
|
783
|
+
options: { resolve?: RefsToResolveStrict<L, R> },
|
784
|
+
listener: (value: Resolved<L, R>, unsubscribe: () => void) => void,
|
785
|
+
): () => void;
|
786
|
+
subscribe<L extends CoList, const R extends RefsToResolve<L>>(
|
787
|
+
this: CoListJazzApi<L>,
|
788
|
+
...args: SubscribeRestArgs<L, R>
|
789
|
+
): () => void {
|
790
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
791
|
+
return subscribeToExistingCoValue(this.coList, options, listener);
|
792
|
+
}
|
793
|
+
|
673
794
|
/**
|
674
795
|
* Wait for the `CoList` to be uploaded to the other peers.
|
675
796
|
*
|
676
797
|
* @category Subscription & Loading
|
677
798
|
*/
|
678
|
-
waitForSync(options?: { timeout?: number }) {
|
679
|
-
|
799
|
+
async waitForSync(options?: { timeout?: number }): Promise<void> {
|
800
|
+
await this.raw.core.waitForSync(options);
|
801
|
+
}
|
802
|
+
|
803
|
+
/**
|
804
|
+
* Get the descriptor for the items in the `CoList`
|
805
|
+
* @internal
|
806
|
+
*/
|
807
|
+
getItemsDescriptor(): Schema | undefined {
|
808
|
+
return this.schema[ItemsSym];
|
809
|
+
}
|
810
|
+
|
811
|
+
/**
|
812
|
+
* If a `CoList`'s items are a `coField.ref(...)`, you can use `coList.$jazz.refs[i]` to access
|
813
|
+
* the `Ref` instead of the potentially loaded/null value.
|
814
|
+
*
|
815
|
+
* This allows you to always get the ID or load the value manually.
|
816
|
+
*
|
817
|
+
* @example
|
818
|
+
* ```ts
|
819
|
+
* animals.$jazz.refs[0].id; // => ID<Animal>
|
820
|
+
* animals.$jazz.refs[0].value;
|
821
|
+
* // => Animal | null
|
822
|
+
* const animal = await animals.$jazz.refs[0].load();
|
823
|
+
* ```
|
824
|
+
*
|
825
|
+
* @category Content
|
826
|
+
**/
|
827
|
+
get refs(): {
|
828
|
+
[idx: number]: Exclude<CoListItem<L>, null> extends CoValue
|
829
|
+
? Ref<Exclude<CoListItem<L>, null>>
|
830
|
+
: never;
|
831
|
+
} & {
|
832
|
+
length: number;
|
833
|
+
[Symbol.iterator](): IterableIterator<
|
834
|
+
Exclude<CoListItem<L>, null> extends CoValue
|
835
|
+
? Ref<Exclude<CoListItem<L>, null>>
|
836
|
+
: never
|
837
|
+
>;
|
838
|
+
} {
|
839
|
+
return makeRefs<number>(
|
840
|
+
this.coList,
|
841
|
+
(idx) => this.raw.get(idx) as unknown as ID<CoValue>,
|
842
|
+
() => Array.from({ length: this.raw.entries().length }, (_, idx) => idx),
|
843
|
+
this.loadedAs,
|
844
|
+
(_idx) => this.schema[ItemsSym] as RefEncoded<CoValue>,
|
845
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
846
|
+
) as any;
|
847
|
+
}
|
848
|
+
|
849
|
+
/**
|
850
|
+
* Get the edits made to the CoList.
|
851
|
+
*
|
852
|
+
* @category Collaboration
|
853
|
+
*/
|
854
|
+
getEdits(): {
|
855
|
+
[idx: number]: {
|
856
|
+
value?: CoListItem<L>;
|
857
|
+
ref?: CoListItem<L> extends CoValue ? Ref<CoListItem<L>> : never;
|
858
|
+
by: Account | null;
|
859
|
+
madeAt: Date;
|
860
|
+
};
|
861
|
+
} {
|
862
|
+
throw new Error("Not implemented");
|
863
|
+
}
|
864
|
+
|
865
|
+
/** @internal */
|
866
|
+
get raw(): RawCoList {
|
867
|
+
return this.getRaw();
|
868
|
+
}
|
869
|
+
|
870
|
+
/** @internal */
|
871
|
+
get schema(): {
|
872
|
+
[ItemsSym]: SchemaFor<CoListItem<L>> | any;
|
873
|
+
} {
|
874
|
+
return (this.coList.constructor as typeof CoList)._schema;
|
680
875
|
}
|
681
876
|
}
|
682
877
|
|
@@ -690,8 +885,8 @@ export class CoList<out Item = any> extends Array<Item> implements CoValue {
|
|
690
885
|
function toRawItems<Item>(
|
691
886
|
items: Item[],
|
692
887
|
itemDescriptor: Schema,
|
693
|
-
owner:
|
694
|
-
) {
|
888
|
+
owner: Group,
|
889
|
+
): JsonValue[] {
|
695
890
|
let rawItems: JsonValue[] = [];
|
696
891
|
if (itemDescriptor === "json") {
|
697
892
|
rawItems = items as JsonValue[];
|
@@ -699,15 +894,17 @@ function toRawItems<Item>(
|
|
699
894
|
rawItems = items?.map((e) => itemDescriptor.encoded.encode(e));
|
700
895
|
} else if (isRefEncoded(itemDescriptor)) {
|
701
896
|
rawItems = items?.map((value) => {
|
702
|
-
if (value == null)
|
703
|
-
|
897
|
+
if (value == null) {
|
898
|
+
return null;
|
899
|
+
}
|
900
|
+
let refId = (value as unknown as CoValue).$jazz?.id;
|
704
901
|
if (!refId) {
|
705
902
|
const coValue = instantiateRefEncodedWithInit(
|
706
903
|
itemDescriptor,
|
707
904
|
value,
|
708
905
|
owner,
|
709
906
|
);
|
710
|
-
refId = coValue.id;
|
907
|
+
refId = coValue.$jazz.id;
|
711
908
|
}
|
712
909
|
return refId;
|
713
910
|
});
|
@@ -720,8 +917,8 @@ function toRawItems<Item>(
|
|
720
917
|
const CoListProxyHandler: ProxyHandler<CoList> = {
|
721
918
|
get(target, key, receiver) {
|
722
919
|
if (typeof key === "string" && !isNaN(+key)) {
|
723
|
-
const itemDescriptor = target.
|
724
|
-
const rawValue = target.
|
920
|
+
const itemDescriptor = target.$jazz.schema[ItemsSym] as Schema;
|
921
|
+
const rawValue = target.$jazz.raw.get(Number(key));
|
725
922
|
if (itemDescriptor === "json") {
|
726
923
|
return rawValue;
|
727
924
|
} else if ("encoded" in itemDescriptor) {
|
@@ -734,7 +931,7 @@ const CoListProxyHandler: ProxyHandler<CoList> = {
|
|
734
931
|
: accessChildByKey(target, rawValue as string, key);
|
735
932
|
}
|
736
933
|
} else if (key === "length") {
|
737
|
-
return target.
|
934
|
+
return target.$jazz.raw.entries().length;
|
738
935
|
} else {
|
739
936
|
return Reflect.get(target, key, receiver);
|
740
937
|
}
|
@@ -747,31 +944,7 @@ const CoListProxyHandler: ProxyHandler<CoList> = {
|
|
747
944
|
return true;
|
748
945
|
}
|
749
946
|
if (typeof key === "string" && !isNaN(+key)) {
|
750
|
-
|
751
|
-
let rawValue;
|
752
|
-
if (itemDescriptor === "json") {
|
753
|
-
rawValue = value;
|
754
|
-
} else if ("encoded" in itemDescriptor) {
|
755
|
-
rawValue = itemDescriptor.encoded.encode(value);
|
756
|
-
} else if (isRefEncoded(itemDescriptor)) {
|
757
|
-
if (value === undefined) {
|
758
|
-
if (itemDescriptor.optional) {
|
759
|
-
rawValue = null;
|
760
|
-
} else {
|
761
|
-
throw new Error(
|
762
|
-
`Cannot set required reference ${key} to undefined`,
|
763
|
-
);
|
764
|
-
}
|
765
|
-
} else if (value?.id) {
|
766
|
-
rawValue = value.id;
|
767
|
-
} else {
|
768
|
-
throw new Error(
|
769
|
-
`Cannot set reference ${key} to a non-CoValue. Got ${value}`,
|
770
|
-
);
|
771
|
-
}
|
772
|
-
}
|
773
|
-
target._raw.replace(Number(key), rawValue);
|
774
|
-
return true;
|
947
|
+
throw Error("Cannot update a CoList directly. Use `$jazz.set` instead.");
|
775
948
|
} else {
|
776
949
|
return Reflect.set(target, key, value, receiver);
|
777
950
|
}
|
@@ -793,7 +966,7 @@ const CoListProxyHandler: ProxyHandler<CoList> = {
|
|
793
966
|
},
|
794
967
|
has(target, key) {
|
795
968
|
if (typeof key === "string" && !isNaN(+key)) {
|
796
|
-
return Number(key) < target.
|
969
|
+
return Number(key) < target.$jazz.raw.entries().length;
|
797
970
|
} else {
|
798
971
|
return Reflect.has(target, key);
|
799
972
|
}
|