jazz-tools 0.7.0-alpha.0

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