jazz-tools 0.7.0-alpha.9 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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 +298 -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 -74
  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 -114
  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;