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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. package/.eslintrc.cjs +8 -1
  2. package/CHANGELOG.md +14 -0
  3. package/dist/coValues/account.js +138 -0
  4. package/dist/coValues/account.js.map +1 -0
  5. package/dist/coValues/coList.js +196 -0
  6. package/dist/coValues/coList.js.map +1 -0
  7. package/dist/coValues/coMap.js +249 -0
  8. package/dist/coValues/coMap.js.map +1 -0
  9. package/dist/coValues/coStream.js +189 -0
  10. package/dist/coValues/coStream.js.map +1 -0
  11. package/dist/coValues/extensions/imageDef.js +12 -12
  12. package/dist/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/coValues/group.js +93 -0
  14. package/dist/coValues/group.js.map +1 -0
  15. package/dist/coValues/interfaces.js +58 -0
  16. package/dist/coValues/interfaces.js.map +1 -0
  17. package/dist/implementation/errors.js.map +1 -0
  18. package/dist/implementation/inspect.js +2 -0
  19. package/dist/implementation/inspect.js.map +1 -0
  20. package/dist/{refs.js → implementation/refs.js} +11 -13
  21. package/dist/implementation/refs.js.map +1 -0
  22. package/dist/implementation/schema.js +6 -0
  23. package/dist/implementation/schema.js.map +1 -0
  24. package/dist/{subscriptionScope.js → implementation/subscriptionScope.js} +1 -1
  25. package/dist/implementation/subscriptionScope.js.map +1 -0
  26. package/dist/index.js +8 -28
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal.js +13 -0
  29. package/dist/internal.js.map +1 -0
  30. package/dist/tests/coList.test.js +26 -22
  31. package/dist/tests/coList.test.js.map +1 -1
  32. package/dist/tests/coMap.test.js +74 -43
  33. package/dist/tests/coMap.test.js.map +1 -1
  34. package/dist/tests/coStream.test.js +35 -24
  35. package/dist/tests/coStream.test.js.map +1 -1
  36. package/package.json +11 -4
  37. package/src/coValues/account.ts +297 -0
  38. package/src/coValues/coList.ts +320 -0
  39. package/src/coValues/coMap.ts +447 -0
  40. package/src/coValues/coStream.ts +325 -0
  41. package/src/coValues/extensions/imageDef.ts +25 -16
  42. package/src/coValues/group.ts +186 -0
  43. package/src/coValues/interfaces.ts +216 -0
  44. package/src/implementation/inspect.ts +2 -0
  45. package/src/{refs.ts → implementation/refs.ts} +21 -32
  46. package/src/implementation/schema.ts +69 -0
  47. package/src/{subscriptionScope.ts → implementation/subscriptionScope.ts} +11 -13
  48. package/src/index.ts +9 -54
  49. package/src/internal.ts +15 -0
  50. package/src/tests/coList.test.ts +27 -25
  51. package/src/tests/coMap.test.ts +111 -50
  52. package/src/tests/coStream.test.ts +51 -38
  53. package/dist/coValueInterfaces.js +0 -8
  54. package/dist/coValueInterfaces.js.map +0 -1
  55. package/dist/coValues/account/account.js +0 -11
  56. package/dist/coValues/account/account.js.map +0 -1
  57. package/dist/coValues/account/accountOf.js +0 -150
  58. package/dist/coValues/account/accountOf.js.map +0 -1
  59. package/dist/coValues/account/migration.js +0 -4
  60. package/dist/coValues/account/migration.js.map +0 -1
  61. package/dist/coValues/coList/coList.js +0 -2
  62. package/dist/coValues/coList/coList.js.map +0 -1
  63. package/dist/coValues/coList/coListOf.js +0 -235
  64. package/dist/coValues/coList/coListOf.js.map +0 -1
  65. package/dist/coValues/coList/internalDocs.js +0 -2
  66. package/dist/coValues/coList/internalDocs.js.map +0 -1
  67. package/dist/coValues/coMap/coMap.js +0 -2
  68. package/dist/coValues/coMap/coMap.js.map +0 -1
  69. package/dist/coValues/coMap/coMapOf.js +0 -262
  70. package/dist/coValues/coMap/coMapOf.js.map +0 -1
  71. package/dist/coValues/coMap/internalDocs.js +0 -2
  72. package/dist/coValues/coMap/internalDocs.js.map +0 -1
  73. package/dist/coValues/coStream/coStream.js +0 -2
  74. package/dist/coValues/coStream/coStream.js.map +0 -1
  75. package/dist/coValues/coStream/coStreamOf.js +0 -244
  76. package/dist/coValues/coStream/coStreamOf.js.map +0 -1
  77. package/dist/coValues/construction.js +0 -34
  78. package/dist/coValues/construction.js.map +0 -1
  79. package/dist/coValues/group/group.js +0 -2
  80. package/dist/coValues/group/group.js.map +0 -1
  81. package/dist/coValues/group/groupOf.js +0 -109
  82. package/dist/coValues/group/groupOf.js.map +0 -1
  83. package/dist/coValues/resolution.js +0 -66
  84. package/dist/coValues/resolution.js.map +0 -1
  85. package/dist/errors.js.map +0 -1
  86. package/dist/refs.js.map +0 -1
  87. package/dist/schemaHelpers.js +0 -14
  88. package/dist/schemaHelpers.js.map +0 -1
  89. package/dist/subscriptionScope.js.map +0 -1
  90. package/dist/tests/types.test.js +0 -33
  91. package/dist/tests/types.test.js.map +0 -1
  92. package/src/coValueInterfaces.ts +0 -105
  93. package/src/coValues/account/account.ts +0 -106
  94. package/src/coValues/account/accountOf.ts +0 -284
  95. package/src/coValues/account/migration.ts +0 -12
  96. package/src/coValues/coList/coList.ts +0 -57
  97. package/src/coValues/coList/coListOf.ts +0 -377
  98. package/src/coValues/coList/internalDocs.ts +0 -1
  99. package/src/coValues/coMap/coMap.ts +0 -110
  100. package/src/coValues/coMap/coMapOf.ts +0 -451
  101. package/src/coValues/coMap/internalDocs.ts +0 -1
  102. package/src/coValues/coStream/coStream.ts +0 -63
  103. package/src/coValues/coStream/coStreamOf.ts +0 -404
  104. package/src/coValues/construction.ts +0 -110
  105. package/src/coValues/group/group.ts +0 -27
  106. package/src/coValues/group/groupOf.ts +0 -183
  107. package/src/coValues/resolution.ts +0 -111
  108. package/src/schemaHelpers.ts +0 -72
  109. package/src/tests/types.test.ts +0 -37
  110. /package/dist/{errors.js → implementation/errors.js} +0 -0
  111. /package/src/{errors.ts → implementation/errors.ts} +0 -0
