jazz-tools 0.7.0-alpha.8 → 0.7.1

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 (72) hide show
  1. package/.eslintrc.cjs +3 -10
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +3 -19
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +140 -0
  6. package/CHANGELOG.md +304 -0
  7. package/README.md +10 -2
  8. package/dist/coValues/account.js +59 -41
  9. package/dist/coValues/account.js.map +1 -1
  10. package/dist/coValues/coList.js +49 -46
  11. package/dist/coValues/coList.js.map +1 -1
  12. package/dist/coValues/coMap.js +143 -44
  13. package/dist/coValues/coMap.js.map +1 -1
  14. package/dist/coValues/coStream.js +144 -35
  15. package/dist/coValues/coStream.js.map +1 -1
  16. package/dist/coValues/deepLoading.js +60 -0
  17. package/dist/coValues/deepLoading.js.map +1 -0
  18. package/dist/coValues/extensions/imageDef.js +10 -7
  19. package/dist/coValues/extensions/imageDef.js.map +1 -1
  20. package/dist/coValues/group.js +49 -13
  21. package/dist/coValues/group.js.map +1 -1
  22. package/dist/coValues/interfaces.js +70 -31
  23. package/dist/coValues/interfaces.js.map +1 -1
  24. package/dist/implementation/devtoolsFormatters.js +114 -0
  25. package/dist/implementation/devtoolsFormatters.js.map +1 -0
  26. package/dist/implementation/refs.js +58 -18
  27. package/dist/implementation/refs.js.map +1 -1
  28. package/dist/implementation/schema.js +58 -0
  29. package/dist/implementation/schema.js.map +1 -0
  30. package/dist/implementation/subscriptionScope.js +19 -1
  31. package/dist/implementation/subscriptionScope.js.map +1 -1
  32. package/dist/implementation/symbols.js +5 -0
  33. package/dist/implementation/symbols.js.map +1 -0
  34. package/dist/index.js +3 -5
  35. package/dist/index.js.map +1 -1
  36. package/dist/internal.js +5 -2
  37. package/dist/internal.js.map +1 -1
  38. package/dist/tests/coList.test.js +51 -48
  39. package/dist/tests/coList.test.js.map +1 -1
  40. package/dist/tests/coMap.test.js +131 -73
  41. package/dist/tests/coMap.test.js.map +1 -1
  42. package/dist/tests/coStream.test.js +56 -41
  43. package/dist/tests/coStream.test.js.map +1 -1
  44. package/dist/tests/deepLoading.test.js +188 -0
  45. package/dist/tests/deepLoading.test.js.map +1 -0
  46. package/dist/tests/groupsAndAccounts.test.js +83 -0
  47. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  48. package/package.json +17 -9
  49. package/src/coValues/account.ts +113 -125
  50. package/src/coValues/coList.ts +87 -103
  51. package/src/coValues/coMap.ts +200 -147
  52. package/src/coValues/coStream.ts +264 -80
  53. package/src/coValues/deepLoading.ts +229 -0
  54. package/src/coValues/extensions/imageDef.ts +17 -13
  55. package/src/coValues/group.ts +92 -58
  56. package/src/coValues/interfaces.ts +215 -115
  57. package/src/implementation/devtoolsFormatters.ts +110 -0
  58. package/src/implementation/inspect.ts +1 -1
  59. package/src/implementation/refs.ts +80 -28
  60. package/src/implementation/schema.ts +138 -0
  61. package/src/implementation/subscriptionScope.ts +48 -12
  62. package/src/implementation/symbols.ts +11 -0
  63. package/src/index.ts +12 -8
  64. package/src/internal.ts +7 -3
  65. package/src/tests/coList.test.ts +77 -62
  66. package/src/tests/coMap.test.ts +201 -113
  67. package/src/tests/coStream.test.ts +113 -84
  68. package/src/tests/deepLoading.test.ts +301 -0
  69. package/src/tests/groupsAndAccounts.test.ts +91 -0
  70. package/dist/implementation/encoding.js +0 -26
  71. package/dist/implementation/encoding.js.map +0 -1
  72. package/src/implementation/encoding.ts +0 -105
