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

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 +84 -9
  2. package/CHANGELOG.md +110 -0
  3. package/dist/coValues/account.js +66 -33
  4. package/dist/coValues/account.js.map +1 -1
  5. package/dist/coValues/coList.js +147 -97
  6. package/dist/coValues/coList.js.map +1 -1
  7. package/dist/coValues/coMap.js +151 -164
  8. package/dist/coValues/coMap.js.map +1 -1
  9. package/dist/coValues/coStream.js +176 -70
  10. package/dist/coValues/coStream.js.map +1 -1
  11. package/dist/coValues/extensions/imageDef.js +10 -7
  12. package/dist/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/coValues/group.js +13 -35
  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 -3
  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 +108 -38
  26. package/dist/tests/coMap.test.js.map +1 -1
  27. package/dist/tests/coStream.test.js +46 -51
  28. package/dist/tests/coStream.test.js.map +1 -1
  29. package/package.json +5 -4
  30. package/src/coValues/account.ts +98 -68
  31. package/src/coValues/coList.ts +188 -120
  32. package/src/coValues/coMap.ts +232 -276
  33. package/src/coValues/coStream.ts +265 -124
  34. package/src/coValues/extensions/imageDef.ts +7 -12
  35. package/src/coValues/group.ts +33 -80
  36. package/src/coValues/interfaces.ts +12 -10
  37. package/src/implementation/refs.ts +45 -18
  38. package/src/implementation/schema.ts +86 -31
  39. package/src/index.ts +10 -8
  40. package/src/tests/coList.test.ts +5 -9
  41. package/src/tests/coMap.test.ts +89 -53
  42. package/src/tests/coStream.test.ts +61 -66
