atom.io 0.40.9 → 0.41.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 (32) hide show
  1. package/dist/eslint-plugin/index.js +1 -1
  2. package/dist/internal/index.d.ts +11 -2
  3. package/dist/internal/index.d.ts.map +1 -1
  4. package/dist/internal/index.js +34 -1
  5. package/dist/internal/index.js.map +1 -1
  6. package/dist/realtime/index.d.ts +2 -1
  7. package/dist/realtime/index.d.ts.map +1 -1
  8. package/dist/realtime/index.js.map +1 -1
  9. package/dist/realtime-client/index.js +2 -1
  10. package/dist/realtime-client/index.js.map +1 -1
  11. package/dist/realtime-server/index.js +1 -1
  12. package/dist/realtime-server/index.js.map +1 -1
  13. package/dist/transceivers/o-list/index.d.ts +87 -0
  14. package/dist/transceivers/o-list/index.d.ts.map +1 -0
  15. package/dist/transceivers/o-list/index.js +513 -0
  16. package/dist/transceivers/o-list/index.js.map +1 -0
  17. package/dist/transceivers/set-rtx/index.d.ts +16 -16
  18. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  19. package/dist/transceivers/set-rtx/index.js.map +1 -1
  20. package/dist/transceivers/u-list/index.d.ts +27 -18
  21. package/dist/transceivers/u-list/index.d.ts.map +1 -1
  22. package/dist/transceivers/u-list/index.js +54 -34
  23. package/dist/transceivers/u-list/index.js.map +1 -1
  24. package/package.json +17 -13
  25. package/src/internal/index.ts +1 -0
  26. package/src/internal/micro.ts +69 -0
  27. package/src/realtime/shared-room-store.ts +3 -2
  28. package/src/realtime-server/ipc-sockets/parent-socket.ts +1 -1
  29. package/src/transceivers/o-list/index.ts +1 -0
  30. package/src/transceivers/o-list/o-list.ts +613 -0
  31. package/src/transceivers/set-rtx/set-rtx.ts +22 -21
  32. package/src/transceivers/u-list/u-list.ts +85 -55
@@ -3,26 +3,26 @@ import { Json, primitive } from "atom.io/json";
3
3
 
4
4
  //#region src/transceivers/set-rtx/set-rtx.d.ts
5
5
  type SetUpdateType = `add` | `clear` | `del` | `tx`;
6
- type SetUpdate = `${SetUpdateType}:${string}`;
7
- type NumberedSetUpdate = `${number | `*`}=${SetUpdate}`;
6
+ type SetUpdateString = `${SetUpdateType}:${string}`;
7
+ type NumberedSetUpdateString = `${number | `*`}=${SetUpdateString}`;
8
8
  interface SetRTXView<P extends primitive> extends ReadonlySet<P> {
9
- readonly cache: ReadonlyArray<NumberedSetUpdate | null>;
9
+ readonly cache: ReadonlyArray<NumberedSetUpdateString | null>;
10
10
  readonly cacheLimit: number;
11
11
  readonly cacheIdx: number;
12
12
  readonly cacheUpdateNumber: number;
13
13
  }
14
14
  interface SetRTXJson<P extends primitive> extends Json.Object {
15
15
  members: P[];
16
- cache: (NumberedSetUpdate | null)[];
16
+ cache: (NumberedSetUpdateString | null)[];
17
17
  cacheLimit: number;
18
18
  cacheIdx: number;
19
19
  cacheUpdateNumber: number;
20
20
  }