@@ -1,17 +1,14 @@
1
1
  import type { RawCoList } from "cojson";
2
2
  import { RawAccount } from "cojson";
3
- import type { Effect, Stream } from "effect";
4
3
  import type {
5
- AccountCtx,
6
4
  CoValue,
7
- ValidItem,
8
- Encoding,
9
- EncodingFor,
5
+ Schema,
6
+ SchemaFor,
10
7
  ID,
11
8
  RefEncoded,
12
- SubclassedConstructor,
13
- UnavailableError,
14
- IsVal,
9
+ ClassOf,
10
+ UnCo,
11
+ CoValueClass,
15
12
  } from "../internal.js";
16
13
  import {
17
14
  Account,
@@ -21,21 +18,23 @@ import {
21
18
  ItemsSym,
22
19
  Ref,
23
20
  SchemaInit,
24
- val,
21
+ co,
25
22
  inspect,
23
+ isRefEncoded,
26
24
  makeRefs,
27
25
  } from "../internal.js";
28
- import { Schema } from "@effect/schema";
26
+ import { encodeSync, decodeSync } from "@effect/schema/Schema";
29
27
 
30
- export class CoList<Item extends ValidItem<Item, "CoList"> = any>
28
+ /** @category CoValues */
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ export class CoList<Item = any>
31
31
  extends Array<Item>
32
32
  implements CoValue<"CoList", RawCoList>
33
33
  {
34
- static Of<Item extends ValidItem<Item, "CoList"> = any>(
35
- item: IsVal<Item, Item>
36
- ): typeof CoList<Item> {
34
+ static Of<Item>(item: Item): typeof CoList<Item> {
35
+ // TODO: cache superclass for item class
37
36
  return class CoListOf extends CoList<Item> {
38
- [val.items] = item;
37
+ [co.items] = item;
39
38
  };
40
39
  }
41
40
 
@@ -50,14 +49,16 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
50
49
  this.prototype._type = "CoList";
51
50
  }
52
51
  _raw!: RawCoList;
52
+ _instanceID!: string;
53
53
 
54
54
  /** @internal This is only a marker type and doesn't exist at runtime */
55
55
  [ItemsSym]!: Item;
56
- static _encoding: any;
57
- get _encoding(): {
58
- [ItemsSym]: EncodingFor<Item>;
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ static _schema: any;
58
+ get _schema(): {
59
+ [ItemsSym]: SchemaFor<Item>;
59
60
  } {
60
- return (this.constructor as typeof CoList)._encoding;
61
+ return (this.constructor as typeof CoList)._schema;
61
62
  }
62
63
 
63
64
  get _owner(): Account | Group {
@@ -66,14 +67,17 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
66
67
  : Group.fromRaw(this._raw.group);
67
68
  }
68
69
 
70
+ /** @category Content */
69
71
  get _refs(): {
70
- [idx: number]: NonNullable<Item> extends CoValue
71
- ? Ref<NonNullable<Item>>
72
+ [idx: number]: Exclude<Item, null> extends CoValue
73
+ ? Ref<UnCo<Exclude<Item, null>>>
72
74
  : never;
73
75
  } & {
74
76
  length: number;
75
77
  [Symbol.iterator](): IterableIterator<
76
- NonNullable<Item> extends CoValue ? Ref<NonNullable<Item>> : never
78
+ Exclude<Item, null> extends CoValue
79
+ ? Ref<Exclude<Item, null>>
80
+ : never
77
81
  >;
78
82
  } {
79
83
  return makeRefs<number>(
@@ -81,10 +85,11 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
81
85
  () =>
82
86
  Array.from(
83
87
  { length: this._raw.entries().length },
84
- (_, idx) => idx
88
+ (_, idx) => idx,
85
89
  ),
86
90
  this._loadedAs,
87
- (_idx) => this._encoding[ItemsSym] as RefEncoded<CoValue>
91
+ (_idx) => this._schema[ItemsSym] as RefEncoded<CoValue>,
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
93
  ) as any;
89
94
  }
90
95
 
@@ -103,30 +108,28 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
103
108
  return Account.fromNode(this._raw.core.node);
104
109
  }
105
110
 
106
- [InitValues]?: {
107
- init: Item[];
108
- owner: Account | Group;
109
- };
111
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
+ [InitValues]?: any;
110
113
 
111
114
  static get [Symbol.species]() {
112
115
  return Array;
113
116
  }
114
117
 
115
- constructor(_init: undefined, options: { fromRaw: RawCoList });
116
- constructor(init: Item[], options: { owner: Account | Group });
117
118
  constructor(
118
- init: Item[] | undefined,
119
- options?: { owner: Account | Group } | { fromRaw: RawCoList }
119
+ options:
120
+ | { init: Item[]; owner: Account | Group }
121
+ | { fromRaw: RawCoList },
120
122
  ) {
121
123
  super();
122
124
 
123
- if (!options) {
124
- throw new Error("Must provide options");
125
- }
125
+ Object.defineProperty(this, "_instanceID", {
126
+ value: `instance-${Math.random().toString(36).slice(2)}`,
127
+ enumerable: false,
128
+ });
126
129
 
127
- if (init && "owner" in options) {
130
+ if ("owner" in options) {
128
131
  this[InitValues] = {
129
- init,
132
+ init: options.init,
130
133
  owner: options.owner,
131
134
  };
132
135
  } else if ("fromRaw" in options) {
@@ -142,13 +145,21 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
142
145
  return new Proxy(this, CoListProxyHandler as ProxyHandler<this>);
143
146
  }
144
147
 
148
+ static create<L extends CoList>(
149
+ this: ClassOf<L>,
150
+ items: UnCo<L[number]>[],
151
+ options: { owner: Account | Group },
152
+ ) {
153
+ return new this({ init: items, owner: options.owner });
154
+ }
155
+
145
156
  push(...items: Item[]): number;
146
157
  /** @private For exact type compatibility with Array superclass */
147
158
  push(...items: Item[]): number;
148
159
  push(...items: Item[]): number {
149
160
  for (const item of toRawItems(
150
161
  items as Item[],
151
- this._encoding[ItemsSym]
162
+ this._schema[ItemsSym],
152
163
  )) {
153
164
  this._raw.append(item);
154
165
  }
@@ -162,7 +173,7 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
162
173
  unshift(...items: Item[]): number {
163
174
  for (const item of toRawItems(
164
175
  items as Item[],
165
- this._encoding[ItemsSym]
176
+ this._schema[ItemsSym],
166
177
  )) {
167
178
  this._raw.prepend(item);
168
179
  }
@@ -186,24 +197,23 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
186
197
  return first;
187
198
  }
188
199
 
189
- splice(start: number, deleteCount: number, ...items: Item[]): Item[];
190
- splice(start: number, deleteCount: number, ...items: Item[]): Item[];
191
200
  splice(start: number, deleteCount: number, ...items: Item[]): Item[] {
192
201
  const deleted = this.slice(start, start + deleteCount);
193
202
 
194
203
  for (
195
- let idxToDelete = start + deleteCount;
196
- idxToDelete > start;
204
+ let idxToDelete = start + deleteCount - 1;
205
+ idxToDelete >= start;
197
206
  idxToDelete--
198
207
  ) {
199
208
  this._raw.delete(idxToDelete);
200
209
  }
201
210
 
202
- let appendAfter = start;
211
+ let appendAfter = Math.max(start - 1, 0);
203
212
  for (const item of toRawItems(
204
213
  items as Item[],
205
- this._encoding[ItemsSym]
214
+ this._schema[ItemsSym],
206
215
  )) {
216
+ console.log(this._raw.asArray(), appendAfter);
207
217
  this._raw.append(item, appendAfter);
208
218
  appendAfter++;
209
219
  }
@@ -212,14 +222,14 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
212
222
  }
213
223
 
214
224
  toJSON() {
215
- const itemDescriptor = this._encoding[ItemsSym] as Encoding;
225
+ const itemDescriptor = this._schema[ItemsSym] as Schema;
216
226
  if (itemDescriptor === "json") {
217
227
  return this._raw.asArray();
218
228
  } else if ("encoded" in itemDescriptor) {
219
229
  return this._raw
220
230
  .asArray()
221
- .map((e) => Schema.encodeSync(itemDescriptor.encoded)(e));
222
- } else if ("ref" in itemDescriptor) {
231
+ .map((e) => encodeSync(itemDescriptor.encoded)(e));
232
+ } else if (isRefEncoded(itemDescriptor)) {
223
233
  return this.map((item) => (item as unknown as CoValue)?.toJSON());
224
234
  } else {
225
235
  return [];
@@ -230,61 +240,35 @@ export class CoList<Item extends ValidItem<Item, "CoList"> = any>
230
240
  return this.toJSON();
231
241
  }
232
242
 
233
- subscribe!: (listener: (update: this) => void) => () => void;
234
- static {
235
- this.prototype.subscribe = CoValueBase.prototype.subscribe as any;
236
- }
237
-
238
- subscribeEf!: () => Stream.Stream<this, "unavailable", never>;
239
- static {
240
- this.prototype.subscribeEf = CoValueBase.prototype.subscribeEf as any;
241
- }
242
-
243
243
  static fromRaw<V extends CoList>(
244
- this: SubclassedConstructor<V> & typeof CoList,
245
- raw: RawCoList
244
+ this: ClassOf<V> & typeof CoList,
245
+ raw: RawCoList,
246
246
  ) {
247
- return new this(undefined, { fromRaw: raw });
247
+ return new this({ fromRaw: raw });
248
248
  }
249
249
 
250
- static loadEf = CoValueBase.loadEf as unknown as <V extends CoValue>(
251
- this: SubclassedConstructor<V>,
252
- id: ID<V>
253
- ) => Effect.Effect<V, UnavailableError, AccountCtx>;
254
- static load = CoValueBase.load as unknown as <V extends CoValue>(
255
- this: SubclassedConstructor<V>,
256
- id: ID<V>,
257
- options: { as: Account | Group }
258
- ) => Promise<V | undefined>;
259
- static subscribeEf = CoValueBase.subscribeEf as unknown as <
260
- V extends CoValue,
261
- >(
262
- this: SubclassedConstructor<V>,
263
- id: ID<V>
264
- ) => Stream.Stream<V, UnavailableError, AccountCtx>;
265
- static subscribe = CoValueBase.subscribe as unknown as <V extends CoValue>(
266
- this: SubclassedConstructor<V>,
267
- id: ID<V>,
268
- options: { as: Account | Group },
269
- onUpdate: (value: V) => void
270
- ) => () => void;
271
-
272
- static encoding<V extends CoList>(
250
+ static load = CoValueBase.load as CoValueClass["load"];
251
+ static loadEf = CoValueBase.loadEf as CoValueClass["loadEf"];
252
+ static subscribe = CoValueBase.subscribe as CoValueClass["subscribe"];
253
+ static subscribeEf = CoValueBase.subscribeEf as CoValueClass["subscribeEf"];
254
+
255
+ static schema<V extends CoList>(
256
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
273
257
  this: { new (...args: any): V } & typeof CoList,
274
- def: { [ItemsSym]: V["_encoding"][ItemsSym] }
258
+ def: { [ItemsSym]: V["_schema"][ItemsSym] },
275
259
  ) {
276
- this._encoding ||= {};
277
- Object.assign(this._encoding, def);
260
+ this._schema ||= {};
261
+ Object.assign(this._schema, def);
278
262
  }
279
263
  }
280
264
 
281
- function toRawItems<Item>(items: Item[], itemDescriptor: Encoding) {
265
+ function toRawItems<Item>(items: Item[], itemDescriptor: Schema) {
282
266
  const rawItems =
283
267
  itemDescriptor === "json"
284
268
  ? items
285
269
  : "encoded" in itemDescriptor
286
- ? items?.map((e) => Schema.encodeSync(itemDescriptor.encoded)(e))
287
- : "ref" in itemDescriptor
270
+ ? items?.map((e) => encodeSync(itemDescriptor.encoded)(e))
271
+ : isRefEncoded(itemDescriptor)
288
272
  ? items?.map((v) => (v as unknown as CoValue).id)
289
273
  : (() => {
290
274
  throw new Error("Invalid element descriptor");
@@ -296,7 +280,7 @@ function init(list: CoList) {
296
280
  if (list[InitValues]) {
297
281
  const { init, owner } = list[InitValues];
298
282
  const raw = owner._raw.createList(
299
- toRawItems(init, list._encoding[ItemsSym])
283
+ toRawItems(init, list._schema[ItemsSym]),
300
284
  );
301
285
 
302
286
  Object.defineProperties(list, {
@@ -313,22 +297,22 @@ function init(list: CoList) {
313
297
  const CoListProxyHandler: ProxyHandler<CoList> = {
314
298
  get(target, key, receiver) {
315
299
  if (typeof key === "string" && !isNaN(+key)) {
316
- const itemDescriptor = target._encoding[ItemsSym] as Encoding;
300
+ const itemDescriptor = target._schema[ItemsSym] as Schema;
317
301
  const rawValue = target._raw.get(Number(key));
318
302
  if (itemDescriptor === "json") {
319
303
  return rawValue;
320
304
  } else if ("encoded" in itemDescriptor) {
321
305
  return rawValue === undefined
322
306
  ? undefined
323
- : Schema.decodeSync(itemDescriptor.encoded)(rawValue);
324
- } else if ("ref" in itemDescriptor) {
307
+ : decodeSync(itemDescriptor.encoded)(rawValue);
308
+ } else if (isRefEncoded(itemDescriptor)) {
325
309
  return rawValue === undefined
326
310
  ? undefined
327
311
  : new Ref(
328
312
  rawValue as unknown as ID<CoValue>,
329
313
  target._loadedAs,
330
- itemDescriptor
331
- ).accessFrom(receiver);
314
+ itemDescriptor,
315
+ ).accessFrom(receiver, Number(key));
332
316
  }
333
317
  } else if (key === "length") {
334
318
  return target._raw.entries().length;
@@ -342,20 +326,20 @@ const CoListProxyHandler: ProxyHandler<CoList> = {
342
326
  typeof value === "object" &&
343
327
  SchemaInit in value
344
328
  ) {
345
- (target.constructor as typeof CoList)._encoding ||= {};
346
- (target.constructor as typeof CoList)._encoding[ItemsSym] =
329
+ (target.constructor as typeof CoList)._schema ||= {};
330
+ (target.constructor as typeof CoList)._schema[ItemsSym] =
347
331
  value[SchemaInit];
348
332
  init(target);
349
333
  return true;
350
334
  }
351
335
  if (typeof key === "string" && !isNaN(+key)) {
352
- const itemDescriptor = target._encoding[ItemsSym] as Encoding;
336
+ const itemDescriptor = target._schema[ItemsSym] as Schema;
353
337
  let rawValue;
354
338
  if (itemDescriptor === "json") {
355
339
  rawValue = value;
356
340
  } else if ("encoded" in itemDescriptor) {
357
- rawValue = Schema.encodeSync(itemDescriptor.encoded)(value);
358
- } else if ("ref" in itemDescriptor) {
341
+ rawValue = encodeSync(itemDescriptor.encoded)(value);
342
+ } else if (isRefEncoded(itemDescriptor)) {
359
343
  rawValue = value.id;
360
344
  }
361
345
  target._raw.replace(Number(key), rawValue);
@@ -371,8 +355,8 @@ const CoListProxyHandler: ProxyHandler<CoList> = {
371
355
  typeof descriptor.value === "object" &&
372
356
  SchemaInit in descriptor.value
373
357
  ) {
374
- (target.constructor as typeof CoList)._encoding ||= {};
375
- (target.constructor as typeof CoList)._encoding[ItemsSym] =
358
+ (target.constructor as typeof CoList)._schema ||= {};
359
+ (target.constructor as typeof CoList)._schema[ItemsSym] =
376
360
  descriptor.value[SchemaInit];
377
361
  init(target);
378
362
  return true;