@@ -11,59 +11,81 @@ import type {
11
11
  import { cojsonInternals } from "cojson";
12
12
  import type {
13
13
  CoValue,
14
- EnsureItemNullable,
15
- FieldDescriptor,
16
- FieldDescriptorFor,
14
+ ValidItem,
15
+ Schema,
16
+ SchemaFor,
17
17
  Group,
18
18
  ID,
19
19
  Me,
20
+ IfCo,
20
21
  } from "../internal.js";
21
- import { Account, CoValueBase, ValueRef, inspect } from "../internal.js";
22
- import { Schema } from "@effect/schema";
22
+ import {
23
+ ItemsSym,
24
+ Account,
25
+ CoValueBase,
26
+ Ref,
27
+ inspect,
28
+ co,
29
+ InitValues,
30
+ SchemaInit,
31
+ isRefEncoded,
32
+ } from "../internal.js";
33
+ import { encodeSync, decodeSync } from "@effect/schema/Schema";
34
+
35
+ export type CoStreamEntry<Item> = SingleCoStreamEntry<Item> & {
36
+ all: IterableIterator<SingleCoStreamEntry<Item>>;
37
+ };
23
38
 
24
- export type CoStreamEntry<Item> = {
39
+ export type SingleCoStreamEntry<Item> = {
25
40
  value: NonNullable<Item> extends CoValue ? NonNullable<Item> | null : Item;
26
- ref?: NonNullable<Item> extends CoValue
27
- ? ValueRef<NonNullable<Item>>
28
- : never;
29
- by?: Account;
41
+ ref: NonNullable<Item> extends CoValue ? Ref<NonNullable<Item>> : never;
42
+ by?: Account | null;
30
43
  madeAt: Date;
31
44
  tx: CojsonInternalTypes.TransactionID;
32
45
  };
33
46
 
34
- export class CoStream<Item extends EnsureItemNullable<Item, "Co.Stream"> = any>
47
+ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
35
48
  extends CoValueBase
36
49
  implements CoValue<"CoStream", RawCoStream>
37
50
  {
38
- id!: ID<this>;
39
- _type!: "CoStream";
51
+ static Of<Item extends ValidItem<Item, "CoStream"> = any>(
52
+ item: IfCo<Item, Item>
53
+ ): typeof CoStream<Item> {
54
+ return class CoStreamOf extends CoStream<Item> {
55
+ [co.items] = item;
56
+ };
57
+ }
58
+
59
+ declare id: ID<this>;
60
+ declare _type: "CoStream";
40
61
  static {
41
62
  this.prototype._type = "CoStream";
42
63
  }
43
- _raw!: RawCoStream;
64
+ declare _raw: RawCoStream;
44
65
 
45
66
  /** @internal This is only a marker type and doesn't exist at runtime */
46
- _item!: Item;
47
- static _encoding: any;
48
- get _encoding(): {
49
- _item: FieldDescriptorFor<Item>;
67
+ [ItemsSym]!: Item;
68
+ static _schema: any;
69
+ get _schema(): {
70
+ [ItemsSym]: SchemaFor<Item>;
50
71
  } {
51
- return (this.constructor as typeof CoStream)._encoding;
72
+ return (this.constructor as typeof CoStream)._schema;
52
73
  }
53
74
 
54
- by: {
55
- [key: ID<Account>]: CoStreamEntry<Item>;
56
- } = {};
75
+ [key: ID<Account>]: CoStreamEntry<Item>;
76
+
57
77
  get byMe(): CoStreamEntry<Item> | undefined {
58
- return this.by[this._loadedAs.id];
78
+ return this[this._loadedAs.id];
59
79
  }
60
- in: {
80
+ perSession!: {
61
81
  [key: SessionID]: CoStreamEntry<Item>;
62
- } = {};
82
+ };
63
83
  get inCurrentSession(): CoStreamEntry<Item> | undefined {
64
- return this.in[this._loadedAs.sessionID];
84
+ return this.perSession[this._loadedAs.sessionID];
65
85
  }
66
86
 
87
+ [InitValues]?: any;
88
+
67
89
  constructor(_init: undefined, options: { fromRaw: RawCoStream });
68
90
  constructor(init: Item[], options: { owner: Account | Group });
69
91
  constructor(
@@ -72,120 +94,64 @@ export class CoStream<Item extends EnsureItemNullable<Item, "Co.Stream"> = any>
72
94
  ) {
73
95
  super();
74
96
 
75
- let raw: RawCoStream;
76
-
77
97
  if ("fromRaw" in options) {
78
- raw = options.fromRaw;
79
- } else {
80
- const rawOwner = options.owner._raw;
81
-
82
- raw = rawOwner.createStream();
83
- }
84
-
85
- Object.defineProperties(this, {
86
- id: {
87
- value: raw.id,
88
- enumerable: false,
89
- },
90
- _raw: { value: raw, enumerable: false },
91
- });
92
-
93
- if (init !== undefined) {
94
- for (const item of init) {
95
- this.pushItem(item);
96
- }
97
- }
98
-
99
- this.updateEntries();
100
- }
101
-
102
- private updateEntries() {
103
- for (const accountID of this._raw.accounts()) {
104
- Object.defineProperty(this.by, accountID, {
105
- get: () => {
106
- const rawEntry = this._raw.lastItemBy(accountID);
107
-
108
- if (!rawEntry) return;
109
- return entryFromRawEntry(
110
- this,
111
- rawEntry,
112
- this._loadedAs,
113
- accountID as unknown as ID<Account>,
114
- this._encoding._item
115
- );
98
+ Object.defineProperties(this, {
99
+ id: {
100
+ value: options.fromRaw.id,
101
+ enumerable: false,
116
102
  },
117
- configurable: true,
118
- enumerable: true,
103
+ _raw: { value: options.fromRaw, enumerable: false },
119
104
  });
105
+ } else {
106
+ this[InitValues] = {
107
+ init,
108
+ owner: options.owner,
109
+ };
120
110
  }
121
111
 
122
- for (const sessionID of this._raw.sessions()) {
123
- Object.defineProperty(this.in, sessionID, {
124
- get: () => {
125
- const rawEntry = this._raw.lastItemIn(
126
- sessionID as unknown as SessionID
127
- );
128
-
129
- if (!rawEntry) return;
130
- const by =
131
- cojsonInternals.accountOrAgentIDfromSessionID(
132
- sessionID
133
- );
134
- return entryFromRawEntry(
135
- this,
136
- rawEntry,
137
- this._loadedAs,
138
- cojsonInternals.isAccountID(by)
139
- ? (by as unknown as ID<Account>)
140
- : undefined,
141
- this._encoding._item
142
- );
143
- },
144
- configurable: true,
145
- enumerable: true,
146
- });
147
- }
112
+ return new Proxy(this, CoStreamProxyHandler as ProxyHandler<this>);
148
113
  }
149
114
 
150
115
  push(...items: Item[]) {
151
116
  for (const item of items) {
152
117
  this.pushItem(item);
153
118
  }
154
- this.updateEntries();
155
119
  }
156
120
 
157
121
  private pushItem(item: Item) {
158
- const itemDescriptor = this._encoding._item as FieldDescriptor;
122
+ const itemDescriptor = this._schema[ItemsSym] as Schema;
159
123
 
160
124
  if (itemDescriptor === "json") {
161
125
  this._raw.push(item as JsonValue);
162
126
  } else if ("encoded" in itemDescriptor) {
163
- this._raw.push(Schema.encodeSync(itemDescriptor.encoded)(item));
164
- } else if ("ref" in itemDescriptor) {
127
+ this._raw.push(
128
+ encodeSync(itemDescriptor.encoded)(item)
129
+ );
130
+ } else if (isRefEncoded(itemDescriptor)) {
165
131
  this._raw.push((item as unknown as CoValue).id);
166
132
  }
167
133
  }
168
134
 
169
135
  toJSON() {
170
- const itemDescriptor = this._encoding._item as FieldDescriptor;
136
+ const itemDescriptor = this._schema[ItemsSym] as Schema;
171
137
  const mapper =
172
138
  itemDescriptor === "json"
173
139
  ? (v: unknown) => v
174
140
  : "encoded" in itemDescriptor
175
- ? Schema.encodeSync(itemDescriptor.encoded)
141
+ ? encodeSync(itemDescriptor.encoded)
176
142
  : (v: unknown) => v && (v as CoValue).id;
177
143
 
178
144
  return {
179
145
  id: this.id,
180
146
  _type: this._type,
181
- by: Object.fromEntries(
182
- Object.entries(this.by).map(([account, entry]) => [
147
+ ...Object.fromEntries(
148
+ Object.entries(this).map(([account, entry]) => [
183
149
  account,
184
150
  mapper(entry.value),
185
151
  ])
186
152
  ),
187
153
  in: Object.fromEntries(
188
- Object.entries(this.in).map(([session, entry]) => [
154
+ Object.entries(this.perSession).map(([session, entry]) => [
189
155
  session,
190
156
  mapper(entry.value),
191
157
  ])
@@ -197,12 +163,12 @@ export class CoStream<Item extends EnsureItemNullable<Item, "Co.Stream"> = any>
197
163
  return this.toJSON();
198
164
  }
199
165
 
200
- static encoding<V extends CoStream>(
166
+ static schema<V extends CoStream>(
201
167
  this: { new (...args: any): V } & typeof CoStream,
202
- def: { _item: V["_encoding"]["_item"] }
168
+ def: { [ItemsSym]: V["_schema"][ItemsSym] }
203
169
  ) {
204
- this._encoding ||= {};
205
- Object.assign(this._encoding, def);
170
+ this._schema ||= {};
171
+ Object.assign(this._schema, def);
206
172
  }
207
173
  }
208
174
 
@@ -216,32 +182,50 @@ function entryFromRawEntry<Item>(
216
182
  },
217
183
  loadedAs: Account & Me,
218
184
  accountID: ID<Account> | undefined,
219
- itemField: FieldDescriptor
220
- ) {
185
+ itemField: Schema
186
+ ): Omit<CoStreamEntry<Item>, "all"> {
221
187
  return {
222
- get value(): Item | undefined {
188
+ get value(): NonNullable<Item> extends CoValue
189
+ ? (CoValue & Item) | null
190
+ : Item {
223
191
  if (itemField === "json") {
224
- return rawEntry.value as Item;
192
+ return rawEntry.value as NonNullable<Item> extends CoValue
193
+ ? (CoValue & Item) | null
194
+ : Item;
225
195
  } else if ("encoded" in itemField) {
226
- return Schema.decodeSync(itemField.encoded)(rawEntry.value);
227
- } else if ("ref" in itemField) {
228
- return this.ref?.accessFrom(accessFrom) as Item;
196
+ return decodeSync(itemField.encoded)(
197
+ rawEntry.value
198
+ );
199
+ } else if (isRefEncoded(itemField)) {
200
+ return this.ref?.accessFrom(
201
+ accessFrom
202
+ ) as NonNullable<Item> extends CoValue
203
+ ? (CoValue & Item) | null
204
+ : Item;
205
+ } else {
206
+ throw new Error("Invalid item field schema");
229
207
  }
230
208
  },
231
- get ref() {
232
- if (itemField !== "json" && "ref" in itemField) {
209
+ get ref(): NonNullable<Item> extends CoValue
210
+ ? Ref<NonNullable<Item>>
211
+ : never {
212
+ if (itemField !== "json" && isRefEncoded(itemField)) {
233
213
  const rawId = rawEntry.value;
234
- return new ValueRef(
214
+ return new Ref(
235
215
  rawId as unknown as ID<CoValue>,
236
216
  loadedAs,
237
- itemField.ref()
238
- );
217
+ itemField
218
+ ) as NonNullable<Item> extends CoValue
219
+ ? Ref<NonNullable<Item>>
220
+ : never;
221
+ } else {
222
+ return undefined as never;
239
223
  }
240
224
  },
241
225
  get by() {
242
226
  return (
243
227
  accountID &&
244
- new ValueRef(
228
+ new Ref<Account>(
245
229
  accountID as unknown as ID<Account>,
246
230
  loadedAs,
247
231
  Account
@@ -253,16 +237,173 @@ function entryFromRawEntry<Item>(
253
237
  };
254
238
  }
255
239
 
240
+ function init(stream: CoStream) {
241
+ const init = stream[InitValues];
242
+ if (!init) return;
243
+
244
+ const raw = init.owner._raw.createStream();
245
+
246
+ Object.defineProperties(stream, {
247
+ id: {
248
+ value: raw.id,
249
+ enumerable: false,
250
+ },
251
+ _raw: { value: raw, enumerable: false },
252
+ });
253
+
254
+ if (init.init) {
255
+ stream.push(...init.init);
256
+ }
257
+
258
+ delete stream[InitValues];
259
+ }
260
+
261
+ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
262
+ get(target, key, receiver) {
263
+ if (typeof key === "string" && key.startsWith("co_")) {
264
+ const rawEntry = target._raw.lastItemBy(key as AccountID);
265
+
266
+ if (!rawEntry) return;
267
+ const entry = entryFromRawEntry(
268
+ receiver,
269
+ rawEntry,
270
+ target._loadedAs,
271
+ key as unknown as ID<Account>,
272
+ target._schema[ItemsSym]
273
+ );
274
+
275
+ Object.defineProperty(entry, "all", {
276
+ get: () => {
277
+ const allRawEntries = target._raw.itemsBy(key as AccountID);
278
+ return (function* () {
279
+ const rawEntry = allRawEntries.next();
280
+ if (rawEntry.done) return;
281
+ yield entryFromRawEntry(
282
+ receiver,
283
+ rawEntry.value,
284
+ target._loadedAs,
285
+ key as unknown as ID<Account>,
286
+ target._schema[ItemsSym]
287
+ );
288
+ })() satisfies IterableIterator<SingleCoStreamEntry<any>>;
289
+ },
290
+ });
291
+
292
+ return entry;
293
+ } else if (key === "perSession") {
294
+ return new Proxy(receiver, CoStreamPerSessionProxyHandler);
295
+ } else {
296
+ return Reflect.get(target, key, receiver);
297
+ }
298
+ },
299
+ set(target, key, value, receiver) {
300
+ if (
301
+ key === ItemsSym &&
302
+ typeof value === "object" &&
303
+ SchemaInit in value
304
+ ) {
305
+ (target.constructor as typeof CoStream)._schema ||= {};
306
+ (target.constructor as typeof CoStream)._schema[ItemsSym] =
307
+ value[SchemaInit];
308
+ init(target);
309
+ return true;
310
+ } else {
311
+ return Reflect.set(target, key, value, receiver);
312
+ }
313
+ },
314
+ defineProperty(target, key, descriptor) {
315
+ if (
316
+ descriptor.value &&
317
+ key === ItemsSym &&
318
+ typeof descriptor.value === "object" &&
319
+ SchemaInit in descriptor.value
320
+ ) {
321
+ (target.constructor as typeof CoStream)._schema ||= {};
322
+ (target.constructor as typeof CoStream)._schema[ItemsSym] =
323
+ descriptor.value[SchemaInit];
324
+ init(target);
325
+ return true;
326
+ } else {
327
+ return Reflect.defineProperty(target, key, descriptor);
328
+ }
329
+ },
330
+ ownKeys(target) {
331
+ const keys = Reflect.ownKeys(target);
332
+
333
+ for (const accountID of target._raw.accounts()) {
334
+ keys.push(accountID);
335
+ }
336
+
337
+ return keys;
338
+ },
339
+ getOwnPropertyDescriptor(target, key) {
340
+ if (typeof key === "string" && key.startsWith("co_")) {
341
+ return {
342
+ configurable: true,
343
+ enumerable: true,
344
+ writable: false,
345
+ };
346
+ } else {
347
+ return Reflect.getOwnPropertyDescriptor(target, key);
348
+ }
349
+ },
350
+ };
351
+
352
+ const CoStreamPerSessionProxyHandler: ProxyHandler<CoStream> = {
353
+ get(target, key, receiver) {
354
+ if (typeof key === "string" && key.includes("session")) {
355
+ const sessionID = key as SessionID;
356
+ const rawEntry = target._raw.lastItemIn(sessionID);
357
+
358
+ if (!rawEntry) return;
359
+ const by = cojsonInternals.accountOrAgentIDfromSessionID(sessionID);
360
+
361
+ const entry = entryFromRawEntry(
362
+ target,
363
+ rawEntry,
364
+ target._loadedAs,
365
+ cojsonInternals.isAccountID(by)
366
+ ? (by as unknown as ID<Account>)
367
+ : undefined,
368
+ target._schema[ItemsSym]
369
+ );
370
+
371
+ Object.defineProperty(entry, "all", {
372
+ get: () => {
373
+ const allRawEntries = target._raw.itemsIn(sessionID);
374
+ return (function* () {
375
+ const rawEntry = allRawEntries.next();
376
+ if (rawEntry.done) return;
377
+ yield entryFromRawEntry(
378
+ receiver,
379
+ rawEntry.value,
380
+ target._loadedAs,
381
+ cojsonInternals.isAccountID(by)
382
+ ? (by as unknown as ID<Account>)
383
+ : undefined,
384
+ target._schema[ItemsSym]
385
+ );
386
+ })() satisfies IterableIterator<SingleCoStreamEntry<any>>;
387
+ },
388
+ });
389
+
390
+ return entry;
391
+ } else {
392
+ return Reflect.get(target, key, receiver);
393
+ }
394
+ },
395
+ };
396
+
256
397
  export class BinaryCoStream
257
398
  extends CoValueBase
258
399
  implements CoValue<"BinaryCoStream", RawBinaryCoStream>
259
400
  {
260
- id!: ID<this>;
261
- _type!: "BinaryCoStream";
262
- _raw!: RawBinaryCoStream;
401
+ declare id: ID<this>;
402
+ declare _type: "BinaryCoStream";
403
+ declare _raw: RawBinaryCoStream;
263
404
 
264
405
  constructor(
265
- init: [] | undefined,
406
+ _init: [] | undefined,
266
407
  options:
267
408
  | {
268
409
  owner: Account | Group;
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  BinaryCoStream,
3
3
  CoMap,
4
- indexSignature,
4
+ co,
5
5
  subscriptionsScopes,
6
6
  } from "../../internal.js";
7
7
 
8
8
  export class ImageDefinition extends CoMap<ImageDefinition> {
9
- declare originalSize: [number, number];
10
- declare placeholderDataURL?: string;
9
+ originalSize = co.json<[number, number]>();
10
+ placeholderDataURL? = co.string;
11
11
 
12
- [res: `${number}x${number}`]: BinaryCoStream | null;
13
- declare [indexSignature]: BinaryCoStream | null;
12
+ [co.items] = co.ref(BinaryCoStream);
13
+ [res: `${number}x${number}`]: co<BinaryCoStream | null>;
14
14
 
15
- get _highestResAvailable():
15
+ get highestResAvailable():
16
16
  | { res: `${number}x${number}`; stream: BinaryCoStream }
17
17
  | undefined {
18
18
  if (!subscriptionsScopes.get(this)) {
@@ -52,9 +52,4 @@ export class ImageDefinition extends CoMap<ImageDefinition> {
52
52
  }
53
53
  );
54
54
  }
55
- }
56
- ImageDefinition.encoding({
57
- originalSize: "json",
58
- placeholderDataURL: "json",
59
- [indexSignature]: { ref: () => BinaryCoStream },
60
- });
55
+ }