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.
Files changed (228) hide show
  1. package/.svelte-kit/__package__/jazz.class.svelte.js +1 -1
  2. package/.svelte-kit/__package__/media/image.svelte +3 -9
  3. package/.svelte-kit/__package__/media/image.svelte.d.ts +1 -6
  4. package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
  5. package/.svelte-kit/__package__/media/image.types.d.ts +7 -0
  6. package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -0
  7. package/.svelte-kit/__package__/media/image.types.js +1 -0
  8. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +31 -31
  9. package/.turbo/turbo-build.log +50 -50
  10. package/CHANGELOG.md +31 -0
  11. package/dist/browser/index.js +2 -2
  12. package/dist/browser/index.js.map +1 -1
  13. package/dist/{chunk-LZOF6WP5.js → chunk-HJ3GTGY7.js} +1320 -1018
  14. package/dist/chunk-HJ3GTGY7.js.map +1 -0
  15. package/dist/index.js +18 -18
  16. package/dist/index.js.map +1 -1
  17. package/dist/inspector/{custom-element-ZSNTCECD.js → custom-element-WCY6D3QJ.js} +3 -3
  18. package/dist/inspector/{custom-element-ZSNTCECD.js.map → custom-element-WCY6D3QJ.js.map} +1 -1
  19. package/dist/inspector/index.js +1 -1
  20. package/dist/inspector/index.js.map +1 -1
  21. package/dist/inspector/register-custom-element.js +1 -1
  22. package/dist/media/{chunk-E5J3WLQW.js → chunk-KR2V6X2N.js} +14 -9
  23. package/dist/media/chunk-KR2V6X2N.js.map +1 -0
  24. package/dist/media/create-image.d.ts +6 -6
  25. package/dist/media/index.browser.d.ts +6 -6
  26. package/dist/media/index.browser.js +1 -1
  27. package/dist/media/index.d.ts +1 -1
  28. package/dist/media/index.js +1 -1
  29. package/dist/media/index.native.d.ts +6 -6
  30. package/dist/media/index.native.js +1 -1
  31. package/dist/media/utils.d.ts.map +1 -1
  32. package/dist/prosemirror/index.js +2 -2
  33. package/dist/prosemirror/index.js.map +1 -1
  34. package/dist/react/index.js +7 -5
  35. package/dist/react/index.js.map +1 -1
  36. package/dist/react-core/hooks.d.ts.map +1 -1
  37. package/dist/react-core/index.js +4658 -23
  38. package/dist/react-core/index.js.map +1 -1
  39. package/dist/react-native-core/index.js +1 -1
  40. package/dist/react-native-core/index.js.map +1 -1
  41. package/dist/svelte/jazz.class.svelte.js +1 -1
  42. package/dist/svelte/media/image.svelte +3 -9
  43. package/dist/svelte/media/image.svelte.d.ts +1 -6
  44. package/dist/svelte/media/image.svelte.d.ts.map +1 -1
  45. package/dist/svelte/media/image.types.d.ts +7 -0
  46. package/dist/svelte/media/image.types.d.ts.map +1 -0
  47. package/dist/svelte/media/image.types.js +1 -0
  48. package/dist/svelte/tests/media/image.svelte.test.js +31 -31
  49. package/dist/testing.js +18 -14
  50. package/dist/testing.js.map +1 -1
  51. package/dist/tools/coValues/CoFieldInit.d.ts +13 -0
  52. package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -0
  53. package/dist/tools/coValues/CoValueBase.d.ts +18 -15
  54. package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
  55. package/dist/tools/coValues/account.d.ts +100 -46
  56. package/dist/tools/coValues/account.d.ts.map +1 -1
  57. package/dist/tools/coValues/coFeed.d.ts +78 -62
  58. package/dist/tools/coValues/coFeed.d.ts.map +1 -1
  59. package/dist/tools/coValues/coList.d.ts +212 -99
  60. package/dist/tools/coValues/coList.d.ts.map +1 -1
  61. package/dist/tools/coValues/coMap.d.ts +200 -192
  62. package/dist/tools/coValues/coMap.d.ts.map +1 -1
  63. package/dist/tools/coValues/coPlainText.d.ts +30 -22
  64. package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
  65. package/dist/tools/coValues/deepLoading.d.ts +13 -13
  66. package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
  67. package/dist/tools/coValues/extensions/imageDef.d.ts +1 -1
  68. package/dist/tools/coValues/group.d.ts +32 -32
  69. package/dist/tools/coValues/group.d.ts.map +1 -1
  70. package/dist/tools/coValues/inbox.d.ts.map +1 -1
  71. package/dist/tools/coValues/interfaces.d.ts +18 -17
  72. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  73. package/dist/tools/coValues/profile.d.ts +6 -5
  74. package/dist/tools/coValues/profile.d.ts.map +1 -1
  75. package/dist/tools/coValues/schemaUnion.d.ts +3 -3
  76. package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
  77. package/dist/tools/exports.d.ts +1 -1
  78. package/dist/tools/exports.d.ts.map +1 -1
  79. package/dist/tools/implementation/anonymousJazzAgent.d.ts +2 -1
  80. package/dist/tools/implementation/anonymousJazzAgent.d.ts.map +1 -1
  81. package/dist/tools/implementation/schema.d.ts +5 -5
  82. package/dist/tools/implementation/schema.d.ts.map +1 -1
  83. package/dist/tools/implementation/symbols.d.ts +2 -0
  84. package/dist/tools/implementation/symbols.d.ts.map +1 -1
  85. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +2 -2
  86. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  87. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +6 -2
  88. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  89. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +8 -3
  90. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  91. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +12 -7
  92. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  93. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +13 -7
  94. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
  95. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +11 -2
  96. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
  97. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +4 -0
  98. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
  99. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +4 -0
  100. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
  101. package/dist/tools/implementation/zodSchema/typeConverters/{CoFieldInit.d.ts → CoFieldSchemaInit.d.ts} +7 -7
  102. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -0
  103. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +4 -4
  104. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
  105. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +4 -4
  106. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
  107. package/dist/tools/implementation/zodSchema/zodCo.d.ts +2 -2
  108. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  109. package/dist/tools/internal.d.ts +2 -1
  110. package/dist/tools/internal.d.ts.map +1 -1
  111. package/dist/tools/lib/migration.d.ts +1 -1
  112. package/dist/tools/lib/migration.d.ts.map +1 -1
  113. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  114. package/dist/tools/subscribe/index.d.ts +1 -1
  115. package/dist/tools/subscribe/index.d.ts.map +1 -1
  116. package/dist/tools/subscribe/utils.d.ts +2 -2
  117. package/dist/tools/subscribe/utils.d.ts.map +1 -1
  118. package/dist/tools/testing.d.ts.map +1 -1
  119. package/dist/tools/tests/utils.d.ts +2 -6
  120. package/dist/tools/tests/utils.d.ts.map +1 -1
  121. package/dist/worker/index.js +3 -3
  122. package/dist/worker/index.js.map +1 -1
  123. package/package.json +4 -4
  124. package/src/browser/auth/PasskeyAuth.ts +2 -2
  125. package/src/browser/createBrowserContext.ts +2 -2
  126. package/src/browser/tests/PasskeyAuth.test.ts +2 -2
  127. package/src/inspector/custom-element.tsx +2 -2
  128. package/src/inspector/viewer/new-app.tsx +1 -1
  129. package/src/media/create-image.test.ts +7 -7
  130. package/src/media/create-image.ts +5 -3
  131. package/src/media/index.ts +1 -1
  132. package/src/media/utils.test.ts +72 -66
  133. package/src/media/utils.ts +9 -6
  134. package/src/prosemirror/lib/plugin.ts +1 -1
  135. package/src/prosemirror/lib/sync.ts +1 -1
  136. package/src/prosemirror/tests/plugin.test.ts +4 -4
  137. package/src/react/media/image.tsx +2 -2
  138. package/src/react/tests/media/image.test.tsx +52 -32
  139. package/src/react-core/hooks.ts +11 -5
  140. package/src/react-core/tests/useAccount.test.ts +16 -22
  141. package/src/react-core/tests/useCoState.test.ts +19 -19
  142. package/src/react-core/tests/useInboxSender.test.ts +5 -2
  143. package/src/react-core/tests/usePassPhraseAuth.test.ts +6 -6
  144. package/src/react-native-core/media/image.tsx +1 -1
  145. package/src/svelte/jazz.class.svelte.ts +1 -1
  146. package/src/svelte/media/image.svelte +3 -9
  147. package/src/svelte/media/image.types.ts +7 -0
  148. package/src/svelte/tests/media/image.svelte.test.ts +34 -32
  149. package/src/tools/auth/DemoAuth.ts +2 -2
  150. package/src/tools/auth/PassphraseAuth.ts +2 -2
  151. package/src/tools/auth/clerk/index.ts +2 -2
  152. package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +1 -1
  153. package/src/tools/coValues/CoFieldInit.ts +20 -0
  154. package/src/tools/coValues/CoValueBase.ts +40 -60
  155. package/src/tools/coValues/account.ts +306 -232
  156. package/src/tools/coValues/coFeed.ts +185 -153
  157. package/src/tools/coValues/coList.ts +507 -334
  158. package/src/tools/coValues/coMap.ts +420 -286
  159. package/src/tools/coValues/coPlainText.ts +94 -110
  160. package/src/tools/coValues/deepLoading.ts +13 -13
  161. package/src/tools/coValues/group.ts +100 -114
  162. package/src/tools/coValues/inbox.ts +16 -14
  163. package/src/tools/coValues/interfaces.ts +49 -31
  164. package/src/tools/coValues/profile.ts +8 -6
  165. package/src/tools/coValues/request.ts +9 -9
  166. package/src/tools/coValues/schemaUnion.ts +11 -5
  167. package/src/tools/exports.ts +1 -1
  168. package/src/tools/implementation/ContextManager.ts +4 -4
  169. package/src/tools/implementation/anonymousJazzAgent.ts +2 -1
  170. package/src/tools/implementation/createContext.ts +1 -1
  171. package/src/tools/implementation/devtoolsFormatters.ts +9 -9
  172. package/src/tools/implementation/invites.ts +2 -2
  173. package/src/tools/implementation/schema.ts +7 -7
  174. package/src/tools/implementation/symbols.ts +3 -0
  175. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -2
  176. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +11 -2
  177. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +18 -7
  178. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +17 -7
  179. package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +20 -11
  180. package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +19 -2
  181. package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +6 -0
  182. package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +6 -0
  183. package/src/tools/implementation/zodSchema/typeConverters/{CoFieldInit.ts → CoFieldSchemaInit.ts} +11 -11
  184. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +4 -4
  185. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +4 -4
  186. package/src/tools/implementation/zodSchema/zodCo.ts +2 -2
  187. package/src/tools/internal.ts +2 -1
  188. package/src/tools/lib/migration.ts +5 -5
  189. package/src/tools/subscribe/SubscriptionScope.ts +32 -24
  190. package/src/tools/subscribe/index.ts +4 -4
  191. package/src/tools/subscribe/utils.ts +11 -11
  192. package/src/tools/testing.ts +17 -13
  193. package/src/tools/tests/ContextManager.test.ts +68 -57
  194. package/src/tools/tests/PassphraseAuth.test.ts +2 -2
  195. package/src/tools/tests/account.test.ts +139 -69
  196. package/src/tools/tests/coDiscriminatedUnion.test-d.ts +12 -6
  197. package/src/tools/tests/coDiscriminatedUnion.test.ts +26 -17
  198. package/src/tools/tests/coFeed.test-d.ts +18 -17
  199. package/src/tools/tests/coFeed.test.ts +108 -97
  200. package/src/tools/tests/coList.test-d.ts +18 -23
  201. package/src/tools/tests/coList.test.ts +350 -165
  202. package/src/tools/tests/coMap.record.test-d.ts +9 -13
  203. package/src/tools/tests/coMap.record.test.ts +37 -23
  204. package/src/tools/tests/coMap.test-d.ts +43 -21
  205. package/src/tools/tests/coMap.test.ts +360 -182
  206. package/src/tools/tests/coOptional.test.ts +28 -13
  207. package/src/tools/tests/coPlainText.test.ts +15 -15
  208. package/src/tools/tests/createContext.test.ts +14 -14
  209. package/src/tools/tests/deepLoading.test.ts +95 -94
  210. package/src/tools/tests/exportImport.test.ts +61 -41
  211. package/src/tools/tests/groupsAndAccounts.test.ts +333 -116
  212. package/src/tools/tests/inbox.test.ts +22 -17
  213. package/src/tools/tests/interfaces.test.ts +12 -11
  214. package/src/tools/tests/invites.test.ts +6 -4
  215. package/src/tools/tests/load.test.ts +20 -18
  216. package/src/tools/tests/patterns/notifications.test.ts +6 -6
  217. package/src/tools/tests/patterns/quest.test.ts +3 -3
  218. package/src/tools/tests/patterns/requestToJoin.test.ts +22 -22
  219. package/src/tools/tests/request.test.ts +38 -39
  220. package/src/tools/tests/schemaUnion.test.ts +64 -10
  221. package/src/tools/tests/subscribe.test.ts +64 -64
  222. package/src/tools/tests/testing.test.ts +5 -9
  223. package/src/tools/tests/utils.ts +3 -3
  224. package/src/tools/tests/zod.test.ts +3 -3
  225. package/src/worker/index.ts +3 -3
  226. package/dist/chunk-LZOF6WP5.js.map +0 -1
  227. package/dist/media/chunk-E5J3WLQW.js.map +0 -1
  228. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts.map +0 -1
