informa 1.0.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 (53) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/README.md +238 -0
  3. package/dist/EnumerableWeakMap.d.ts +13 -0
  4. package/dist/EnumerableWeakMap.d.ts.map +1 -0
  5. package/dist/EnumerableWeakMap.js +56 -0
  6. package/dist/EnumerableWeakMap.js.map +1 -0
  7. package/dist/clone.d.ts +2 -0
  8. package/dist/clone.d.ts.map +1 -0
  9. package/dist/clone.js +30 -0
  10. package/dist/clone.js.map +1 -0
  11. package/dist/high.d.ts +60 -0
  12. package/dist/high.d.ts.map +1 -0
  13. package/dist/high.js +107 -0
  14. package/dist/high.js.map +1 -0
  15. package/dist/internals.d.ts +14 -0
  16. package/dist/internals.d.ts.map +1 -0
  17. package/dist/internals.js +24 -0
  18. package/dist/internals.js.map +1 -0
  19. package/dist/low.d.ts +57 -0
  20. package/dist/low.d.ts.map +1 -0
  21. package/dist/low.js +260 -0
  22. package/dist/low.js.map +1 -0
  23. package/dist/quirks/array.d.ts +21 -0
  24. package/dist/quirks/array.d.ts.map +1 -0
  25. package/dist/quirks/array.js +176 -0
  26. package/dist/quirks/array.js.map +1 -0
  27. package/dist/quirks/basestatified.d.ts +5 -0
  28. package/dist/quirks/basestatified.d.ts.map +1 -0
  29. package/dist/quirks/basestatified.js +117 -0
  30. package/dist/quirks/basestatified.js.map +1 -0
  31. package/dist/quirks/set.d.ts +12 -0
  32. package/dist/quirks/set.d.ts.map +1 -0
  33. package/dist/quirks/set.js +37 -0
  34. package/dist/quirks/set.js.map +1 -0
  35. package/dist/test.d.ts +2 -0
  36. package/dist/test.d.ts.map +1 -0
  37. package/dist/test.js +37 -0
  38. package/dist/test.js.map +1 -0
  39. package/dist/utils.d.ts +5 -0
  40. package/dist/utils.d.ts.map +1 -0
  41. package/dist/utils.js +23 -0
  42. package/dist/utils.js.map +1 -0
  43. package/package.json +28 -0
  44. package/src/EnumerableWeakMap.ts +63 -0
  45. package/src/high.ts +163 -0
  46. package/src/internals.ts +32 -0
  47. package/src/low.ts +411 -0
  48. package/src/quirks/array.ts +211 -0
  49. package/src/quirks/basestatified.ts +194 -0
  50. package/src/quirks/set.ts +48 -0
  51. package/src/test.ts +49 -0
  52. package/src/utils.ts +31 -0
  53. package/tsconfig.json +44 -0
