jazz-tools 0.7.0-alpha.2 → 0.7.0-alpha.21

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