jazz-tools 0.7.0-alpha.3 → 0.7.0-alpha.31

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/.turbo/turbo-build.log +78 -8
  2. package/CHANGELOG.md +181 -0
  3. package/dist/coValues/account.js +81 -41
  4. package/dist/coValues/account.js.map +1 -1
  5. package/dist/coValues/coList.js +156 -104
  6. package/dist/coValues/coList.js.map +1 -1
  7. package/dist/coValues/coMap.js +182 -163
  8. package/dist/coValues/coMap.js.map +1 -1
  9. package/dist/coValues/coStream.js +202 -71
  10. package/dist/coValues/coStream.js.map +1 -1
  11. package/dist/coValues/extensions/imageDef.js +13 -8
  12. package/dist/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/coValues/group.js +46 -38
  14. package/dist/coValues/group.js.map +1 -1
  15. package/dist/coValues/interfaces.js +23 -5
  16. package/dist/coValues/interfaces.js.map +1 -1
  17. package/dist/implementation/refs.js +26 -12
  18. package/dist/implementation/refs.js.map +1 -1
  19. package/dist/implementation/schema.js +38 -1
  20. package/dist/implementation/schema.js.map +1 -1
  21. package/dist/implementation/symbols.js +5 -0
  22. package/dist/implementation/symbols.js.map +1 -0
  23. package/dist/index.js +4 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/internal.js +1 -0
  26. package/dist/internal.js.map +1 -1
  27. package/dist/tests/coList.test.js +32 -36
  28. package/dist/tests/coList.test.js.map +1 -1
  29. package/dist/tests/coMap.test.js +170 -59
  30. package/dist/tests/coMap.test.js.map +1 -1
  31. package/dist/tests/coStream.test.js +59 -64
  32. package/dist/tests/coStream.test.js.map +1 -1
  33. package/dist/tests/groupsAndAccounts.test.js +88 -0
  34. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  35. package/package.json +5 -4
  36. package/src/coValues/account.ts +129 -105
  37. package/src/coValues/coList.ts +200 -131
  38. package/src/coValues/coMap.ts +243 -305
  39. package/src/coValues/coStream.ts +300 -127
  40. package/src/coValues/extensions/imageDef.ts +14 -16
  41. package/src/coValues/group.ts +90 -106
  42. package/src/coValues/interfaces.ts +33 -12
  43. package/src/implementation/refs.ts +42 -25
  44. package/src/implementation/schema.ts +69 -46
  45. package/src/implementation/symbols.ts +12 -0
  46. package/src/index.ts +10 -8
  47. package/src/internal.ts +1 -0
  48. package/src/tests/coList.test.ts +35 -39
  49. package/src/tests/coMap.test.ts +176 -81
  50. package/src/tests/coStream.test.ts +76 -81
  51. package/src/tests/groupsAndAccounts.test.ts +100 -0
@@ -4,28 +4,46 @@ import type { Effect, Stream } from "effect";
4
4
  import type {
5
5
  AccountCtx,
6
6
  CoValue,
7
- EnsureItemNullable,
8
- FieldDescriptor,
9
- FieldDescriptorFor,
7
+ Schema,
8
+ SchemaFor,
10
9
  ID,
11
- RefField,
10
+ RefEncoded,
12
11
  SubclassedConstructor,
13
12
  UnavailableError,
13
+ IfCo,
14
+ UnCo,
14
15
  } from "../internal.js";
15
16
  import {
16
17
  Account,
17
18
  CoValueBase,
18
19
  Group,
19
- ValueRef,
20
+ InitValues,
21
+ ItemsSym,
22
+ Ref,
23
+ SchemaInit,
24
+ co,
20
25
  inspect,
26
+ isRefEncoded,
21
27
  makeRefs,
22
28
  } from "../internal.js";
23
- import { Schema } from "@effect/schema";
29
+ import { encodeSync, decodeSync } from "@effect/schema/Schema";
24
30
 
25
- export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
31
+ export class CoList<Item = any>
26
32
  extends Array<Item>
27
33
  implements CoValue<"CoList", RawCoList>
