jazz-tools 0.7.0-alpha.1 → 0.7.0-alpha.11

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