21
- declare class SetRTX<P extends primitive> extends Set<P> implements Transceiver<SetRTXView<P>, NumberedSetUpdate, SetRTXJson<P>>, Lineage {
21
+ declare class SetRTX<P extends primitive> extends Set<P> implements Transceiver<SetRTXView<P>, NumberedSetUpdateString, SetRTXJson<P>>, Lineage {
22
22
  mode: TransceiverMode;
23
- readonly subject: Subject<SetUpdate>;
23
+ readonly subject: Subject<SetUpdateString>;
24
24
  cacheLimit: number;
25
- cache: (NumberedSetUpdate | null)[];
25
+ cache: (NumberedSetUpdateString | null)[];
26
26
  cacheIdx: number;
27
27
  cacheUpdateNumber: number;
28
28
  constructor(values?: Iterable<P>, cacheLimit?: number);
@@ -34,17 +34,17 @@ declare class SetRTX<P extends primitive> extends Set<P> implements Transceiver<
34
34
  delete(value: P): boolean;
35
35
  readonly parent: SetRTX<P> | null;
36
36
  child: SetRTX<P> | null;
37
- transactionUpdates: SetUpdate[] | null;
37
+ transactionUpdates: SetUpdateString[] | null;
38
38
  transaction(run: (child: SetRTX<P>) => boolean): void;
39
- protected _subscribe(key: string, fn: (update: SetUpdate) => void): () => void;
40
- subscribe(key: string, fn: (update: NumberedSetUpdate) => void): () => void;
41
- emit(update: SetUpdate): void;
39
+ protected _subscribe(key: string, fn: (update: SetUpdateString) => void): () => void;
40
+ subscribe(key: string, fn: (update: NumberedSetUpdateString) => void): () => void;
41
+ emit(update: SetUpdateString): void;
42
42
  private doStep;
43
- getUpdateNumber(update: NumberedSetUpdate): number;
44
- do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null;
45
- undoStep(update: SetUpdate): void;
46
- undo(update: NumberedSetUpdate): number | null;
43
+ getUpdateNumber(update: NumberedSetUpdateString): number;
44
+ do(update: NumberedSetUpdateString): number | `OUT_OF_RANGE` | null;
45
+ undoStep(update: SetUpdateString): void;
46
+ undo(update: NumberedSetUpdateString): number | null;
47
47
  }
48
48
  //#endregion
49
- export { NumberedSetUpdate, SetRTX, SetRTXJson, SetRTXView, SetUpdate, SetUpdateType };
49
+ export { NumberedSetUpdateString, SetRTX, SetRTXJson, SetRTXView, SetUpdateString, SetUpdateType };
50
50
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":[],"mappings":";;;;KAKY,aAAA;AAAA,KACA,SAAA,GADA,GACe,aADf,IAAA,MAAA,EAAA;AACA,KACA,iBAAA,GADe,GAAA,MAAA,GAAA,GAAA,IACwB,SADxB,EAAA;AACf,UAEK,UAFL,CAAA,UAE0B,SAFa,CAAA,SAEM,WAFN,CAEkB,CAFlB,CAAA,CAAA;EAEnD,SAAiB,KAAA,EACA,aADA,CACc,iBADd,GAAA,IAAA,CAAA;EAAA,SAAA,UAAA,EAAA,MAAA;WAAqB,QAAA,EAAA,MAAA;WAA+B,iBAAA,EAAA,MAAA;;AACpD,UAMA,UANA,CAAA,UAMqB,SANrB,CAAA,SAMwC,IAAA,CAAK,MAN7C,CAAA;SADwC,EAQ/C,CAR+C,EAAA;EAAA,KAAA,EAAA,CAShD,iBATgD,GAAA,IAAA,CAAA,EAAA;EAOzD,UAAiB,EAAA,MAAA;EAAA,QAAA,EAAA,MAAA;mBAAqB,EAAA,MAAA;;AAE7B,cAKI,MALJ,CAAA,UAKqB,SALrB,CAAA,SAMA,GANA,CAMI,CANJ,CAAA,YAQP,WARO,CAQK,UARL,CAQgB,CARhB,CAAA,EAQoB,iBARpB,EAQuC,UARvC,CAQkD,CARlD,CAAA,CAAA,EASP,OATO,CAAA;QAWK,eAbgD;EAAA,SAAA,OAAA,EAcpC,OAdoC,CAc5B,SAd4B,CAAA;EAO9D,UAAa,EAAA,MAAA;EAAA,KAAA,EAAA,CASG,iBATH,GAAA,IAAA,CAAA,EAAA;UAAiB,EAAA,MAAA;mBACjB,EAAA,MAAA;aAEY,CAAA,MAAA,CAAA,EAUI,QAVJ,CAUa,CAVb,CAAA,EAAA,UAAA,CAAA,EAAA,MAAA;WAAX,aAAA,EA2BkB,UA3BlB,CA2B6B,CA3B7B,CAAA;QAAe,CAAA,CAAA,EA6BX,UA7BW,CA6BA,CA7BA,CAAA;SAA8B,QAAA,CAAA,UAuCzB,SAvCyB,CAAA,CAAA,IAAA,EAuCR,UAvCQ,CAuCG,CAvCH,CAAA,CAAA,EAuCQ,MAvCR,CAuCe,CAvCf,CAAA;WAAX,EA+C7B,CA/C6B,CAAA,EAAA,IAAA;SAGlC,EAAA,IAAA;QACoB,CAAA,KAAA,EA6DZ,CA7DY,CAAA,EAAA,OAAA;WAAR,MAAA,EAsED,MAtEC,CAsEM,CAtEN,CAAA,GAAA,IAAA;SAuEX,MArEC,CAqEM,CArEN,CAAA,GAAA,IAAA;oBAIsB,EAkEV,SAlEU,EAAA,GAAA,IAAA;aAAT,CAAA,GAAA,EAAA,CAAA,KAAA,EAmEI,MAnEJ,CAmEW,CAnEX,CAAA,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA;YAiBc,UAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAmF5B,SAnF4B,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;WAAX,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAyFjB,iBAzFiB,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;aAEH,EA8FR,SA9FQ,CAAA,EAAA,IAAA;UAAX,MAAA;iBAUgB,CAAA,MAAA,EA6GF,iBA7GE,CAAA,EAAA,MAAA;WAA4B,EAkH3C,iBAlH2C,CAAA,EAAA,MAAA,GAAA,cAAA,GAAA,IAAA;UAAX,CAAA,MAAA,EA6J1B,SA7J0B,CAAA,EAAA,IAAA;aAAuB,EAsLrD,iBAtLqD,CAAA,EAAA,MAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":[],"mappings":";;;;KAKY,aAAA;AAAA,KACA,eAAA,GADA,GACqB,aADrB,IAAA,MAAA,EAAA;AACA,KACA,uBAAA,GADqB,GAAA,MAAA,GAAA,GAAA,IACwB,eADxB,EAAA;AACrB,UAEK,UAFL,CAAA,UAE0B,SAFmB,CAAA,SAEA,WAFA,CAEY,CAFZ,CAAA,CAAA;EAEzD,SAAiB,KAAA,EACA,aADA,CACc,uBADd,GAAA,IAAA,CAAA;EAAA,SAAA,UAAA,EAAA,MAAA;WAAqB,QAAA,EAAA,MAAA;WAA+B,iBAAA,EAAA,MAAA;;AACpD,UAMA,UANA,CAAA,UAMqB,SANrB,CAAA,SAMwC,IAAA,CAAK,MAN7C,CAAA;SADwC,EAQ/C,CAR+C,EAAA;EAAA,KAAA,EAAA,CAShD,uBATgD,GAAA,IAAA,CAAA,EAAA;EAOzD,UAAiB,EAAA,MAAA;EAAA,QAAA,EAAA,MAAA;mBAAqB,EAAA,MAAA;;AAE7B,cAKI,MALJ,CAAA,UAKqB,SALrB,CAAA,SAMA,GANA,CAMI,CANJ,CAAA,YAQP,WARO,CAQK,UARL,CAQgB,CARhB,CAAA,EAQoB,uBARpB,EAQ6C,UAR7C,CAQwD,CARxD,CAAA,CAAA,EASP,OATO,CAAA;QAWK,eAbgD;EAAA,SAAA,OAAA,EAcpC,OAdoC,CAc5B,eAd4B,CAAA;EAO9D,UAAa,EAAA,MAAA;EAAA,KAAA,EAAA,CAUG,uBAVH,GAAA,IAAA,CAAA,EAAA;UAAiB,EAAA,MAAA;mBACjB,EAAA,MAAA;aAEY,CAAA,MAAA,CAAA,EAWI,QAXJ,CAWa,CAXb,CAAA,EAAA,UAAA,CAAA,EAAA,MAAA;WAAX,aAAA,EA4BkB,UA5BlB,CA4B6B,CA5B7B,CAAA;QAAe,CAAA,CAAA,EA8BX,UA9BW,CA8BA,CA9BA,CAAA;SAAoC,QAAA,CAAA,UAwC/B,SAxC+B,CAAA,CAAA,IAAA,EAwCd,UAxCc,CAwCH,CAxCG,CAAA,CAAA,EAwCE,MAxCF,CAwCS,CAxCT,CAAA;WAAX,EAgDnC,CAhDmC,CAAA,EAAA,IAAA;SAGxC,EAAA,IAAA;QACoB,CAAA,KAAA,EA8DZ,CA9DY,CAAA,EAAA,OAAA;WAAR,MAAA,EAuED,MAvEC,CAuEM,CAvEN,CAAA,GAAA,IAAA;SAwEX,MArEC,CAqEM,CArEN,CAAA,GAAA,IAAA;oBAIsB,EAkEV,eAlEU,EAAA,GAAA,IAAA;aAAT,CAAA,GAAA,EAAA,CAAA,KAAA,EAmEI,MAnEJ,CAmEW,CAnEX,CAAA,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA;YAiBc,UAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAmF5B,eAnF4B,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;WAAX,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAyFjB,uBAzFiB,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;aAEH,EA8FR,eA9FQ,CAAA,EAAA,IAAA;UAAX,MAAA;iBAUgB,CAAA,MAAA,EA6GF,uBA7GE,CAAA,EAAA,MAAA;WAA4B,EAkH3C,uBAlH2C,CAAA,EAAA,MAAA,GAAA,cAAA,GAAA,IAAA;UAAX,CAAA,MAAA,EA6J1B,eA7J0B,CAAA,EAAA,IAAA;aAAuB,EAsLrD,uBAtLqD,CAAA,EAAA,MAAA,GAAA,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdateType = `add` | `clear` | `del` | `tx`\nexport type SetUpdate = `${SetUpdateType}:${string}`\nexport type NumberedSetUpdate = `${number | `*`}=${SetUpdate}`\n\nexport interface SetRTXView<P extends primitive> extends ReadonlySet<P> {\n\treadonly cache: ReadonlyArray<NumberedSetUpdate | null>\n\treadonly cacheLimit: number\n\treadonly cacheIdx: number\n\treadonly cacheUpdateNumber: number\n}\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements\n\t\tTransceiver<SetRTXView<P>, NumberedSetUpdate, SetRTXJson<P>>,\n\t\tLineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<SetUpdate> = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: SetRTXView<P> = this\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null = null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\t/* eslint-disable-next-line no-console */\n\t\t\tconsole.warn(\n\t\t\t\t`Did not apply transaction to SetRTX; this error was thrown:`,\n\t\t\t\tthrown,\n\t\t\t)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) => {\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`)\n\t\t})\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as SetUpdateType\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const subUpdate of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(subUpdate as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdate): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture || Number.isNaN(eventOffset)) {\n\t\t\tif (eventOffset === 1 || Number.isNaN(eventOffset)) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst u = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!u) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(u)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as SetUpdateType\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdateType = `add` | `clear` | `del` | `tx`\nexport type SetUpdateString = `${SetUpdateType}:${string}`\nexport type NumberedSetUpdateString = `${number | `*`}=${SetUpdateString}`\n\nexport interface SetRTXView<P extends primitive> extends ReadonlySet<P> {\n\treadonly cache: ReadonlyArray<NumberedSetUpdateString | null>\n\treadonly cacheLimit: number\n\treadonly cacheIdx: number\n\treadonly cacheUpdateNumber: number\n}\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdateString | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements\n\t\tTransceiver<SetRTXView<P>, NumberedSetUpdateString, SetRTXJson<P>>,\n\t\tLineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<SetUpdateString> =\n\t\tnew Subject<SetUpdateString>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdateString | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: SetRTXView<P> = this\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null = null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdateString[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\t/* eslint-disable-next-line no-console */\n\t\t\tconsole.warn(\n\t\t\t\t`Did not apply transaction to SetRTX; this error was thrown:`,\n\t\t\t\tthrown,\n\t\t\t)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdateString) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdateString) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) => {\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`)\n\t\t})\n\t}\n\n\tpublic emit(update: SetUpdateString): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdateString): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as SetUpdateType\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const subUpdate of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(subUpdate as SetUpdateString)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdateString): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdateString): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture || Number.isNaN(eventOffset)) {\n\t\t\tif (eventOffset === 1 || Number.isNaN(eventOffset)) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdateString\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst u = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!u) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(u)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdateString\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdateString): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as SetUpdateType\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdateString[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdateString): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdateString\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"],"mappings":"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"}
@@ -1,29 +1,38 @@
1
- import { Subject, Transceiver, TransceiverMode } from "atom.io/internal";
2
- import { Json, primitive, stringified } from "atom.io/json";
1
+ import { Enumeration, Fn, Subject, Transceiver, TransceiverMode } from "atom.io/internal";
2
+ import { primitive } from "atom.io/json";
3
3
 