28
34
  {
35
+ static Of<Item>(item: IfCo<Item, Item>): typeof CoList<Item> {
36
+ // TODO: cache superclass for item class
37
+ return class CoListOf extends CoList<Item> {
38
+ [co.items] = item;
39
+ };
40
+ }
41
+
42
+ /** @deprecated Use UPPERCASE `CoList.Of` instead! */
43
+ static of(..._args: never): never {
44
+ throw new Error("Can't use Array.of with CoLists");
45
+ }
46
+
29
47
  id!: ID<this>;
30
48
  _type!: "CoList";
31
49
  static {
@@ -33,11 +51,13 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
33
51
  }
34
52
  _raw!: RawCoList;
35
53
 
36
- static _encoding: any;
37
- get _encoding(): {
38
- _item: FieldDescriptorFor<Item>;
54
+ /** @internal This is only a marker type and doesn't exist at runtime */
55
+ [ItemsSym]!: Item;
56
+ static _schema: any;
57
+ get _schema(): {
58
+ [ItemsSym]: SchemaFor<Item>;
39
59
  } {
40
- return (this.constructor as typeof CoList)._encoding;
60
+ return (this.constructor as typeof CoList)._schema;
41
61
  }
42
62
 
43
63
  get _owner(): Account | Group {
@@ -48,8 +68,13 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
48
68
 
49
69
  get _refs(): {
50
70
  [idx: number]: NonNullable<Item> extends CoValue
51
- ? ValueRef<NonNullable<Item>>
71
+ ? Ref<NonNullable<Item>>
52
72
  : never;
73
+ } & {
74
+ length: number;
75
+ [Symbol.iterator](): IterableIterator<
76
+ NonNullable<Item> extends CoValue ? Ref<NonNullable<Item>> : never
77
+ >;
53
78
  } {
54
79
  return makeRefs<number>(
55
80
  (idx) => this._raw.get(idx) as unknown as ID<CoValue>,
@@ -59,14 +84,14 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
59
84
  (_, idx) => idx
60
85
  ),
61
86
  this._loadedAs,
62
- (_idx) => (this._encoding._item as RefField<CoValue>).ref()
87
+ (_idx) => this._schema[ItemsSym] as RefEncoded<CoValue>
63
88
  ) as any;
64
89
  }
65
90
 
66
91
  get _edits(): {
67
92
  [idx: number]: {
68
93
  value?: Item;
69
- ref?: Item extends CoValue ? ValueRef<Item> : never;
94
+ ref?: Item extends CoValue ? Ref<Item> : never;
70
95
  by?: Account;
71
96
  madeAt: Date;
72
97
  };
@@ -78,71 +103,53 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
78
103
  return Account.fromNode(this._raw.core.node);
79
104
  }
80
105
 
81
- constructor(_init: undefined, options: { fromRaw: RawCoList });
82
- constructor(init: Item[], options: { owner: Account | Group });
83
- constructor(init: number);
106
+ [InitValues]?: any;
107
+
108
+ static get [Symbol.species]() {
109
+ return Array;
110
+ }
111
+
84
112
  constructor(
85
- init: Item[] | undefined | number,
86
- options?: { owner: Account | Group } | { fromRaw: RawCoList }
113
+ options:
114
+ | { init: Item[]; owner: Account | Group }
115
+ | { fromRaw: RawCoList }
87
116
  ) {
88
- if (typeof init === "number") {
89
- // this might be called from an intrinsic, like map, trying to create an empty array
90
- // passing `0` as the only parameter
91
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
- return new Array(init) as any;
93
- }
94
-
95
117
  super();
96
118
 
97
- if (!options) {
98
- throw new Error("Must provide options");
119
+ if ("owner" in options) {
120
+ this[InitValues] = {
121
+ init: options.init,
122
+ owner: options.owner,
123
+ };
124
+ } else if ("fromRaw" in options) {
125
+ Object.defineProperties(this, {
126
+ id: {
127
+ value: options.fromRaw.id,
128
+ enumerable: false,
129
+ },
130
+ _raw: { value: options.fromRaw, enumerable: false },
131
+ });
99
132
  }
100
133
 
101
- let raw: RawCoList;
102
-
103
- if ("fromRaw" in options) {
104
- raw = options.fromRaw;
105
- } else {
106
- const rawOwner = options.owner._raw;
107
-
108
- const rawInit = init && this.toRawItems(init);
109
-
110
- raw = rawOwner.createList(rawInit);
111
- }
112
-
113
- Object.defineProperties(this, {
114
- id: {
115
- value: raw.id,
116
- enumerable: false,
117
- },
118
- _raw: { value: raw, enumerable: false },
119
- });
120
-
121
- return new Proxy(this, CoListProxyHandler<Item>(this._encoding._item));
134
+ return new Proxy(this, CoListProxyHandler as ProxyHandler<this>);
122
135
  }
123
136
 
124
- private toRawItems(items: Item[]) {
125
- const itemDescriptor = this._encoding._item as FieldDescriptor;
126
- const rawItems =
127
- itemDescriptor === "json"
128
- ? items
129
- : "encoded" in itemDescriptor
130
- ? items?.map((e) =>
131
- Schema.encodeSync(itemDescriptor.encoded)(e)
132
- )
133
- : "ref" in itemDescriptor
134
- ? items?.map((v) => (v as unknown as CoValue).id)
135
- : (() => {
136
- throw new Error("Invalid element descriptor");
137
- })();
138
- return rawItems;
137
+ static create<L extends CoList>(
138
+ this: SubclassedConstructor<L>,
139
+ items: UnCo<L[number]>[],
140
+ options: {owner: Account | Group}
141
+ ) {
142
+ return new this({ init: items, owner: options.owner });
139
143
  }
140
144
 
141
145
  push(...items: Item[]): number;
142
146
  /** @private For exact type compatibility with Array superclass */
143
147
  push(...items: Item[]): number;
144
148
  push(...items: Item[]): number {
145
- for (const item of this.toRawItems(items as Item[])) {
149
+ for (const item of toRawItems(
150
+ items as Item[],
151
+ this._schema[ItemsSym]
152
+ )) {
146
153
  this._raw.append(item);
147
154
  }
148
155
 
@@ -153,7 +160,10 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
153
160
  /** @private For exact type compatibility with Array superclass */
154
161
  unshift(...items: Item[]): number;
155
162
  unshift(...items: Item[]): number {
156
- for (const item of this.toRawItems(items as Item[])) {
163
+ for (const item of toRawItems(
164
+ items as Item[],
165
+ this._schema[ItemsSym]
166
+ )) {
157
167
  this._raw.prepend(item);
158
168
  }
159
169
 
@@ -176,21 +186,23 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
176
186
  return first;
177
187
  }
178
188
 
179
- splice(start: number, deleteCount: number, ...items: Item[]): Item[];
180
- splice(start: number, deleteCount: number, ...items: Item[]): Item[];
181
189
  splice(start: number, deleteCount: number, ...items: Item[]): Item[] {
182
190
  const deleted = this.slice(start, start + deleteCount);
183
191
 
184
192
  for (
185
- let idxToDelete = start + deleteCount;
186
- idxToDelete > start;
193
+ let idxToDelete = start + deleteCount - 1;
194
+ idxToDelete >= start;
187
195
  idxToDelete--
188
196
  ) {
189
197
  this._raw.delete(idxToDelete);
190
198
  }
191
199
 
192
- let appendAfter = start;
193
- for (const item of this.toRawItems(items as Item[])) {
200
+ let appendAfter = Math.max(start - 1, 0);
201
+ for (const item of toRawItems(
202
+ items as Item[],
203
+ this._schema[ItemsSym]
204
+ )) {
205
+ console.log(this._raw.asArray(), appendAfter);
194
206
  this._raw.append(item, appendAfter);
195
207
  appendAfter++;
196
208
  }
@@ -199,14 +211,14 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
199
211
  }
200
212
 
201
213
  toJSON() {
202
- const itemDescriptor = this._encoding._item as FieldDescriptor;
214
+ const itemDescriptor = this._schema[ItemsSym] as Schema;
203
215
  if (itemDescriptor === "json") {
204
216
  return this._raw.asArray();
205
217
  } else if ("encoded" in itemDescriptor) {
206
218
  return this._raw
207
219
  .asArray()
208
- .map((e) => Schema.encodeSync(itemDescriptor.encoded)(e));
209
- } else if ("ref" in itemDescriptor) {
220
+ .map((e) => encodeSync(itemDescriptor.encoded)(e));
221
+ } else if (isRefEncoded(itemDescriptor)) {
210
222
  return this.map((item) => (item as unknown as CoValue)?.toJSON());
211
223
  } else {
212
224
  return [];
@@ -231,7 +243,7 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
231
243
  this: SubclassedConstructor<V> & typeof CoList,
232
244
  raw: RawCoList
233
245
  ) {
234
- return new this(undefined, { fromRaw: raw });
246
+ return new this({ fromRaw: raw });
235
247
  }
236
248
 
237
249
  static loadEf = CoValueBase.loadEf as unknown as <V extends CoValue>(
@@ -256,65 +268,122 @@ export class CoList<Item extends EnsureItemNullable<Item, 'Co.List'> = any>
256
268
  onUpdate: (value: V) => void
257
269
  ) => () => void;
258
270
 
259
- static encoding<V extends CoList>(
271
+ static schema<V extends CoList>(
260
272
  this: { new (...args: any): V } & typeof CoList,
261
- def: { _item: V["_encoding"]["_item"] }
273
+ def: { [ItemsSym]: V["_schema"][ItemsSym] }
262
274
  ) {
263
- this._encoding ||= {};
264
- Object.assign(this._encoding, def);
275
+ this._schema ||= {};
276
+ Object.assign(this._schema, def);
265
277
  }
266
278
  }
267
279
 
268
- function CoListProxyHandler<Item extends EnsureItemNullable<Item, "Co.List">>(
269
- itemDescriptor: FieldDescriptor
270
- ): ProxyHandler<CoList<Item>> {
271
- return {
272
- get(target, key, receiver) {
273
- if (typeof key === "string" && !isNaN(+key)) {
274
- const rawValue = target._raw.get(Number(key));
275
- if (itemDescriptor === "json") {
276
- return rawValue;
277
- } else if ("encoded" in itemDescriptor) {
278
- return rawValue === undefined
279
- ? undefined
280
- : Schema.decodeSync(itemDescriptor.encoded)(rawValue);
281
- } else if ("ref" in itemDescriptor) {
282
- return rawValue === undefined
283
- ? undefined
284
- : new ValueRef(
285
- rawValue as unknown as ID<CoValue>,
286
- target._loadedAs,
287
- itemDescriptor.ref()
288
- ).accessFrom(receiver);
289
- }
290
- } else if (key === "length") {
291
- return target._raw.entries().length;
292
- } else {
293
- return Reflect.get(target, key, receiver);
294
- }
295
- },
296
- set(target, key, value, receiver) {
297
- if (typeof key === "string" && !isNaN(+key)) {
298
- let rawValue;
299
- if (itemDescriptor === "json") {
300
- rawValue = value;
301
- } else if ("encoded" in itemDescriptor) {
302
- rawValue = Schema.encodeSync(itemDescriptor.encoded)(value);
303
- } else if ("ref" in itemDescriptor) {
304
- rawValue = value.id;
305
- }
306
- target._raw.replace(Number(key), rawValue);
307
- return true;
308
- } else {
309
- return Reflect.set(target, key, value, receiver);
280
+ function toRawItems<Item>(items: Item[], itemDescriptor: Schema) {
281
+ const rawItems =
282
+ itemDescriptor === "json"
283
+ ? items
284
+ : "encoded" in itemDescriptor
285
+ ? items?.map((e) => encodeSync(itemDescriptor.encoded)(e))
286
+ : isRefEncoded(itemDescriptor)
287
+ ? items?.map((v) => (v as unknown as CoValue).id)
288
+ : (() => {
289
+ throw new Error("Invalid element descriptor");
290
+ })();
291
+ return rawItems;
292
+ }
293
+
294
+ function init(list: CoList) {
295
+ if (list[InitValues]) {
296
+ const { init, owner } = list[InitValues];
297
+ const raw = owner._raw.createList(
298
+ toRawItems(init, list._schema[ItemsSym])
299
+ );
300
+
301
+ Object.defineProperties(list, {
302
+ id: {
303
+ value: raw.id,
304
+ enumerable: false,
305
+ },
306
+ _raw: { value: raw, enumerable: false },
307
+ });
308
+ delete list[InitValues];
309
+ }
310
+ }
311
+
312
+ const CoListProxyHandler: ProxyHandler<CoList> = {
313
+ get(target, key, receiver) {
314
+ if (typeof key === "string" && !isNaN(+key)) {
315
+ const itemDescriptor = target._schema[ItemsSym] as Schema;
316
+ const rawValue = target._raw.get(Number(key));
317
+ if (itemDescriptor === "json") {
318
+ return rawValue;
319
+ } else if ("encoded" in itemDescriptor) {
320
+ return rawValue === undefined
321
+ ? undefined
322
+ : decodeSync(itemDescriptor.encoded)(rawValue);
323
+ } else if (isRefEncoded(itemDescriptor)) {
324
+ return rawValue === undefined
325
+ ? undefined
326
+ : new Ref(
327
+ rawValue as unknown as ID<CoValue>,
328
+ target._loadedAs,
329
+ itemDescriptor
330
+ ).accessFrom(receiver);
310
331
  }
311
- },
312
- has(target, key) {
313
- if (typeof key === "string" && !isNaN(+key)) {
314
- return Number(key) < target._raw.entries().length;
315
- } else {
316
- return Reflect.has(target, key);
332
+ } else if (key === "length") {
333
+ return target._raw.entries().length;
334
+ } else {
335
+ return Reflect.get(target, key, receiver);
336
+ }
337
+ },
338
+ set(target, key, value, receiver) {
339
+ if (
340
+ key === ItemsSym &&
341
+ typeof value === "object" &&
342
+ SchemaInit in value
343
+ ) {
344
+ (target.constructor as typeof CoList)._schema ||= {};
345
+ (target.constructor as typeof CoList)._schema[ItemsSym] =
346
+ value[SchemaInit];
347
+ init(target);
348
+ return true;
349
+ }
350
+ if (typeof key === "string" && !isNaN(+key)) {
351
+ const itemDescriptor = target._schema[ItemsSym] as Schema;
352
+ let rawValue;
353
+ if (itemDescriptor === "json") {
354
+ rawValue = value;
355
+ } else if ("encoded" in itemDescriptor) {
356
+ rawValue = encodeSync(itemDescriptor.encoded)(value);
357
+ } else if (isRefEncoded(itemDescriptor)) {
358
+ rawValue = value.id;
317
359
  }
318
- },
319
- };
320
- }
360
+ target._raw.replace(Number(key), rawValue);
361
+ return true;
362
+ } else {
363
+ return Reflect.set(target, key, value, receiver);
364
+ }
365
+ },
366
+ defineProperty(target, key, descriptor) {
367
+ if (
368
+ descriptor.value &&
369
+ key === ItemsSym &&
370
+ typeof descriptor.value === "object" &&
371
+ SchemaInit in descriptor.value
372
+ ) {
373
+ (target.constructor as typeof CoList)._schema ||= {};
374
+ (target.constructor as typeof CoList)._schema[ItemsSym] =
375
+ descriptor.value[SchemaInit];
376
+ init(target);
377
+ return true;
378
+ } else {
379
+ return Reflect.defineProperty(target, key, descriptor);
380
+ }
381
+ },
382
+ has(target, key) {
383
+ if (typeof key === "string" && !isNaN(+key)) {
384
+ return Number(key) < target._raw.entries().length;
385
+ } else {
386
+ return Reflect.has(target, key);
387
+ }
388
+ },
389
+ };