@@ -0,0 +1,37 @@
1
+ import { exitProxySymbol, setMetadataOf, statifySealKey } from "../internals.js";
2
+ import { StateMetadata } from "../low.js";
3
+ export class StatifiedSet extends Set {
4
+ [statifySealKey] = true;
5
+ #metadata;
6
+ constructor(args) {
7
+ super(args);
8
+ this.#metadata = setMetadataOf(this, new StateMetadata());
9
+ }
10
+ add(value) {
11
+ if (!super.has(value)) {
12
+ super.add(value);
13
+ this.#metadata.emit("addItem", value);
14
+ this.#metadata.emit("sizeChanged");
15
+ }
16
+ return this;
17
+ }
18
+ clear() {
19
+ const oldValues = [...this.values()];
20
+ super.clear();
21
+ for (const value of oldValues) {
22
+ this.#metadata.emit("deleteItem", value);
23
+ }
24
+ if (oldValues.length > 0) {
25
+ this.#metadata.emit("sizeChanged");
26
+ }
27
+ }
28
+ delete(value) {
29
+ if (super.delete(value)) {
30
+ this.#metadata.emit("deleteItem", value);
31
+ this.#metadata.emit("sizeChanged");
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ }
37
+ //# sourceMappingURL=set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.js","sourceRoot":"","sources":["../../src/quirks/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAA6C,MAAM,WAAW,CAAC;AAErF,MAAM,OAAO,YAAwC,SAAQ,GAAM;IACjE,CAAC,cAAc,CAAC,GAAS,IAAI,CAAC;IAG9B,SAAS,CAAgB;IAEzB,YAAY,IAAyB;QACnC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,GAAG,CAAC,KAAQ;QACV,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAErC,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAQ;QACb,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
package/dist/test.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":""}
package/dist/test.js ADDED
@@ -0,0 +1,37 @@
1
+ import $ from "./high.js";
2
+ import { BaseStatified } from "./quirks/basestatified.js";
3
+ import { StatifiedSet } from "./quirks/set.js";
4
+ const stateful = $.state({ a: [] });
5
+ $.onSpliceInElement(() => stateful.a, (v) => {
6
+ console.log("pushed", v);
7
+ $.onSet(() => v.d, (newValue) => {
8
+ console.log("New value is", newValue);
9
+ });
10
+ });
11
+ $.onSet(() => stateful.b?.c?.d, (newValue) => {
12
+ console.log("New value of .b.c.d is", newValue);
13
+ });
14
+ const b = $.state({ d: 3 });
15
+ stateful.a.push(b);
16
+ b.d = 10;
17
+ const asdf = $.state({ d: new Set() });
18
+ const asdf2 = $.state({ c: asdf });
19
+ // const aassddff = $.state(new Set());
20
+ stateful.b = asdf2;
21
+ class Wayland extends BaseStatified {
22
+ displays = new StatifiedSet();
23
+ #state = 0;
24
+ get state() { return this.#state; }
25
+ set state(v) {
26
+ console.log("set", v);
27
+ this.#state = v;
28
+ super.state = v;
29
+ }
30
+ constructor() {
31
+ super();
32
+ }
33
+ }
34
+ const w = new Wayland();
35
+ $.onSet(() => w.state, (v) => console.log("asdf awawa!!", v));
36
+ w.state = 5;
37
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,WAAW,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAA4D,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAE/F,CAAC,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;IAC1C,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAEzB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE;IAC3C,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5B,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEnB,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAET,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC,CAAC;AAC/C,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AAEnC,uCAAuC;AACvC,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC;AAEnB,MAAM,OAAQ,SAAQ,aAAa;IACjC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IAE9B,MAAM,GAAG,CAAC,CAAC;IACX,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,CAAS;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACrB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAClB,CAAC;IAED;QACE,KAAK,EAAE,CAAC;IACV,CAAC;CACF;AAED,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;AACxB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;AAE9D,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function ofWhichIsProto<T extends object, U extends symbol>(target: object, expect: Map<T, U>): U | undefined;
2
+ export declare const isSetProto: unique symbol;
3
+ export declare const supportedQuirks: Map<Set<any>, typeof isSetProto>;
4
+ export declare function isListInGrid<T>(grid: T[][], list: T[]): boolean;
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAanH;AAED,eAAO,MAAM,UAAU,eAAW,CAAC;AACnC,eAAO,MAAM,eAAe,kCAEjB,CAAC;AAGZ,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,CAAC,EAAE,EAAE,EACX,IAAI,EAAE,CAAC,EAAE,WAOV"}
package/dist/utils.js ADDED
@@ -0,0 +1,23 @@
1
+ export function ofWhichIsProto(target, expect) {
2
+ let current = Reflect.getPrototypeOf(target);
3
+ while (current) {
4
+ const correspondingSymbol = expect.get(current);
5
+ if (correspondingSymbol) {
6
+ return correspondingSymbol;
7
+ }
8
+ current = Reflect.getPrototypeOf(current);
9
+ }
10
+ return undefined;
11
+ }
12
+ export const isSetProto = Symbol();
13
+ export const supportedQuirks = new Map([
14
+ [Set.prototype, isSetProto]
15
+ ]);
16
+ export function isListInGrid(grid, list) {
17
+ return grid.some((row) => {
18
+ if (row.length !== list.length)
19
+ return false;
20
+ return row.every((v, i) => v === list[i]);
21
+ });
22
+ }
23
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAqC,MAAc,EAAE,MAAiB;IAClG,IAAI,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAE7C,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC,OAAY,CAAC,CAAC;QACrD,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QAED,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IACrC,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC;CACnB,CAAC,CAAC;AAGZ,MAAM,UAAU,YAAY,CAC1B,IAAW,EACX,IAAS;IAET,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAE7C,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "informa",
3
+ "version": "1.0.0",
4
+ "description": "Informa's State Management",
5
+ "keywords": [
6
+ "state management",
7
+ "proxy"
8
+ ],
9
+ "homepage": "https://github.com/immjs/informa#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/immjs/informa/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/immjs/informa.git"
16
+ },
17
+ "license": "ISC",
18
+ "author": "Juliette Wang <immjs>",
19
+ "type": "module",
20
+ "main": "dist/high.js",
21
+ "scripts": {
22
+ "test": "echo \"Error: no test specified\" && exit 1"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^26.1.1",
26
+ "typescript": "^7.0.2"
27
+ }
28
+ }
@@ -0,0 +1,63 @@
1
+ export class EnumerableWeakMap<K extends WeakKey, V> implements WeakMap<K, V>, Iterable<[K, V]> {
2
+ #map = new WeakMap<K, V>();
3
+
4
+ #refs: WeakRef<K>[] = [];
5
+
6
+ constructor(iterable: Iterable<[K, V]> | null = null) {
7
+ if (iterable) for (const [key, value] of iterable) this.set(key, value);
8
+ }
9
+
10
+ get [Symbol.toStringTag]() {
11
+ return "WeakerableMapByWebReflection";
12
+ }
13
+
14
+ get(key: K) {
15
+ return this.#map.get(key);
16
+ }
17
+
18
+ getOrInsert(key: K, defaultValue: V): V {
19
+ if (this.#map.has(key)) {
20
+ return this.#map.get(key)!;
21
+ }
22
+ this.#map.set(key, defaultValue);
23
+ this.#refs.push(new WeakRef(key));
24
+ return defaultValue;
25
+ }
26
+
27
+ getOrInsertComputed(key: K, callback: (k: K) => V): V {
28
+ if (this.#map.has(key)) {
29
+ return this.#map.get(key)!;
30
+ }
31
+ const value = callback(key);
32
+ this.#map.set(key, value);
33
+ this.#refs.push(new WeakRef(key));
34
+ return value;
35
+ }
36
+
37
+ set(key: K, value: V): this {
38
+ if (!this.#map.has(key)) this.#refs.push(new WeakRef(key));
39
+ this.#map.set(key, value);
40
+
41
+ return this;
42
+ }
43
+
44
+ delete(value: K) {
45
+ return this.#map.delete(value);
46
+ }
47
+
48
+ has(value: K) {
49
+ return this.#map.has(value);
50
+ }
51
+
52
+ *[Symbol.iterator]() {
53
+ const map = this.#map, refs = [];
54
+ for (const wr of this.#refs) {
55
+ const key = wr.deref();
56
+ if (key && map.has(key)) {
57
+ refs.push(wr);
58
+ yield [key, map.get(key)!] satisfies [K, V];
59
+ }
60
+ }
61
+ this.#refs = refs;
62
+ }
63
+ }
package/src/high.ts ADDED
@@ -0,0 +1,163 @@
1
+ import { getMetadataOf, isStatified, proxyMemoized, type Statify } from "./internals.js";
2
+ import { hook, selectorToRootAndPath, statifyObject, type StatifiableObj, type StatifiableProp, type Statified } from "./low.js";
3
+ import { StatifiedArray } from "./quirks/array.js";
4
+ import { StatifiedSet } from "./quirks/set.js";
5
+
6
+ export function stateInner<T extends StatifiableProp>(original: T): Statified<T> {
7
+ if (typeof original !== 'object' || original === null) {
8
+ return original as Statified<T>;
9
+ }
10
+
11
+ if (proxyMemoized.has(original)) return proxyMemoized.get(original) as Statified<T>;
12
+
13
+ const unmemoed = (() => {
14
+ switch (Reflect.getPrototypeOf(original)) {
15
+ case Set.prototype:
16
+ const set = original as unknown as Set<any>;
17
+ return new StatifiedSet(set[Symbol.iterator]().map(stateInner));
18
+
19
+ case Array.prototype:
20
+ const array = original as unknown as any[];
21
+ return new StatifiedArray(...array.map(stateInner));
22
+
23
+ case StatifiedArray.prototype:
24
+ case StatifiedSet.prototype:
25
+ return original as StatifiedArray<StatifiableProp> | StatifiedSet<StatifiableProp>;
26
+
27
+ case Object.prototype:
28
+ const newObj = original as unknown as Record<string | symbol, any>;
29
+ const entries = Object.entries(newObj)
30
+ .map(([k, v]) => [k, stateInner(v)]);
31
+ const result = statifyObject(Object.fromEntries(entries));
32
+
33
+ entries.forEach(([k, v]) => isStatified(v) && hook(getMetadataOf(result), k, getMetadataOf(v)))
34
+
35
+ return result;
36
+ }
37
+
38
+ if (Array.isArray(original)) {
39
+ return new StatifiedArray(...original.map(stateInner));
40
+ }
41
+
42
+ throw new Error(`Cannot clone object with prototype`);
43
+ })();
44
+
45
+ proxyMemoized.set(original, unmemoed);
46
+
47
+ return unmemoed as Statified<T>;
48
+ }
49
+
50
+ export function state<T extends StatifiableObj>(original: T): Statified<T> {
51
+ return stateInner<T>(original);
52
+ }
53
+
54
+ interface Options {
55
+ }
56
+
57
+ interface Listeners<T> {
58
+ set?(v: T): void;
59
+ replace?(v: T): void;
60
+ }
61
+
62
+ interface ObjectListeners<K extends string | number | symbol, V> extends Listeners<Record<K, V>> {
63
+ setProp?(v: V, i: string | symbol): void;
64
+ replaceProp?(v: V, i: string | symbol): void;
65
+ deleteProp?(v: V, i: string | symbol): void;
66
+ }
67
+
68
+ interface ArrayListeners<T> extends ObjectListeners<number, T> {
69
+ spliceInElement?(v: T, i: number): void;
70
+ spliceOutElement?(v: T, i: number): void;
71
+ replaceElement?(v: T, i: number): void;
72
+ lengthChanged?(): void;
73
+ }
74
+
75
+ interface SetListeners<T> extends ObjectListeners<keyof Set<T>, Set<T>[keyof Set<T>]> {
76
+ addItem?(v: T): void;
77
+ deleteItem?(v: T): void;
78
+ sizeChanged?(): void;
79
+ }
80
+
81
+ export function on<T, K extends string | number | symbol, V, U>(
82
+ ...[selector, listeners, options]:
83
+ [() => T, Listeners<T>]
84
+ | [() => T, Listeners<T>, Options | undefined]
85
+ | [() => Statify<Record<K, V>>, ObjectListeners<K, V>]
86
+ | [() => Statify<Record<K, V>>, ObjectListeners<K, V>, Options | undefined]
87
+ | [() => Statify<U[]>, ArrayListeners<U>]
88
+ | [() => Statify<U[]>, ArrayListeners<U>, Options | undefined]
89
+ | [() => Statify<Set<U>>, SetListeners<U>]
90
+ | [() => Statify<Set<U>>, SetListeners<U>, Options | undefined]
91
+ ): () => void {
92
+ const { path, stateRoot } = selectorToRootAndPath(selector as () => Statify<StatifiableObj>);
93
+
94
+ const metadata = getMetadataOf(stateRoot);
95
+
96
+ const eventEmitter = metadata.eventEmitterAtPath(path);
97
+
98
+ for (const [key, value] of Object.entries(listeners)) {
99
+ eventEmitter.on(key, value);
100
+ }
101
+
102
+ return () => {
103
+ for (const [key, value] of Object.entries(listeners)) {
104
+ eventEmitter.off(key, value);
105
+ }
106
+ }
107
+ }
108
+
109
+ function onSet<T>(s: () => T, l: (v: T) => void, o?: Options) {
110
+ // TODO Handle `once` option
111
+ return on(s, { set: l }, o);
112
+ }
113
+ function onReplace<T>(s: () => T, l: (v: T) => void, o?: Options) {
114
+ return on(s, { replace: l }, o);
115
+ }
116
+
117
+ function onReplaceProp<T extends Record<string | number | symbol, StatifiableProp>>(s: () => Statify<T>, l: (v: T[keyof T], k: keyof T) => void, o?: Options) {
118
+ return on(s, { replaceProp: l }, o);
119
+ }
120
+ function onDeleteProp<T extends Record<string | number | symbol, StatifiableProp>>(s: () => Statify<T>, l: (v: T[keyof T], k: keyof T) => void, o?: Options) {
121
+ return on(s, { deleteProp: l }, o);
122
+ }
123
+ function onSetProp<T extends Record<string | number | symbol, StatifiableProp>>(s: () => Statify<T>, l: (v: T[keyof T], k: keyof T) => void, o?: Options) {
124
+ return on(s, { setProp: l }, o);
125
+ }
126
+ function onLengthChanged(s: () => Statify<StatifiableObj[]>, l: () => void, o?: Options) {
127
+ return on(s, { lengthChanged: l }, o);
128
+ }
129
+ function onSpliceInElement<T extends StatifiableObj>(s: () => Statify<T[]>, l: (v: T, k: number) => void, o?: Options) {
130
+ return on(s, { spliceInElement: l }, o);
131
+ }
132
+ function onSpliceOutElement<T extends StatifiableObj>(s: () => Statify<T[]>, l: (v: T, k: number) => void, o?: Options) {
133
+ return on(s, { spliceOutElement: l }, o);
134
+ }
135
+ function onReplaceElement<T extends StatifiableObj>(s: () => Statify<T[]>, l: (v: T, k: number) => void, o?: Options) {
136
+ return on(s, { replaceElement: l }, o);
137
+ }
138
+ function onSizeChanged<T extends StatifiableObj>(s: () => Statify<Set<T>>, l: () => void, o?: Options) {
139
+ return on(s, { sizeChanged: l }, o);
140
+ }
141
+ function onAddItem<T extends StatifiableObj>(s: () => Statify<Set<T>>, l: (v: T) => void, o?: Options) {
142
+ return on(s, { addItem: l }, o);
143
+ }
144
+ function onDeleteItem<T extends StatifiableObj>(s: () => Statify<Set<T>>, l: (v: T) => void, o?: Options) {
145
+ return on(s, { deleteItem: l }, o);
146
+ }
147
+
148
+ export default {
149
+ on,
150
+ onSet,
151
+ onReplace,
152
+ onReplaceProp,
153
+ onDeleteProp,
154
+ onSetProp,
155
+ onLengthChanged,
156
+ onSpliceInElement,
157
+ onSpliceOutElement,
158
+ onReplaceElement,
159
+ onSizeChanged,
160
+ onAddItem,
161
+ onDeleteItem,
162
+ state,
163
+ };
@@ -0,0 +1,32 @@
1
+ import type { StateMetadata, Exitable, StatifiableObj } from "./low.js";
2
+
3
+ export const exitProxySymbol = Symbol();
4
+
5
+ // The mode is used by the functions exposed by informa,
6
+ // no concurrency issues arise because of the unique call stack.
7
+ export let globalStateMode: "normal" | "extract-proxy-path" = "normal";
8
+ export function setGlobalStateMode(mode: "normal" | "extract-proxy-path") {
9
+ globalStateMode = mode;
10
+ }
11
+
12
+ export const metadataMap = new WeakMap<Statify<StatifiableObj>, StateMetadata>();
13
+ export function getMetadataOf(v: Statify<StatifiableObj>) {
14
+ const result = metadataMap.get(v);
15
+
16
+ if (!result) throw new Error("Assertion failed: Metadata should have been created alongside statified object");
17
+
18
+ return result;
19
+ }
20
+ export function setMetadataOf(v: Statify<StatifiableObj>, s: StateMetadata) {
21
+ metadataMap.set(v, s);
22
+
23
+ return s;
24
+ }
25
+
26
+ export const proxyMemoized = new WeakMap<object, Statify<StatifiableObj>>();
27
+
28
+ export const statifySealKey = Symbol();
29
+ export function isStatified<T extends StatifiableObj>(v: T): v is Statify<T> {
30
+ return (v as Statify<T>)[statifySealKey];
31
+ }
32
+ export type Statify<T extends StatifiableObj> = T & { [statifySealKey]: true } & Exitable;