jazz-tools 0.7.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.eslintrc.cjs +24 -0
  2. package/.turbo/turbo-build.log +24 -0
  3. package/CHANGELOG.md +42 -0
  4. package/LICENSE.txt +19 -0
  5. package/README.md +3 -0
  6. package/dist/coValueInterfaces.js +8 -0
  7. package/dist/coValueInterfaces.js.map +1 -0
  8. package/dist/coValues/account/account.js +11 -0
  9. package/dist/coValues/account/account.js.map +1 -0
  10. package/dist/coValues/account/accountOf.js +150 -0
  11. package/dist/coValues/account/accountOf.js.map +1 -0
  12. package/dist/coValues/account/migration.js +4 -0
  13. package/dist/coValues/account/migration.js.map +1 -0
  14. package/dist/coValues/coList/coList.js +2 -0
  15. package/dist/coValues/coList/coList.js.map +1 -0
  16. package/dist/coValues/coList/coListOf.js +235 -0
  17. package/dist/coValues/coList/coListOf.js.map +1 -0
  18. package/dist/coValues/coList/internalDocs.js +2 -0
  19. package/dist/coValues/coList/internalDocs.js.map +1 -0
  20. package/dist/coValues/coMap/coMap.js +2 -0
  21. package/dist/coValues/coMap/coMap.js.map +1 -0
  22. package/dist/coValues/coMap/coMapOf.js +262 -0
  23. package/dist/coValues/coMap/coMapOf.js.map +1 -0
  24. package/dist/coValues/coMap/internalDocs.js +2 -0
  25. package/dist/coValues/coMap/internalDocs.js.map +1 -0
  26. package/dist/coValues/coStream/coStream.js +2 -0
  27. package/dist/coValues/coStream/coStream.js.map +1 -0
  28. package/dist/coValues/coStream/coStreamOf.js +244 -0
  29. package/dist/coValues/coStream/coStreamOf.js.map +1 -0
  30. package/dist/coValues/construction.js +34 -0
  31. package/dist/coValues/construction.js.map +1 -0
  32. package/dist/coValues/extensions/imageDef.js +36 -0
  33. package/dist/coValues/extensions/imageDef.js.map +1 -0
  34. package/dist/coValues/group/group.js +2 -0
  35. package/dist/coValues/group/group.js.map +1 -0
  36. package/dist/coValues/group/groupOf.js +109 -0
  37. package/dist/coValues/group/groupOf.js.map +1 -0
  38. package/dist/coValues/resolution.js +66 -0
  39. package/dist/coValues/resolution.js.map +1 -0
  40. package/dist/errors.js +2 -0
  41. package/dist/errors.js.map +1 -0
  42. package/dist/index.js +31 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/refs.js +95 -0
  45. package/dist/refs.js.map +1 -0
  46. package/dist/schemaHelpers.js +14 -0
  47. package/dist/schemaHelpers.js.map +1 -0
  48. package/dist/subscriptionScope.js +81 -0
  49. package/dist/subscriptionScope.js.map +1 -0
  50. package/dist/tests/coList.test.js +207 -0
  51. package/dist/tests/coList.test.js.map +1 -0
  52. package/dist/tests/coMap.test.js +238 -0
  53. package/dist/tests/coMap.test.js.map +1 -0
  54. package/dist/tests/coStream.test.js +263 -0
  55. package/dist/tests/coStream.test.js.map +1 -0
  56. package/dist/tests/types.test.js +33 -0
  57. package/dist/tests/types.test.js.map +1 -0
  58. package/package.json +23 -0
  59. package/src/coValueInterfaces.ts +105 -0
  60. package/src/coValues/account/account.ts +106 -0
  61. package/src/coValues/account/accountOf.ts +284 -0
  62. package/src/coValues/account/migration.ts +12 -0
  63. package/src/coValues/coList/coList.ts +57 -0
  64. package/src/coValues/coList/coListOf.ts +377 -0
  65. package/src/coValues/coList/internalDocs.ts +1 -0
  66. package/src/coValues/coMap/coMap.ts +110 -0
  67. package/src/coValues/coMap/coMapOf.ts +451 -0
  68. package/src/coValues/coMap/internalDocs.ts +1 -0
  69. package/src/coValues/coStream/coStream.ts +63 -0
  70. package/src/coValues/coStream/coStreamOf.ts +404 -0
  71. package/src/coValues/construction.ts +110 -0
  72. package/src/coValues/extensions/imageDef.ts +51 -0
  73. package/src/coValues/group/group.ts +27 -0
  74. package/src/coValues/group/groupOf.ts +183 -0
  75. package/src/coValues/resolution.ts +111 -0
  76. package/src/errors.ts +1 -0
  77. package/src/index.ts +68 -0
  78. package/src/refs.ts +128 -0
  79. package/src/schemaHelpers.ts +72 -0
  80. package/src/subscriptionScope.ts +118 -0
  81. package/src/tests/coList.test.ts +283 -0
  82. package/src/tests/coMap.test.ts +357 -0
  83. package/src/tests/coStream.test.ts +415 -0
  84. package/src/tests/types.test.ts +37 -0
  85. package/tsconfig.json +15 -0