4
4
  //#region src/transceivers/u-list/u-list.d.ts
5
- type UListUpdateType = `add` | `clear` | `del`;
6
- type UListUpdate<P extends primitive> = `${`add` | `del`}:${stringified<P>}` | `clear:${stringified<P[]>}`;
7
- interface UListJson<P extends primitive> extends Json.Object {
8
- members: P[];
9
- }
10
- declare class UList<P extends primitive> extends Set<P> implements Transceiver<ReadonlySet<P>, UListUpdate<P>, UListJson<P>> {
5
+ type SetMutations = Exclude<keyof Set<any>, symbol | keyof ReadonlySet<any>>;
6
+ type SetUpdate<P extends primitive> = {
7
+ type: `add` | `delete`;
8
+ value: P;
9
+ } | {
10
+ type: `clear`;
11
+ values: P[];
12
+ };
13
+ type UListUpdateType = SetUpdate<any>[`type`];
14
+ type PackedSetUpdate<P extends primitive> = string & {
15
+ update?: SetUpdate<P>;
16
+ };
17
+ declare const SET_UPDATE_ENUM: Enumeration<[`add`, `delete`, `clear`]>;
18
+ declare function packSetUpdate<P extends primitive>(update: SetUpdate<P>): PackedSetUpdate<P>;
19
+ declare function unpackSetUpdate<P extends primitive>(packed: PackedSetUpdate<P>): SetUpdate<P>;
20
+ type SetMutationHandler = { [K in UListUpdateType]: Fn };
21
+ declare class UList<P extends primitive> extends Set<P> implements Transceiver<ReadonlySet<P>, PackedSetUpdate<P>, ReadonlyArray<P>>, SetMutationHandler {
11
22
  mode: TransceiverMode;
12
- readonly subject: Subject<UListUpdate<P>>;
23
+ readonly subject: Subject<PackedSetUpdate<P>>;
13
24
  constructor(values?: Iterable<P>);
14
25
  readonly READONLY_VIEW: ReadonlySet<P>;
15
- toJSON(): UListJson<P>;
16
- static fromJSON<P extends primitive>(json: UListJson<P>): UList<P>;
26
+ toJSON(): ReadonlyArray<P>;
27
+ static fromJSON<P extends primitive>(json: ReadonlyArray<P>): UList<P>;
17
28
  add(value: P): this;
18
29
  clear(): void;
19
30
  delete(value: P): boolean;
20
- subscribe(key: string, fn: (update: UListUpdate<P>) => void): () => void;
21
- emit(update: UListUpdate<P>): void;
22
- private doStep;
23
- do(update: UListUpdate<P>): null;
24
- undoStep(update: UListUpdate<P>): void;
25
- undo(update: UListUpdate<P>): number | null;
31
+ subscribe(key: string, fn: (update: PackedSetUpdate<P>) => void): () => void;
32
+ emit(update: SetUpdate<P>): void;
33
+ do(packed: PackedSetUpdate<P>): null;
34
+ undo(packed: PackedSetUpdate<P>): number | null;
26
35
  }
27
36
  //#endregion
28
- export { UList, UListJson, UListUpdate, UListUpdateType };
37
+ export { PackedSetUpdate, SET_UPDATE_ENUM, SetMutationHandler, SetMutations, SetUpdate, UList, UListUpdateType, packSetUpdate, unpackSetUpdate };
29
38
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":[],"mappings":";;;;KAKY,eAAA;AAAA,KACA,WADA,CAAA,UACsB,SADtB,CAAA,GAAA,GAAA,KAAA,GAAA,KAAA,IAEW,WAFX,CAEuB,CAFvB,CAAA,EAAA,GAAA,SAGA,WAHA,CAGY,CAHZ,EAAA,CAAA,EAAA;AACA,UAIK,SAJL,CAAA,UAIyB,SAJzB,CAAA,SAI4C,IAAA,CAAK,MAJjD,CAAA;EAAA,OAAA,EAKF,CALE,EAAA;;AACuB,cAMtB,KANsB,CAAA,UAMN,SANM,CAAA,SAO1B,GAP0B,CAOtB,CAPsB,CAAA,YAQvB,WARuB,CAQX,WARW,CAQC,CARD,CAAA,EAQK,WARL,CAQiB,CARjB,CAAA,EAQqB,SARrB,CAQ+B,CAR/B,CAAA,CAAA,CAAA;QAUrB,eAVS;WACC,OAAA,EAUE,OAVF,CAUU,WAVV,CAUsB,CAVtB,CAAA,CAAA;aAAZ,CAAA,MAAA,CAAA,EAciB,QAdjB,CAc0B,CAd1B,CAAA;EAAA,SAAA,aAAA,EAoBoB,WApBpB,CAoBgC,CApBhC,CAAA;EAEZ,MAAiB,CAAA,CAAA,EAoBC,SApBD,CAoBW,CApBX,CAAA;EAAA,OAAA,QAAA,CAAA,UA0BiB,SA1BjB,CAAA,CAAA,IAAA,EA0BkC,SA1BlC,CA0B4C,CA1B5C,CAAA,CAAA,EA0BiD,KA1BjD,CA0BuD,CA1BvD,CAAA;WAAoB,EA8BlB,CA9BkB,CAAA,EAAA,IAAA;SAC3B,EAAA,IAAA;QAD8C,CAAA,KAAK,EA8CvC,CA9CuC,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAwD9C,WAxD8C,CAwDlC,CAxDkC,CAAA,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAG7D,IAAa,CAAA,MAAA,EA0DQ,WA1DR,CA0DoB,CA1DpB,CAAA,CAAA,EAAA,IAAA;EAAA,QAAA,MAAA;WAAgB,EA8EV,WA9EU,CA8EE,CA9EF,CAAA,CAAA,EAAA,IAAA;UAChB,CAAA,MAAA,EAoFY,WApFZ,CAoFwB,CApFxB,CAAA,CAAA,EAAA,IAAA;aACuB,EAqGf,WArGe,CAqGH,CArGG,CAAA,CAAA,EAAA,MAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":["SET_UPDATE_ENUM: Enumeration<[`add`, `delete`, `clear`]>"],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":[],"mappings":";;;;KASY,YAAA,GAAe,cACpB,yBACS;AAFJ,KAIA,SAJA,CAAA,UAIoB,SAJpB,CAAA,GAAA;EAAA,IAAA,EAAA,KAAA,GAAA,QAAA;SAOF,CANH;;QADoB,OAAA;EAAA,MAAA,EAWhB,CAXgB,EAAA;AAI3B,CAAA;AAAY,KASA,eAAA,GAAkB,SATlB,CAAA,GAAA,CAAA,CAAA,MAAA,CAAA;AAAoB,KAcpB,eAdoB,CAAA,UAcM,SAdN,CAAA,GAAA,MAAA,GAAA;QAGtB,CAAA,EAYA,SAZA,CAYU,CAZV,CAAA;;AAIC,cAWEA,eAXF,EAWmB,WAXnB,CAAA,CAAA,KAAA,EAAA,QAAA,EAAA,OAAA,CAAA,CAAA;AAEC,iBAYI,aAZc,CAAA,UAYU,SAZV,CAAA,CAAA,MAAA,EAarB,SAbqB,CAaX,CAbW,CAAA,CAAA,EAc3B,eAd2B,CAcX,CAdW,CAAA;AAKlB,iBAgBI,eAhBJ,CAAA,UAgB8B,SAhB9B,CAAA,CAAA,MAAA,EAiBH,eAjBG,CAiBa,CAjBb,CAAA,CAAA,EAkBT,SAlBS,CAkBC,CAlBD,CAAA;AAAA,KA4BA,kBAAA,GA5BA,QA4B6B,eA5B7B,GA4B+C,EA5B/C,EAAA;AAA0B,cA8BzB,KA9ByB,CAAA,UA8BT,SA9BS,CAAA,SA+B7B,GA/B6B,CA+BzB,CA/ByB,CAAA,YAiCpC,WAjCoC,CAiCxB,WAjCwB,CAiCZ,CAjCY,CAAA,EAiCR,eAjCQ,CAiCQ,CAjCR,CAAA,EAiCY,aAjCZ,CAiC0B,CAjC1B,CAAA,CAAA,EAkCpC,kBAlCoC,CAAA;QAoCxB,eAnCM;WAAV,OAAA,EAoCgB,OApChB,CAoCwB,eApCxB,CAoCwC,CApCxC,CAAA,CAAA;EAAA,WAAA,CAAA,MAAA,CAAA,EAsCmB,QAtCnB,CAsC4B,CAtC5B,CAAA;EAGV,SAAaA,aAA+C,EAyC5B,WAzCF,CAyCc,CAzCd,CAAA;EAG9B,MAAgB,CAAA,CAAA,EAwCE,aAxCF,CAwCgB,CAxChB,CAAA;EAAA,OAAA,QAAA,CAAA,UA4CkB,SA5ClB,CAAA,CAAA,IAAA,EA4CmC,aA5CnC,CA4CiD,CA5CjD,CAAA,CAAA,EA4CsD,KA5CtD,CA4C4D,CA5C5D,CAAA;WAAwB,EAgDrB,CAhDqB,CAAA,EAAA,IAAA;SACrB,EAAA,IAAA;QAAV,CAAA,KAAA,EA+Da,CA/Db,CAAA,EAAA,OAAA;WACU,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAwEJ,eAxEI,CAwEY,CAxEZ,CAAA,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;aAAhB,EA6EkB,SA7ElB,CA6E4B,CA7E5B,CAAA,CAAA,EAAA,IAAA;EAAA,EAAA,CAAA,MAAA,EAiFgB,eAjFhB,CAiFgC,CAjFhC,CAAA,CAAA,EAAA,IAAA;EAOH,IAAgB,CAAA,MAAA,EA2FK,eA3FL,CA2FqB,CA3FrB,CAAA,CAAA,EAAA,MAAA,GAAA,IAAA"}
@@ -1,7 +1,28 @@
1
- import { Subject } from "atom.io/internal";
2
- import { stringifyJson } from "atom.io/json";
1
+ import { Subject, enumeration, packValue, unpackValue } from "atom.io/internal";
3
2
 