@@ -1,11 +1,13 @@
1
- import type { JsonValue, RawCoList, CoValueUniqueness, RawCoID } from "cojson";
2
- import { ControlledAccount, RawAccount, cojsonInternals } from "cojson";
1
+ import type { CoValueUniqueness, JsonValue, RawCoID, RawCoList } from "cojson";
2
+ import { cojsonInternals } from "cojson";
3
3
  import { calcPatch } from "fast-myers-diff";
4
- import type {
4
+ import {
5
5
  Account,
6
+ CoFieldInit,
6
7
  CoValue,
7
8
  CoValueClass,
8
- CoValueFromRaw,
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
- * Since `CoList` is a subclass of `Array`, you can use all the normal array methods like `push`, `pop`, `splice`, etc.
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[3] = "yellow";
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> extends Array<Item> implements CoValue {
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 _type: "CoList";
101
+ declare [TypeSym]: "CoList";
97
102
  static {
98
- this.prototype._type = "CoList";
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
- Object.defineProperty(this, "_instanceID", {
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
- id: {
206
- value: options.fromRaw.id,
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 new Proxy(this, CoListProxyHandler as ProxyHandler<this>);
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({ init: items, owner });
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
- id: {
259
- value: raw.id,
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
- return instance;
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 this._raw.entries().length;
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._schema[ItemsSym] as Schema;
188
+ const itemDescriptor = this.$jazz.schema[ItemsSym] as Schema;
391
189
  if (itemDescriptor === "json") {
392
- return this._raw.asArray();
190
+ return this.$jazz.raw.asArray();
393
191
  } else if ("encoded" in itemDescriptor) {
394
- return this._raw.asArray().map((e) => itemDescriptor.encoded.encode(e));
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)?.id)
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["_schema"][ItemsSym] },
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._type === "Anonymous" ? as.node.crypto : as._raw.core.node.crypto;
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._loadedAs,
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._loadedAs,
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._loadedAs,
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
- return this._raw.core.waitForSync(options);
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: Account | Group,
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) return null;
703
- let refId = (value as unknown as CoValue).id;
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._schema[ItemsSym] as Schema;
724
- const rawValue = target._raw.get(Number(key));
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._raw.entries().length;
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
- const itemDescriptor = target._schema[ItemsSym] as Schema;
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._raw.entries().length;
969
+ return Number(key) < target.$jazz.raw.entries().length;
797
970
  } else {
798
971
  return Reflect.has(target, key);
799
972
  }