@@ -0,0 +1,447 @@
1
+ import type { JsonValue, RawCoMap } from "cojson";
2
+ import type { Simplify } from "effect/Types";
3
+ import { Schema } from "@effect/schema";
4
+ import type {
5
+ CoValue,
6
+ Encoder,
7
+ FieldDescriptor,
8
+ FieldDescriptorFor,
9
+ Group,
10
+ ID,
11
+ RefField,
12
+ EnsureCoValueNullable,
13
+ CoValueClass,
14
+ } from "../internal.js";
15
+ import {
16
+ Account,
17
+ CoValueBase,
18
+ ValueRef,
19
+ inspect,
20
+ makeRefs,
21
+ subscriptionsScopes,
22
+ indexSignature,
23
+ } from "../internal.js";
24
+
25
+ type EnsureValid<
26
+ Fields extends { [key: string]: any; [indexSignature]?: any },
27
+ > = {
28
+ [Key in OwnKeys<Fields> as IfOptionalKey<
29
+ Key,
30
+ Fields
31
+ >]?: EnsureCoValueNullable<Fields[Key], Key>;
32
+ } & {
33
+ [Key in OwnKeys<Fields> as IfRequiredKey<
34
+ Key,
35
+ Fields
36
+ >]: EnsureCoValueNullable<Fields[Key], Key>;
37
+ } & {
38
+ [Key in indexSignature]?: EnsureCoValueNullable<
39
+ Fields[indexSignature],
40
+ Key
41
+ >;
42
+ };
43
+
44
+ type IfOptionalKey<Key extends keyof Obj, Obj> = Pick<
45
+ Partial<Obj>,
46
+ Key
47
+ > extends Pick<Obj, Key>
48
+ ? Key
49
+ : never;
50
+ type IfRequiredKey<Key extends keyof Obj, Obj> = Pick<
51
+ Partial<Obj>,
52
+ Key
53
+ > extends Pick<Obj, Key>
54
+ ? never
55
+ : Key;
56
+
57
+ type DefaultFields = {
58
+ [key: string]: any;
59
+ [indexSignature]?: any;
60
+ };
61
+
62
+ export class CoMap<Fields extends EnsureValid<Fields> = DefaultFields>
63
+ extends CoValueBase
64
+ implements CoValue<"CoMap", RawCoMap>
65
+ {
66
+ id!: ID<this>;
67
+ _type!: "CoMap";
68
+ static {
69
+ this.prototype._type = "CoMap";
70
+ }
71
+ _raw!: RawCoMap;
72
+
73
+ static _encoding: any;
74
+ get _encoding(): {
75
+ [Key in OwnKeys<Fields>]: FieldDescriptorFor<Fields[Key]>;
76
+ } & {
77
+ [indexSignature]: indexSignature extends keyof Fields
78
+ ? FieldDescriptorFor<Fields[indexSignature]>
79
+ : never;
80
+ } {
81
+ return (this.constructor as typeof CoMap)._encoding;
82
+ }
83
+
84
+ get _refs(): {
85
+ [Key in OwnKeys<Fields> as NonNullable<Fields[Key]> extends CoValue
86
+ ? Key
87
+ : never]: NonNullable<Fields[Key]> extends CoValue
88
+ ? ValueRef<NonNullable<Fields[Key]>>
89
+ : never;
90
+ } {
91
+ return makeRefs<OwnKeys<Fields>>(
92
+ (key) => this._raw.get(key as string) as unknown as ID<CoValue>,
93
+ () =>
94
+ Object.keys(this._encoding).filter((key) => {
95
+ const schema = this._encoding[
96
+ key as keyof typeof this._encoding
97
+ ] as FieldDescriptor;
98
+ schema !== "json" && "ref" in schema;
99
+ }) as OwnKeys<Fields>[],
100
+ this._loadedAs,
101
+ (key) => (this._encoding[key] as RefField<CoValue>).ref()
102
+ ) as any;
103
+ }
104
+
105
+ get _edits(): {
106
+ [Key in OwnKeys<Fields>]: {
107
+ value?: Fields[Key];
108
+ ref?: Fields[Key] extends CoValue ? ValueRef<Fields[Key]> : never;
109
+ by?: Account;
110
+ madeAt: Date;
111
+ };
112
+ } {
113
+ return new Proxy(this, {
114
+ get(target, key) {
115
+ const rawEdit = target._raw.lastEditAt(key as string);
116
+ if (!rawEdit) return undefined;
117
+
118
+ const descriptor = target._encoding[
119
+ key as keyof typeof target._encoding
120
+ ] as FieldDescriptor;
121
+
122
+ return {
123
+ value:
124
+ descriptor === "json"
125
+ ? rawEdit.value
126
+ : "encoded" in descriptor
127
+ ? Schema.decodeSync(descriptor.encoded)(
128
+ rawEdit.value
129
+ )
130
+ : new ValueRef(
131
+ rawEdit.value as ID<CoValue>,
132
+ target._loadedAs,
133
+ descriptor.ref()
134
+ ).accessFrom(target),
135
+ ref:
136
+ descriptor !== "json" && "ref" in descriptor
137
+ ? new ValueRef(
138
+ rawEdit.value as ID<CoValue>,
139
+ target._loadedAs,
140
+ descriptor.ref()
141
+ )
142
+ : undefined,
143
+ by:
144
+ rawEdit.by &&
145
+ new ValueRef(
146
+ rawEdit.by as ID<Account>,
147
+ target._loadedAs,
148
+ Account
149
+ ).accessFrom(target),
150
+ madeAt: rawEdit.at,
151
+ };
152
+ },
153
+ }) as any;
154
+ }
155
+
156
+ get _loadedAs() {
157
+ return Account.fromNode(this._raw.core.node);
158
+ }
159
+
160
+ constructor(_init: undefined, options: { fromRaw: RawCoMap });
161
+ constructor(
162
+ init: Simplify<CoMapInit<Fields>>,
163
+ options: { owner: Account | Group }
164
+ );
165
+ constructor(
166
+ init: Simplify<CoMapInit<Fields>> | undefined,
167
+ options: { owner: Account | Group } | { fromRaw: RawCoMap }
168
+ ) {
169
+ super();
170
+
171
+ if (!this._encoding) {
172
+ throw new Error(
173
+ "No schema found in " +
174
+ this.constructor.name +
175
+ " - ensure that you have a `static { this.define({...}) }` block in the class definition."
176
+ );
177
+ }
178
+
179
+ const raw: RawCoMap = this.rawFromInit<Fields>(options, init);
180
+
181
+ Object.defineProperties(this, {
182
+ id: {
183
+ value: raw.id,
184
+ enumerable: false,
185
+ },
186
+ _raw: { value: raw, enumerable: false },
187
+ });
188
+
189
+ this.definePropertiesFromSchema();
190
+
191
+ if (this._encoding[indexSignature]) {
192
+ return new Proxy(this, CoMapProxyHandler<Fields>());
193
+ }
194
+ }
195
+
196
+ toJSON() {
197
+ const jsonedFields = this._raw.keys().map((key) => {
198
+ const tKey = key as OwnKeys<Fields>;
199
+ const descriptor = this._encoding[tKey] as FieldDescriptor;
200
+
201
+ if (descriptor == "json" || "encode" in descriptor) {
202
+ return [key, this._raw.get(key)];
203
+ } else if ("ref" in descriptor) {
204
+ const jsonedRef = (this as any)[tKey]?.toJSON();
205
+ return [key, jsonedRef];
206
+ } else {
207
+ return [key, undefined];
208
+ }
209
+ });
210
+
211
+ return {
212
+ id: this.id,
213
+ _type: this._type,
214
+ ...Object.fromEntries(jsonedFields),
215
+ };
216
+ }
217
+
218
+ [inspect]() {
219
+ return this.toJSON();
220
+ }
221
+
222
+ rawFromInit<Fields extends object = Record<string, any>>(
223
+ options: { owner: Account | Group } | { fromRaw: RawCoMap },
224
+ init: Simplify<CoMapInit<Fields>> | undefined
225
+ ) {
226
+ let raw: RawCoMap;
227
+
228
+ if ("fromRaw" in options) {
229
+ raw = options.fromRaw;
230
+ } else {
231
+ const rawOwner = options.owner._raw;
232
+
233
+ const rawInit = {} as {
234
+ [key in keyof Fields]: JsonValue | undefined;
235
+ };
236
+
237
+ if (init)
238
+ for (const key of Object.keys(init) as (keyof Fields)[]) {
239
+ const initValue = init[key as keyof typeof init];
240
+
241
+ const descriptor = (this._encoding[
242
+ key as keyof typeof this._encoding
243
+ ] || this._encoding[indexSignature]) as FieldDescriptor;
244
+
245
+ if (descriptor === "json") {
246
+ rawInit[key] = initValue as JsonValue;
247
+ } else if ("ref" in descriptor) {
248
+ if (initValue) {
249
+ rawInit[key] = (initValue as unknown as CoValue).id;
250
+ }
251
+ } else if ("encoded" in descriptor) {
252
+ rawInit[key] = Schema.encodeSync(descriptor.encoded)(
253
+ initValue as any
254
+ );
255
+ }
256
+ }
257
+
258
+ raw = rawOwner.createMap(rawInit);
259
+ }
260
+ return raw;
261
+ }
262
+
263
+ static encoding<V extends CoMap>(
264
+ this: { new (...args: any): V } & typeof CoMap,
265
+ fields: Simplify<{
266
+ [Key in keyof V["_encoding"] as V["_encoding"][Key] extends never
267
+ ? never
268
+ : Key]: Simplify<V["_encoding"][Key]>;
269
+ }>
270
+ ) {
271
+ this._encoding ||= {};
272
+ Object.assign(this._encoding, fields);
273
+ }
274
+
275
+ private definePropertiesFromSchema() {
276
+ for (const [key, fieldSchema] of Object.entries(this._encoding)) {
277
+ if (key === "indexSignature") continue;
278
+ const descriptor = fieldSchema as FieldDescriptor;
279
+ if (descriptor === "json") {
280
+ Object.defineProperty(
281
+ this,
282
+ key,
283
+ this.primitivePropDef(key as string)
284
+ );
285
+ } else if ("encoded" in descriptor) {
286
+ Object.defineProperty(
287
+ this,
288
+ key,
289
+ this.encodedPropDef(key as string, descriptor.encoded)
290
+ );
291
+ } else if ("ref" in descriptor) {
292
+ Object.defineProperty(
293
+ this,
294
+ key,
295
+ this.refPropDef(
296
+ key as string,
297
+ (descriptor as RefField<CoValue>).ref
298
+ )
299
+ );
300
+ }
301
+ }
302
+ }
303
+
304
+ private primitivePropDef(key: string): PropertyDescriptor {
305
+ return {
306
+ get: () => {
307
+ return this._raw.get(key);
308
+ },
309
+ set(this: CoMap, value: JsonValue) {
310
+ this._raw.set(key, value);
311
+ },
312
+ enumerable: true,
313
+ configurable: true,
314
+ };
315
+ }
316
+
317
+ private encodedPropDef(key: string, arg: Encoder<any>): PropertyDescriptor {
318
+ return {
319
+ get: () => {
320
+ const raw = this._raw.get(key);
321
+ return raw === undefined
322
+ ? undefined
323
+ : Schema.decodeSync(arg)(raw);
324
+ },
325
+ set(this: CoMap, value: unknown) {
326
+ this._raw.set(key, Schema.encodeSync(arg)(value));
327
+ },
328
+ enumerable: true,
329
+ configurable: true,
330
+ };
331
+ }
332
+
333
+ private refPropDef(
334
+ key: string,
335
+ ref: () => CoValueClass<CoValue>
336
+ ): PropertyDescriptor {
337
+ return {
338
+ get: () => {
339
+ const rawID = this._raw.get(key);
340
+ return rawID === undefined
341
+ ? undefined
342
+ : new ValueRef(
343
+ rawID as unknown as ID<CoValue>,
344
+ this._loadedAs,
345
+ ref()
346
+ ).accessFrom(this);
347
+ },
348
+ set: (value: CoValue) => {
349
+ this._raw.set(key, value.id);
350
+ subscriptionsScopes.get(this)?.onRefAccessedOrSet(value.id);
351
+ },
352
+ enumerable: true,
353
+ configurable: true,
354
+ };
355
+ }
356
+ }
357
+
358
+ export type OwnKeys<Fields extends object> = Exclude<
359
+ keyof Fields & string,
360
+ keyof CoMap<Record<string, never>> | `_${string}`
361
+ >;
362
+
363
+ export type CoMapInit<Fields extends object> = {
364
+ [Key in OwnKeys<Fields> as undefined extends Fields[Key]
365
+ ? never
366
+ : null extends Fields[Key]
367
+ ? never
368
+ : Key]: Fields[Key];
369
+ } & { [Key in OwnKeys<Fields>]?: Fields[Key] };
370
+
371
+ // TODO: cache handlers per descriptor for performance?
372
+ function CoMapProxyHandler<Fields extends EnsureValid<Fields>>(): ProxyHandler<
373
+ CoMap<Fields>
374
+ > {
375
+ return {
376
+ get(target, key, receiver) {
377
+ const descriptor = target._encoding[
378
+ indexSignature
379
+ ] as FieldDescriptor;
380
+ if (key in target || typeof key === "symbol") {
381
+ return Reflect.get(target, key, receiver);
382
+ } else {
383
+ const raw = target._raw.get(key);
384
+
385
+ if (descriptor === "json") {
386
+ return raw;
387
+ } else if ("encoded" in descriptor) {
388
+ return raw === undefined
389
+ ? undefined
390
+ : Schema.decodeSync(descriptor.encoded)(raw);
391
+ } else if ("ref" in descriptor) {
392
+ return raw === undefined
393
+ ? undefined
394
+ : new ValueRef(
395
+ raw as unknown as ID<CoValue>,
396
+ target._loadedAs,
397
+ descriptor.ref()
398
+ ).accessFrom(target);
399
+ }
400
+ }
401
+ },
402
+ set(target, key, value, receiver) {
403
+ const descriptor = target._encoding[
404
+ indexSignature
405
+ ] as FieldDescriptor;
406
+ if (key in target || typeof key === "symbol") {
407
+ return Reflect.set(target, key, value, receiver);
408
+ } else {
409
+ if (descriptor === "json") {
410
+ target._raw.set(key, value);
411
+ } else if ("encoded" in descriptor) {
412
+ target._raw.set(
413
+ key,
414
+ Schema.encodeSync(descriptor.encoded)(value)
415
+ );
416
+ } else if ("ref" in descriptor) {
417
+ target._raw.set(key, value.id);
418
+ subscriptionsScopes
419
+ .get(target)
420
+ ?.onRefAccessedOrSet(value.id);
421
+ }
422
+ return true;
423
+ }
424
+ },
425
+ ownKeys(target) {
426
+ const keys = Reflect.ownKeys(target);
427
+ for (const key of target._raw.keys()) {
428
+ if (!keys.includes(key)) {
429
+ keys.push(key);
430
+ }
431
+ }
432
+
433
+ return keys;
434
+ },
435
+ getOwnPropertyDescriptor(target, key) {
436
+ if (key in target) {
437
+ return Reflect.getOwnPropertyDescriptor(target, key);
438
+ } else if (key in target._raw.ops) {
439
+ return {
440
+ enumerable: true,
441
+ configurable: true,
442
+ writable: true,
443
+ };
444
+ }
445
+ },
446
+ };
447
+ }