4
3
  //#region src/transceivers/u-list/u-list.ts
4
+ const SET_UPDATE_ENUM = enumeration([
5
+ `add`,
6
+ `delete`,
7
+ `clear`
8
+ ]);
9
+ function packSetUpdate(update) {
10
+ const head = SET_UPDATE_ENUM[update.type] + `\u001F`;
11
+ if (update.type === `clear`) return head + update.values.map(packValue).join(`\u001E`);
12
+ return head + packValue(update.value);
13
+ }
14
+ function unpackSetUpdate(packed) {
15
+ const [type, tail] = packed.split(`\u001F`);
16
+ const head = SET_UPDATE_ENUM[type];
17
+ if (head === `clear`) return {
18
+ type: `clear`,
19
+ values: tail.split(`\u001E`).map(unpackValue)
20
+ };
21
+ return {
22
+ type: head,
23
+ value: unpackValue(tail)
24
+ };
25
+ }
5
26
  var UList = class UList extends Set {
6
27
  mode = `record`;
7
28
  subject = new Subject();
@@ -11,77 +32,76 @@ var UList = class UList extends Set {
11
32
  }
12
33
  READONLY_VIEW = this;
13
34
  toJSON() {
14
- return { members: [...this] };
35
+ return [...this];
15
36
  }
16
37
  static fromJSON(json) {
17
- return new UList(json.members);
38
+ return new UList(json);
18
39
  }
19
40
  add(value) {
20
41
  const result = super.add(value);
21
- if (this.mode === `record`) this.emit(`add:${stringifyJson(value)}`);
42
+ if (this.mode === `record`) this.emit({
43
+ type: `add`,
44
+ value
45
+ });
22
46
  return result;
23
47
  }
24
48
  clear() {
25
49
  const capturedContents = this.mode === `record` ? [...this] : null;
26
50
  super.clear();
27
- if (capturedContents) this.emit(`clear:${stringifyJson(capturedContents)}`);
51
+ if (capturedContents) this.emit({
52
+ type: `clear`,
53
+ values: capturedContents
54
+ });
28
55
  }
29
56
  delete(value) {
30
57
  const result = super.delete(value);
31
- if (this.mode === `record`) this.emit(`del:${stringifyJson(value)}`);
58
+ if (this.mode === `record`) this.emit({
59
+ type: `delete`,
60
+ value
61
+ });
32
62
  return result;
33
63
  }
34
64
  subscribe(key, fn) {
35
65
  return this.subject.subscribe(key, fn);
36
66
  }
37
67
  emit(update) {
38
- this.subject.next(update);
68
+ this.subject.next(packSetUpdate(update));
39
69
  }
40
- doStep(update) {
41
- const typeValueBreak = update.indexOf(`:`);
42
- const type = update.substring(0, typeValueBreak);
43
- const value = update.substring(typeValueBreak + 1);
44
- switch (type) {
70
+ do(packed) {
71
+ this.mode = `playback`;
72
+ const update = unpackSetUpdate(packed);
73
+ switch (update.type) {
45
74
  case `add`:
46
- this.add(JSON.parse(value));
75
+ this.add(update.value);
47
76
  break;
48
- case `del`:
49
- this.delete(JSON.parse(value));
77
+ case `delete`:
78
+ this.delete(update.value);
50
79
  break;
51
80
  case `clear`: this.clear();
52
81
  }
53
- }
54
- do(update) {
55
- this.mode = `playback`;
56
- this.doStep(update);
57
82
  this.mode = `record`;
58
83
  return null;
59
84
  }
60
- undoStep(update) {
61
- const breakpoint = update.indexOf(`:`);
62
- const type = update.substring(0, breakpoint);
63
- const value = update.substring(breakpoint + 1);
64
- switch (type) {
85
+ undo(packed) {
86
+ const update = unpackSetUpdate(packed);
87
+ this.mode = `playback`;
88
+ switch (update.type) {
65
89
  case `add`:
66
- this.delete(JSON.parse(value));
90
+ this.delete(update.value);
67
91
  break;
68
- case `del`:
69
- this.add(JSON.parse(value));
92
+ case `delete`:
93
+ this.add(update.value);
70
94
  break;
71
95
  case `clear`: {
72
- const values = JSON.parse(value);
96
+ const values = update.values;
73
97
  for (const v of values) this.add(v);
74
98
  }
75
99
  }
76
- }
77
- undo(update) {
78
- this.mode = `playback`;
79
- this.undoStep(update);
80
100
  this.mode = `record`;
81
101
  return null;
82
102
  }
83
103
  };
84
104
 
85
105
  //#endregion
86
- export { UList };
106
+ export { SET_UPDATE_ENUM, UList, packSetUpdate, unpackSetUpdate };
87
107
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":["import type { Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive, stringified } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type UListUpdateType = `add` | `clear` | `del`\nexport type UListUpdate<P extends primitive> =\n\t| `${`add` | `del`}:${stringified<P>}`\n\t| `clear:${stringified<P[]>}`\n\nexport interface UListJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n}\nexport class UList<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<ReadonlySet<P>, UListUpdate<P>, UListJson<P>>\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<UListUpdate<P>> = new Subject<\n\t\tUListUpdate<P>\n\t>()\n\n\tpublic constructor(values?: Iterable<P>) {\n\t\tsuper(values)\n\t\tif (values instanceof UList) {\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: ReadonlySet<P> = this\n\n\tpublic toJSON(): UListJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: UListJson<P>): UList<P> {\n\t\treturn new UList<P>(json.members)\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.emit(`clear:${stringifyJson(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: UListUpdate<P>) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\n\tpublic emit(update: UListUpdate<P>): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: UListUpdate<P>): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as UListUpdateType\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t}\n\t}\n\n\tpublic do(update: UListUpdate<P>): null {\n\t\tthis.mode = `playback`\n\t\tthis.doStep(update)\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n\n\tpublic undoStep(update: UListUpdate<P>): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as UListUpdateType\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: UListUpdate<P>): number | null {\n\t\tthis.mode = `playback`\n\t\tthis.undoStep(update)\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n}\n"],"mappings":";;;;AAaA,IAAa,QAAb,MAAa,cACJ,IAET;CACC,AAAO,OAAwB;CAC/B,AAAgB,UAAmC,IAAI,SAEpD;CAEH,AAAO,YAAY,QAAsB;AACxC,QAAM,OAAO;AACb,MAAI,kBAAkB,OAAO;;CAI9B,AAAgB,gBAAgC;CAEhD,AAAO,SAAuB;AAC7B,SAAO,EACN,SAAS,CAAC,GAAG,KAAK,EAClB;;CAGF,OAAc,SAA8B,MAA8B;AACzE,SAAO,IAAI,MAAS,KAAK,QAAQ;;CAGlC,AAAO,IAAI,OAAgB;EAC1B,MAAM,SAAS,MAAM,IAAI,MAAM;AAC/B,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK,OAAO,cAAiB,MAAM,GAAG;AAE5C,SAAO;;CAGR,AAAO,QAAc;EACpB,MAAM,mBAAmB,KAAK,SAAS,WAAW,CAAC,GAAG,KAAK,GAAG;AAC9D,QAAM,OAAO;AACb,MAAI,iBACH,MAAK,KAAK,SAAS,cAAc,iBAAiB,GAAG;;CAIvD,AAAO,OAAO,OAAmB;EAChC,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK,OAAO,cAAiB,MAAM,GAAG;AAE5C,SAAO;;CAGR,AAAO,UACN,KACA,IACa;AACb,SAAO,KAAK,QAAQ,UAAU,KAAK,GAAG;;CAGvC,AAAO,KAAK,QAA8B;AACzC,OAAK,QAAQ,KAAK,OAAO;;CAG1B,AAAQ,OAAO,QAA8B;EAC5C,MAAM,iBAAiB,OAAO,QAAQ,IAAI;EAC1C,MAAM,OAAO,OAAO,UAAU,GAAG,eAAe;EAChD,MAAM,QAAQ,OAAO,UAAU,iBAAiB,EAAE;AAClD,UAAQ,MAAR;GACC,KAAK;AACJ,SAAK,IAAI,KAAK,MAAM,MAAM,CAAC;AAC3B;GACD,KAAK;AACJ,SAAK,OAAO,KAAK,MAAM,MAAM,CAAC;AAC9B;GACD,KAAK,QACJ,MAAK,OAAO;;;CAIf,AAAO,GAAG,QAA8B;AACvC,OAAK,OAAO;AACZ,OAAK,OAAO,OAAO;AACnB,OAAK,OAAO;AACZ,SAAO;;CAGR,AAAO,SAAS,QAA8B;EAC7C,MAAM,aAAa,OAAO,QAAQ,IAAI;EACtC,MAAM,OAAO,OAAO,UAAU,GAAG,WAAW;EAC5C,MAAM,QAAQ,OAAO,UAAU,aAAa,EAAE;AAC9C,UAAQ,MAAR;GACC,KAAK;AACJ,SAAK,OAAO,KAAK,MAAM,MAAM,CAAC;AAC9B;GACD,KAAK;AACJ,SAAK,IAAI,KAAK,MAAM,MAAM,CAAC;AAC3B;GACD,KAAK,SAAS;IACb,MAAM,SAAS,KAAK,MAAM,MAAM;AAChC,SAAK,MAAM,KAAK,OAAQ,MAAK,IAAI,EAAE;;;;CAKtC,AAAO,KAAK,QAAuC;AAClD,OAAK,OAAO;AACZ,OAAK,SAAS,OAAO;AACrB,OAAK,OAAO;AACZ,SAAO"}
1
+ {"version":3,"file":"index.js","names":["SET_UPDATE_ENUM: Enumeration<[`add`, `delete`, `clear`]>"],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":["import type {\n\tEnumeration,\n\tFn,\n\tTransceiver,\n\tTransceiverMode,\n} from \"atom.io/internal\"\nimport { enumeration, packValue, Subject, unpackValue } from \"atom.io/internal\"\nimport type { primitive } from \"atom.io/json\"\n\nexport type SetMutations = Exclude<\n\tkeyof Set<any>,\n\tsymbol | keyof ReadonlySet<any>\n>\nexport type SetUpdate<P extends primitive> =\n\t| {\n\t\t\ttype: `add` | `delete`\n\t\t\tvalue: P\n\t }\n\t| {\n\t\t\ttype: `clear`\n\t\t\tvalues: P[]\n\t }\nexport type UListUpdateType = SetUpdate<any>[`type`]\ntrue satisfies SetMutations extends UListUpdateType\n\t? true\n\t: Exclude<SetMutations, UListUpdateType>\n\nexport type PackedSetUpdate<P extends primitive> = string & {\n\tupdate?: SetUpdate<P>\n}\n\nexport const SET_UPDATE_ENUM: Enumeration<[`add`, `delete`, `clear`]> =\n\tenumeration([`add`, `delete`, `clear`] as const)\n\nexport function packSetUpdate<P extends primitive>(\n\tupdate: SetUpdate<P>,\n): PackedSetUpdate<P> {\n\tconst head = SET_UPDATE_ENUM[update.type] + `\\u001F`\n\tif (update.type === `clear`) {\n\t\treturn head + update.values.map(packValue).join(`\\u001E`)\n\t}\n\treturn head + packValue(update.value)\n}\nexport function unpackSetUpdate<P extends primitive>(\n\tpacked: PackedSetUpdate<P>,\n): SetUpdate<P> {\n\tconst [type, tail] = packed.split(`\\u001F`) as [0 | 1 | 2, string]\n\tconst head = SET_UPDATE_ENUM[type]\n\tif (head === `clear`) {\n\t\tconst values = tail.split(`\\u001E`).map(unpackValue) as P[]\n\t\treturn { type: `clear`, values }\n\t}\n\treturn { type: head, value: unpackValue(tail) as P }\n}\n\nexport type SetMutationHandler = { [K in UListUpdateType]: Fn }\n\nexport class UList<P extends primitive>\n\textends Set<P>\n\timplements\n\t\tTransceiver<ReadonlySet<P>, PackedSetUpdate<P>, ReadonlyArray<P>>,\n\t\tSetMutationHandler\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<PackedSetUpdate<P>> = new Subject()\n\n\tpublic constructor(values?: Iterable<P>) {\n\t\tsuper(values)\n\t\tif (values instanceof UList) {\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: ReadonlySet<P> = this\n\n\tpublic toJSON(): ReadonlyArray<P> {\n\t\treturn [...this]\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: ReadonlyArray<P>): UList<P> {\n\t\treturn new UList<P>(json)\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.emit({ type: `add`, value })\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.emit({ type: `clear`, values: capturedContents })\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.emit({ type: `delete`, value })\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: PackedSetUpdate<P>) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\n\tpublic emit(update: SetUpdate<P>): void {\n\t\tthis.subject.next(packSetUpdate(update))\n\t}\n\n\tpublic do(packed: PackedSetUpdate<P>): null {\n\t\tthis.mode = `playback`\n\t\tconst update = unpackSetUpdate(packed)\n\t\tswitch (update.type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(update.value)\n\t\t\t\tbreak\n\t\t\tcase `delete`:\n\t\t\t\tthis.delete(update.value)\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t}\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n\n\tpublic undo(packed: PackedSetUpdate<P>): number | null {\n\t\tconst update = unpackSetUpdate(packed)\n\t\tthis.mode = `playback`\n\t\tswitch (update.type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(update.value)\n\t\t\t\tbreak\n\t\t\tcase `delete`:\n\t\t\t\tthis.add(update.value)\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = update.values\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t}\n\t\t}\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n}\n"],"mappings":";;;AA+BA,MAAaA,kBACZ,YAAY;CAAC;CAAO;CAAU;CAAQ,CAAU;AAEjD,SAAgB,cACf,QACqB;CACrB,MAAM,OAAO,gBAAgB,OAAO,QAAQ;AAC5C,KAAI,OAAO,SAAS,QACnB,QAAO,OAAO,OAAO,OAAO,IAAI,UAAU,CAAC,KAAK,SAAS;AAE1D,QAAO,OAAO,UAAU,OAAO,MAAM;;AAEtC,SAAgB,gBACf,QACe;CACf,MAAM,CAAC,MAAM,QAAQ,OAAO,MAAM,SAAS;CAC3C,MAAM,OAAO,gBAAgB;AAC7B,KAAI,SAAS,QAEZ,QAAO;EAAE,MAAM;EAAS,QADT,KAAK,MAAM,SAAS,CAAC,IAAI,YAAY;EACpB;AAEjC,QAAO;EAAE,MAAM;EAAM,OAAO,YAAY,KAAK;EAAO;;AAKrD,IAAa,QAAb,MAAa,cACJ,IAIT;CACC,AAAO,OAAwB;CAC/B,AAAgB,UAAuC,IAAI,SAAS;CAEpE,AAAO,YAAY,QAAsB;AACxC,QAAM,OAAO;AACb,MAAI,kBAAkB,OAAO;;CAI9B,AAAgB,gBAAgC;CAEhD,AAAO,SAA2B;AACjC,SAAO,CAAC,GAAG,KAAK;;CAGjB,OAAc,SAA8B,MAAkC;AAC7E,SAAO,IAAI,MAAS,KAAK;;CAG1B,AAAO,IAAI,OAAgB;EAC1B,MAAM,SAAS,MAAM,IAAI,MAAM;AAC/B,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK;GAAE,MAAM;GAAO;GAAO,CAAC;AAElC,SAAO;;CAGR,AAAO,QAAc;EACpB,MAAM,mBAAmB,KAAK,SAAS,WAAW,CAAC,GAAG,KAAK,GAAG;AAC9D,QAAM,OAAO;AACb,MAAI,iBACH,MAAK,KAAK;GAAE,MAAM;GAAS,QAAQ;GAAkB,CAAC;;CAIxD,AAAO,OAAO,OAAmB;EAChC,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK;GAAE,MAAM;GAAU;GAAO,CAAC;AAErC,SAAO;;CAGR,AAAO,UACN,KACA,IACa;AACb,SAAO,KAAK,QAAQ,UAAU,KAAK,GAAG;;CAGvC,AAAO,KAAK,QAA4B;AACvC,OAAK,QAAQ,KAAK,cAAc,OAAO,CAAC;;CAGzC,AAAO,GAAG,QAAkC;AAC3C,OAAK,OAAO;EACZ,MAAM,SAAS,gBAAgB,OAAO;AACtC,UAAQ,OAAO,MAAf;GACC,KAAK;AACJ,SAAK,IAAI,OAAO,MAAM;AACtB;GACD,KAAK;AACJ,SAAK,OAAO,OAAO,MAAM;AACzB;GACD,KAAK,QACJ,MAAK,OAAO;;AAEd,OAAK,OAAO;AACZ,SAAO;;CAGR,AAAO,KAAK,QAA2C;EACtD,MAAM,SAAS,gBAAgB,OAAO;AACtC,OAAK,OAAO;AACZ,UAAQ,OAAO,MAAf;GACC,KAAK;AACJ,SAAK,OAAO,OAAO,MAAM;AACzB;GACD,KAAK;AACJ,SAAK,IAAI,OAAO,MAAM;AACtB;GACD,KAAK,SAAS;IACb,MAAM,SAAS,OAAO;AACtB,SAAK,MAAM,KAAK,OAAQ,MAAK,IAAI,EAAE;;;AAGrC,OAAK,OAAO;AACZ,SAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.40.9",
3
+ "version": "0.41.0",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -61,20 +61,20 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint/core": "0.15.2",
64
- "@storybook/addon-docs": "9.1.5",
65
- "@storybook/addon-onboarding": "9.1.5",
66
- "@storybook/react-vite": "9.1.5",
64
+ "@storybook/addon-docs": "9.1.6",
65
+ "@storybook/addon-onboarding": "9.1.6",
66
+ "@storybook/react-vite": "9.1.6",
67
67
  "@testing-library/react": "16.3.0",
68
- "@types/bun": "npm:bun-types@1.2.21",
68
+ "@types/bun": "npm:bun-types@1.2.22",
69
69
  "@types/eslint": "9.6.1",
70
70
  "@types/estree": "1.0.8",
71
71
  "@types/http-proxy": "1.17.16",
72
72
  "@types/npmlog": "7.0.0",
73
73
  "@types/react": "19.1.13",
74
74
  "@types/tmp": "0.2.6",
75
- "@typescript-eslint/parser": "8.43.0",
76
- "@typescript-eslint/rule-tester": "8.43.0",
77
- "@typescript-eslint/utils": "8.43.0",
75
+ "@typescript-eslint/parser": "8.44.0",
76
+ "@typescript-eslint/rule-tester": "8.44.0",
77
+ "@typescript-eslint/utils": "8.44.0",
78
78
  "@vitest/coverage-v8": "3.2.4",
79
79
  "@vitest/ui": "3.2.4",
80
80
  "concurrently": "9.2.1",
@@ -83,20 +83,20 @@
83
83
  "eslint": "9.35.0",
84
84
  "happy-dom": "18.0.1",
85
85
  "http-proxy": "1.18.1",
86
- "motion": "12.23.12",
86
+ "motion": "12.23.13",
87
87
  "npmlog": "7.0.1",
88
88
  "nyc": "17.1.0",
89
89
  "postgres": "3.4.7",
90
- "preact": "10.27.1",
90
+ "preact": "10.27.2",
91
91
  "react": "19.1.1",
92
92
  "react-dom": "19.1.1",
93
- "react-router-dom": "7.9.0",
93
+ "react-router-dom": "7.9.1",
94
94
  "recoverage": "0.1.11",
95
95
  "socket.io": "4.8.1",
96
96
  "socket.io-client": "4.8.1",
97
- "storybook": "9.1.5",
97
+ "storybook": "9.1.6",
98
98
  "tmp": "0.2.5",
99
- "tsdown": "0.15.1",
99
+ "tsdown": "0.15.2",
100
100
  "typescript": "5.9.2",
101
101
  "vite": "7.1.5",
102
102
  "vite-tsconfig-paths": "5.1.4",
@@ -166,6 +166,10 @@
166
166
  "import": "./dist/realtime-testing/index.js",
167
167
  "types": "./dist/realtime-testing/index.d.ts"
168
168
  },
169
+ "./transceivers/o-list": {
170
+ "import": "./dist/transceivers/o-list/index.js",
171
+ "types": "./dist/transceivers/o-list/index.d.ts"
172
+ },
169
173
  "./transceivers/set-rtx": {
170
174
  "import": "./dist/transceivers/set-rtx/index.js",
171
175
  "types": "./dist/transceivers/set-rtx/index.d.ts"
@@ -14,6 +14,7 @@ export * from "./join"
14
14
  export * from "./junction"
15
15
  export * from "./keys"
16
16
  export * from "./lineage"
17
+ export * from "./micro"
17
18
  export * from "./molecule"
18
19
  export * from "./mutable"
19
20
  export * from "./not-found-error"
@@ -0,0 +1,69 @@
1
+ import type { primitive } from "atom.io/json"
2
+
3
+ import type { Flat } from "./utility-types"
4
+
5
+ export type IndexOf<
6
+ T extends readonly unknown[],
7
+ E,
8
+ A extends unknown[] = [],
9
+ > = T extends readonly [infer Head, ...infer Tail]
10
+ ? (<U>() => U extends Head ? 1 : 2) extends <U>() => U extends E ? 1 : 2
11
+ ? A[`length`]
12
+ : IndexOf<Tail, E, [...A, unknown]>
13
+ : never
14
+
15
+ export type Flip<T extends Record<string, number | string>> = {
16
+ [K in keyof T as T[K]]: K
17
+ }
18
+
19
+ export type TwoWay<T extends Record<string, number | string>> = Flip<T> & T
20
+
21
+ export type Enumeration<T extends readonly string[]> = Flat<
22
+ TwoWay<{
23
+ [K in T[number]]: IndexOf<T, K>
24
+ }>
25
+ >
26
+
27
+ export function enumeration<T extends readonly string[]>(
28
+ values: T,
29
+ ): Enumeration<T> {
30
+ const result: Record<any, any> = {}
31
+ let i = 0
32
+ for (const value of values) {
33
+ result[value] = i
34
+ result[i] = value
35
+ ++i
36
+ }
37
+ return result as Enumeration<T>
38
+ }
39
+
40
+ const BOOL = `\u0001`
41
+ const NULL = `\u0002`
42
+ const STRING = `\u0003`
43
+ const NUMBER = `\u0004`
44
+ export const packValue = (value: primitive): string => {
45
+ const type = typeof value as `boolean` | `number` | `object` | `string`
46
+ switch (type) {
47
+ case `string`:
48
+ return STRING + value
49
+ case `number`:
50
+ return NUMBER + value
51
+ case `boolean`:
52
+ return BOOL + +(value as boolean)
53
+ case `object`:
54
+ return NULL
55
+ }
56
+ }
57
+ export const unpackValue = (value: string): primitive => {
58
+ const type = value[0] as `\u0001` | `\u0002` | `\u0003` | `\u0004`
59
+ switch (type) {
60
+ case STRING:
61
+ return value.slice(1)
62
+ case NUMBER:
63
+ return +value.slice(1)
64
+ case BOOL:
65
+ return value.slice(1) === `1`
66
+ case NULL:
67
+ return null
68
+ }
69
+ }
@@ -4,6 +4,7 @@ import type {
4
4
  ReadonlyPureSelectorFamilyToken,
5
5
  } from "atom.io"
6
6
  import { getInternalRelations, join, mutableAtom, selectorFamily } from "atom.io"
7
+ import type { SetRTX } from "atom.io/transceivers/set-rtx"
7
8
  import { UList } from "atom.io/transceivers/u-list"
8
9
 
9
10
  export const usersInThisRoomIndex: MutableAtomToken<UList<string>> = mutableAtom<
@@ -45,9 +46,9 @@ export const usersInRooms: JoinToken<
45
46
  )
46
47
 
47
48
  export const usersInMyRoomView: ReadonlyPureSelectorFamilyToken<
48
- MutableAtomToken<UList<string>>[],
49
+ MutableAtomToken<SetRTX<string>>[],
49
50
  string
50
- > = selectorFamily<MutableAtomToken<UList<string>>[], string>({
51
+ > = selectorFamily<MutableAtomToken<SetRTX<string>>[], string>({
51
52
  key: `usersInMyRoomView`,
52
53
  get:
53
54
  (myUsername) =>
@@ -76,7 +76,7 @@ export class ParentSocket<
76
76
  this.proc.stderr.write(
77
77
  stringifyJson(
78
78
  args.map((arg) =>
79
- arg instanceof UList ? `{ ${arg.toJSON().members.join(` | `)} }` : arg,
79
+ arg instanceof UList ? `{ ${arg.toJSON().join(` | `)} }` : arg,
80
80
  ),
81
81
  ) + `\x03`,
82
82
  )
@@ -0,0 +1 @@
1
+ export * from "./o-list"