@@ -0,0 +1,451 @@
1
+ import {
2
+ ID,
3
+ isCoValueSchema,
4
+ isCoValue,
5
+ CoValue,
6
+ inspect,
7
+ CoValueSchema,
8
+ } from "../../coValueInterfaces.js";
9
+ import {
10
+ CoMapFields,
11
+ CoMapInit,
12
+ CoMapSchema,
13
+ CoMap,
14
+ IndexSignature,
15
+ CoMapBase,
16
+ NoIndexSignature,
17
+ } from "./coMap.js";
18
+ import { ValueRef, makeRefs } from "../../refs.js";
19
+ import { JsonValue, RawAccount, RawCoMap, cojsonInternals } from "cojson";
20
+ import { AnyGroup } from "../group/group.js";
21
+ import { AnyAccount, ControlledAccount } from "../account/account.js";
22
+ import { Account, controlledAccountFromNode } from "../account/accountOf.js";
23
+ import { subscriptionsScopes } from "../../subscriptionScope.js";
24
+ import { AST, Schema } from "@effect/schema";
25
+ import {
26
+ constructorOfSchemaSym,
27
+ propertyIsCoValueSchema,
28
+ } from "../resolution.js";
29
+ import { JsonObject } from "cojson/src/jsonValue.js";
30
+ import { SharedCoValueConstructor } from "../construction.js";
31
+ import {
32
+ PropertySignatureWithOutput,
33
+ propSigToSchema,
34
+ } from "../../schemaHelpers.js";
35
+ import { pipeArguments } from "effect/Pipeable";
36
+ import { Group } from "../group/groupOf.js";
37
+
38
+ export function CoMapOf<
39
+ Fields extends CoMapFields,
40
+ IndexSig extends IndexSignature = NoIndexSignature,
41
+ >(fields: Fields, indexSignature?: IndexSig) {
42
+ class CoMapOfFields
43
+ extends SharedCoValueConstructor
44
+ implements CoMapBase<Fields, IndexSig>
45
+ {
46
+ static get ast() {
47
+ return AST.setAnnotation(
48
+ Schema.instanceOf(this).ast,
49
+ constructorOfSchemaSym,
50
+ this
51
+ );
52
+ }
53
+ static [Schema.TypeId]: Schema.Schema.Variance<
54
+ CoMapOfFields,
55
+ CoMapOfFields,
56
+ never
57
+ >[Schema.TypeId];
58
+ static pipe() {
59
+ // eslint-disable-next-line prefer-rest-params
60
+ return pipeArguments(this, arguments);
61
+ }
62
+ static type = "CoMap" as const;
63
+
64
+ id!: ID<this>;
65
+ _type!: "CoMap";
66
+ _owner!: AnyAccount | AnyGroup;
67
+ _refs!: CoMapBase<Fields, IndexSig>["_refs"];
68
+ _edits!: CoMapBase<Fields, IndexSig>["_edits"];
69
+ _raw!: RawCoMap;
70
+ _loadedAs!: ControlledAccount;
71
+ _schema!: typeof CoMapOfFields;
72
+
73
+ constructor(_init: undefined, options: { fromRaw: RawCoMap });
74
+ constructor(
75
+ init: CoMapInit<Fields>,
76
+ options: { owner: AnyAccount | AnyGroup }
77
+ );
78
+ constructor(
79
+ init: CoMapInit<Fields> | undefined,
80
+ options: { owner: AnyAccount | AnyGroup } | { fromRaw: RawCoMap }
81
+ ) {
82
+ super();
83
+
84
+ let raw: RawCoMap;
85
+
86
+ if ("fromRaw" in options) {
87
+ raw = options.fromRaw;
88
+ } else {
89
+ const rawOwner = options.owner._raw;
90
+
91
+ const rawInit = {} as {
92
+ [key in keyof CoMapInit<Fields>]: JsonValue | undefined;
93
+ };
94
+
95
+ if (init)
96
+ for (const key of Object.keys(
97
+ init
98
+ ) as (keyof CoMapInit<Fields>)[]) {
99
+ const initValue = init[key];
100
+ const field =
101
+ fields[key] ||
102
+ (indexSignature &&
103
+ Schema.is(indexSignature.key)(key) &&
104
+ indexSignature.value);
105
+
106
+ if (!field) {
107
+ throw new Error(`Key ${String(key)} not in schema`);
108
+ }
109
+
110
+ if (propertyIsCoValueSchema(field)) {
111
+ // TOOD: check for alignment of actual value with schema
112
+ if (isCoValue(initValue)) {
113
+ rawInit[key] = initValue.id;
114
+ } else {
115
+ throw new Error(
116
+ `Expected covalue in ${String(
117
+ key
118
+ )} but got ${initValue}`
119
+ );
120
+ }
121
+ } else {
122
+ const fieldSchema = (
123
+ "propertySignatureAST" in field
124
+ ? Schema.make<JsonObject, any, never>(
125
+ (
126
+ field.propertySignatureAST as {
127
+ from: AST.AST;
128
+ }
129
+ ).from
130
+ )
131
+ : field
132
+ ) as Schema.Schema<JsonObject, any, never>;
133
+ rawInit[key] =
134
+ Schema.encodeSync(fieldSchema)(initValue);
135
+ }
136
+ }
137
+
138
+ raw = rawOwner.createMap(rawInit);
139
+ }
140
+
141
+ for (const key of Object.keys(fields) as (keyof Fields)[]) {
142
+ if (typeof key !== "string") continue;
143
+
144
+ const fieldSchema = fields[key]!;
145
+ if (propertyIsCoValueSchema(fieldSchema)) {
146
+ Object.defineProperty(this, key, {
147
+ get(this: CoMapOfFields) {
148
+ return this.getCoValueAtKey(key);
149
+ },
150
+ set(this: CoMapOfFields, value) {
151
+ this.setCoValueAtKey(key, value);
152
+ },
153
+ enumerable: true,
154
+ });
155
+ } else {
156
+ Object.defineProperty(this, key, {
157
+ get(this: CoMapOfFields) {
158
+ return this.getPrimitiveAtKey(key, fieldSchema);
159
+ },
160
+ set(this: CoMapOfFields, value) {
161
+ this.setPrimitiveAtKey(key, value, fieldSchema);
162
+ },
163
+ enumerable: true,
164
+ });
165
+ }
166
+ }
167
+
168
+ const fieldsThatAreRefs = Object.entries(fields)
169
+ .filter(([_, value]) => isCoValueSchema(value))
170
+ .map(([key]) => key);
171
+
172
+ const refs = makeRefs<
173
+ {
174
+ [Key in keyof Fields]: Fields[Key] extends CoValueSchema
175
+ ? Exclude<Schema.Schema.To<Fields[Key]>, undefined>
176
+ : never;
177
+ } & {
178
+ [Key in Schema.Schema.To<IndexSig["key"]>]: Exclude<
179
+ Schema.Schema.To<IndexSig["value"]>,
180
+ undefined
181
+ >;
182
+ }
183
+ >(
184
+ (key) => {
185
+ return raw.get(key as string) as
186
+ | ID<
187
+ Schema.Schema.To<
188
+ Fields[typeof key] & CoValueSchema
189
+ >
190
+ >
191
+ | undefined;
192
+ },
193
+ () => {
194
+ if (indexSignature) {
195
+ return raw
196
+ .keys()
197
+ .filter(
198
+ (key) =>
199
+ fieldsThatAreRefs.includes(key) ||
200
+ Schema.is(indexSignature.key)(key)
201
+ );
202
+ } else {
203
+ return fieldsThatAreRefs;
204
+ }
205
+ },
206
+ controlledAccountFromNode(raw.core.node),
207
+ (key) =>
208
+ fields[key] ||
209
+ (indexSignature
210
+ ? indexSignature.value
211
+ : (() => {
212
+ throw new Error(
213
+ "Expected " + String(key) + " to be valid"
214
+ );
215
+ })())
216
+ );
217
+
218
+ const getEdits = () =>
219
+ new Proxy(this, {
220
+ get(target, key, receiver) {
221
+ const schemaAtKey =
222
+ fields[key as keyof Fields] ||
223
+ (indexSignature &&
224
+ Schema.is(indexSignature?.key)(key)
225
+ ? indexSignature?.value
226
+ : undefined);
227
+ if (!schemaAtKey)
228
+ return Reflect.get(target, key, receiver);
229
+
230
+ const rawEdit = raw.lastEditAt(key as string);
231
+ if (!rawEdit) return undefined;
232
+
233
+ return {
234
+ get value() {
235
+ if (isCoValueSchema(schemaAtKey)) {
236
+ return this.ref?.accessFrom(target);
237
+ } else {
238
+ return (
239
+ rawEdit?.value &&
240
+ Schema.decodeSync(
241
+ propSigToSchema(schemaAtKey)
242
+ )(rawEdit?.value)
243
+ );
244
+ }
245
+ },
246
+
247
+ get ref() {
248
+ if (isCoValueSchema(schemaAtKey)) {
249
+ return (
250
+ rawEdit?.value &&
251
+ new ValueRef(
252
+ rawEdit?.value as ID<CoValue>,
253
+ target._loadedAs,
254
+ schemaAtKey
255
+ )
256
+ );
257
+ }
258
+ },
259
+
260
+ get by() {
261
+ if (cojsonInternals.isAccountID(rawEdit.by)) {
262
+ return new ValueRef(
263
+ rawEdit.by as unknown as ID<AnyAccount>,
264
+ target._loadedAs,
265
+ Account
266
+ ).accessFrom(target);
267
+ }
268
+ },
269
+
270
+ madeAt: rawEdit.at,
271
+ tx: rawEdit.tx,
272
+ };
273
+ },
274
+ });
275
+
276
+ Object.defineProperties(this, {
277
+ id: {
278
+ value: raw.id as unknown as ID<
279
+ this & CoMap<Fields, IndexSig>
280
+ >,
281
+ enumerable: false,
282
+ },
283
+ _type: { value: "CoMap", enumerable: false },
284
+ _owner: {
285
+ get: () =>
286
+ raw.group instanceof RawAccount
287
+ ? Account.fromRaw(raw.group)
288
+ : Group.fromRaw(raw.group),
289
+ enumerable: false,
290
+ },
291
+ _refs: { value: refs, enumerable: false },
292
+ _edits: { get: getEdits, enumerable: false },
293
+ _raw: { value: raw, enumerable: false },
294
+ _loadedAs: {
295
+ get: () => controlledAccountFromNode(raw.core.node),
296
+ enumerable: false,
297
+ },
298
+ _schema: {
299
+ value: this.constructor,
300
+ enumerable: false,
301
+ },
302
+ });
303
+
304
+ if (indexSignature) {
305
+ return new Proxy(this, {
306
+ get(target, key) {
307
+ if (key in target) {
308
+ return Reflect.get(target, key);
309
+ } else {
310
+ if (Schema.is(indexSignature.key)(key as string)) {
311
+ if (
312
+ propertyIsCoValueSchema(
313
+ indexSignature.value
314
+ )
315
+ ) {
316
+ return target.getCoValueAtKey(
317
+ key as string
318
+ );
319
+ } else {
320
+ return target.getPrimitiveAtKey(
321
+ key as string,
322
+ indexSignature.value
323
+ );
324
+ }
325
+ } else {
326
+ throw new Error(
327
+ "No such key " + String(key) + " in CoMap"
328
+ );
329
+ }
330
+ }
331
+ },
332
+ set(target, key, value) {
333
+ if (key in target) {
334
+ return Reflect.set(target, key, value);
335
+ } else if (
336
+ Schema.is(indexSignature.key)(key as string)
337
+ ) {
338
+ if (propertyIsCoValueSchema(indexSignature.value)) {
339
+ target.setCoValueAtKey(key as string, value);
340
+ } else {
341
+ target.setPrimitiveAtKey(
342
+ key as string,
343
+ value,
344
+ indexSignature.value
345
+ );
346
+ }
347
+ return true;
348
+ } else {
349
+ throw new Error(
350
+ "No such key " + String(key) + " in CoMap"
351
+ );
352
+ }
353
+ },
354
+ ownKeys(target) {
355
+ const keys = Reflect.ownKeys(target);
356
+ for (const key of target._raw.keys()) {
357
+ if (!keys.includes(key)) {
358
+ if (
359
+ Schema.is(indexSignature.key)(key as string)
360
+ ) {
361
+ keys.push(key);
362
+ }
363
+ }
364
+ }
365
+ return keys;
366
+ },
367
+ getOwnPropertyDescriptor(target, key) {
368
+ if (key in target) {
369
+ return Reflect.getOwnPropertyDescriptor(
370
+ target,
371
+ key
372
+ );
373
+ } else if (
374
+ Schema.is(indexSignature.key)(key as string)
375
+ ) {
376
+ return {
377
+ enumerable: true,
378
+ configurable: true,
379
+ };
380
+ }
381
+ },
382
+ });
383
+ }
384
+ }
385
+
386
+ static fromRaw(raw: RawCoMap): CoMapOfFields {
387
+ return new CoMapOfFields(undefined, { fromRaw: raw });
388
+ }
389
+
390
+ private getCoValueAtKey(key: string) {
391
+ return this._refs[key as keyof this["_refs"]]?.accessFrom(this);
392
+ }
393
+
394
+ private setCoValueAtKey(key: string, value: CoValue) {
395
+ this._raw.set(key, value.id);
396
+ subscriptionsScopes.get(this)?.onRefAccessedOrSet(value.id);
397
+ }
398
+
399
+ private getPrimitiveAtKey(
400
+ key: string,
401
+ schemaAtKey:
402
+ | Schema.Schema<any, JsonValue | undefined, never>
403
+ | PropertySignatureWithOutput<JsonValue | undefined>
404
+ ) {
405
+ return Schema.decodeSync(propSigToSchema(schemaAtKey))(
406
+ this._raw.get(key)
407
+ );
408
+ }
409
+
410
+ private setPrimitiveAtKey(
411
+ key: string,
412
+ value: any,
413
+ schemaAtKey:
414
+ | Schema.Schema<any, JsonValue | undefined, never>
415
+ | PropertySignatureWithOutput<JsonValue | undefined>
416
+ ) {
417
+ this._raw.set(
418
+ key,
419
+ Schema.encodeSync(propSigToSchema(schemaAtKey))(value) as
420
+ | JsonValue
421
+ | undefined
422
+ );
423
+ }
424
+
425
+ toJSON() {
426
+ return Object.fromEntries(
427
+ Object.entries(this).flatMap(([key, value]) =>
428
+ typeof value === "object" && "toJSON" in value
429
+ ? [[key, value?.toJSON()]]
430
+ : [[key, value]]
431
+ )
432
+ );
433
+ }
434
+
435
+ [inspect]() {
436
+ return this.toJSON();
437
+ }
438
+
439
+ static as<SubClass>() {
440
+ return CoMapOfFields as unknown as CoMapSchema<
441
+ SubClass,
442
+ Fields,
443
+ IndexSig
444
+ >;
445
+ }
446
+ }
447
+
448
+ return CoMapOfFields as CoMapSchema<CoMapOfFields, Fields, IndexSig> & {
449
+ as<SubClass>(): CoMapSchema<SubClass, Fields, IndexSig>;
450
+ };
451
+ }
@@ -0,0 +1 @@
1
+ export { CoMapBase, CoMapInit } from "./coMap.js";
@@ -0,0 +1,63 @@
1
+ import {
2
+ BinaryStreamInfo,
3
+ CojsonInternalTypes,
4
+ JsonValue,
5
+ RawBinaryCoStream,
6
+ RawCoStream,
7
+ SessionID,
8
+ } from "cojson";
9
+ import {
10
+ CoValue,
11
+ CoValueSchema,
12
+ ID,
13
+ } from "../../coValueInterfaces.js";
14
+ import { AnyAccount } from "../account/account.js";
15
+ import { ValueRef } from "../../refs.js";
16
+ import { SchemaWithOutput } from "../../schemaHelpers.js";
17
+ import { Schema } from "@effect/schema";
18
+
19
+ export type CoStreamEntry<Item extends SchemaWithOutput<CoValue> | SchemaWithOutput<JsonValue>> = {
20
+ value: Item extends CoValueSchema<infer Self> ? Self | undefined : Schema.Schema.To<Item>;
21
+ ref?: Item extends CoValueSchema<infer Self, infer Value> ? ValueRef<Self & Value> : never;
22
+ by?: AnyAccount;
23
+ madeAt: Date;
24
+ tx: CojsonInternalTypes.TransactionID;
25
+ }
26
+
27
+ export type CoStream<Item extends SchemaWithOutput<CoValue> | SchemaWithOutput<JsonValue>> =
28
+ CoValue<"CoStream", RawCoStream> & {
29
+ by: { [key: ID<AnyAccount>]: CoStreamEntry<Item>, me: CoStreamEntry<Item> };
30
+ in: { [key: SessionID]: CoStreamEntry<Item>, currentSession: CoStreamEntry<Item> };
31
+ push(...items: Schema.Schema.To<Item>[]): void;
32
+ };
33
+
34
+ export interface CoStreamSchema<
35
+ Self,
36
+ Item extends CoValueSchema | SchemaWithOutput<JsonValue>,
37
+ > extends CoValueSchema<
38
+ Self,
39
+ CoStream<Item>,
40
+ "CoStream",
41
+ Schema.Schema.To<Item>[]
42
+ > {}
43
+
44
+ export interface BinaryCoStream
45
+ extends CoValue<"BinaryCoStream", RawBinaryCoStream> {
46
+ start(options: BinaryStreamInfo): void;
47
+ push(data: Uint8Array): void;
48
+ end(): void;
49
+ getChunks(options?: { allowUnfinished?: boolean }):
50
+ | (BinaryStreamInfo & {
51
+ chunks: Uint8Array[];
52
+ finished: boolean;
53
+ })
54
+ | undefined;
55
+ }
56
+
57
+ export interface BinaryCoStreamSchema
58
+ extends CoValueSchema<
59
+ BinaryCoStream,
60
+ BinaryCoStream,
61
+ "BinaryCoStream",
62
+ undefined
63
+ > {}