@graphrefly/graphrefly 0.25.0 → 0.26.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.
- package/README.md +8 -0
- package/dist/{chunk-QOWVNWOC.js → chunk-3ZWCKRHX.js} +27 -25
- package/dist/{chunk-QOWVNWOC.js.map → chunk-3ZWCKRHX.js.map} +1 -1
- package/dist/chunk-6LDQFTYS.js +102 -0
- package/dist/chunk-6LDQFTYS.js.map +1 -0
- package/dist/{chunk-IAHGTNOZ.js → chunk-AMCG74RZ.js} +193 -24
- package/dist/chunk-AMCG74RZ.js.map +1 -0
- package/dist/{chunk-L2GLW2U7.js → chunk-BVZYTZ5H.js} +9 -103
- package/dist/chunk-BVZYTZ5H.js.map +1 -0
- package/dist/chunk-FQMKGR6L.js +330 -0
- package/dist/chunk-FQMKGR6L.js.map +1 -0
- package/dist/chunk-HXZEYDUR.js +94 -0
- package/dist/chunk-HXZEYDUR.js.map +1 -0
- package/dist/{chunk-EVR6UFUV.js → chunk-IZYUSJC7.js} +16 -14
- package/dist/{chunk-EVR6UFUV.js.map → chunk-IZYUSJC7.js.map} +1 -1
- package/dist/chunk-J22W6HV3.js +107 -0
- package/dist/chunk-J22W6HV3.js.map +1 -0
- package/dist/{chunk-HWPIFSW2.js → chunk-JSCT3CR4.js} +6 -4
- package/dist/{chunk-HWPIFSW2.js.map → chunk-JSCT3CR4.js.map} +1 -1
- package/dist/chunk-JYXEWPH4.js +62 -0
- package/dist/chunk-JYXEWPH4.js.map +1 -0
- package/dist/{chunk-TKE3JGOH.js → chunk-LCE3GF5P.js} +5 -692
- package/dist/chunk-LCE3GF5P.js.map +1 -0
- package/dist/chunk-MJ2NKQQL.js +119 -0
- package/dist/chunk-MJ2NKQQL.js.map +1 -0
- package/dist/chunk-N6UR7YVY.js +198 -0
- package/dist/chunk-N6UR7YVY.js.map +1 -0
- package/dist/chunk-OHISZPOJ.js +97 -0
- package/dist/chunk-OHISZPOJ.js.map +1 -0
- package/dist/{chunk-5DJTTKX3.js → chunk-PHOUUNK7.js} +74 -111
- package/dist/chunk-PHOUUNK7.js.map +1 -0
- package/dist/{chunk-PY4XCDLR.js → chunk-RB6QPHJ7.js} +8 -6
- package/dist/{chunk-PY4XCDLR.js.map → chunk-RB6QPHJ7.js.map} +1 -1
- package/dist/chunk-SN4YWWYO.js +171 -0
- package/dist/chunk-SN4YWWYO.js.map +1 -0
- package/dist/chunk-SX52TAR4.js +110 -0
- package/dist/chunk-SX52TAR4.js.map +1 -0
- package/dist/{chunk-XOFWRC73.js → chunk-THTWHNU4.js} +319 -24
- package/dist/chunk-THTWHNU4.js.map +1 -0
- package/dist/{chunk-H4RVA4VE.js → chunk-VYPWMZ6H.js} +2 -2
- package/dist/chunk-XGPU467M.js +136 -0
- package/dist/chunk-XGPU467M.js.map +1 -0
- package/dist/chunk-ZQMEI34O.js +713 -0
- package/dist/chunk-ZQMEI34O.js.map +1 -0
- package/dist/compat/index.cjs +7656 -0
- package/dist/compat/index.cjs.map +1 -0
- package/dist/compat/index.d.cts +18 -0
- package/dist/compat/index.d.ts +18 -0
- package/dist/compat/index.js +49 -0
- package/dist/compat/index.js.map +1 -0
- package/dist/compat/jotai/index.cjs +2048 -0
- package/dist/compat/jotai/index.cjs.map +1 -0
- package/dist/compat/jotai/index.d.cts +2 -0
- package/dist/compat/jotai/index.d.ts +2 -0
- package/dist/compat/jotai/index.js +9 -0
- package/dist/compat/jotai/index.js.map +1 -0
- package/dist/compat/nanostores/index.cjs +2175 -0
- package/dist/compat/nanostores/index.cjs.map +1 -0
- package/dist/compat/nanostores/index.d.cts +2 -0
- package/dist/compat/nanostores/index.d.ts +2 -0
- package/dist/compat/nanostores/index.js +23 -0
- package/dist/compat/nanostores/index.js.map +1 -0
- package/dist/compat/nestjs/index.cjs +350 -16
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +6 -6
- package/dist/compat/nestjs/index.d.ts +6 -6
- package/dist/compat/nestjs/index.js +10 -9
- package/dist/compat/react/index.cjs +141 -0
- package/dist/compat/react/index.cjs.map +1 -0
- package/dist/compat/react/index.d.cts +2 -0
- package/dist/compat/react/index.d.ts +2 -0
- package/dist/compat/react/index.js +12 -0
- package/dist/compat/react/index.js.map +1 -0
- package/dist/compat/solid/index.cjs +128 -0
- package/dist/compat/solid/index.cjs.map +1 -0
- package/dist/compat/solid/index.d.cts +2 -0
- package/dist/compat/solid/index.d.ts +2 -0
- package/dist/compat/solid/index.js +12 -0
- package/dist/compat/solid/index.js.map +1 -0
- package/dist/compat/svelte/index.cjs +131 -0
- package/dist/compat/svelte/index.cjs.map +1 -0
- package/dist/compat/svelte/index.d.cts +2 -0
- package/dist/compat/svelte/index.d.ts +2 -0
- package/dist/compat/svelte/index.js +12 -0
- package/dist/compat/svelte/index.js.map +1 -0
- package/dist/compat/vue/index.cjs +146 -0
- package/dist/compat/vue/index.cjs.map +1 -0
- package/dist/compat/vue/index.d.cts +3 -0
- package/dist/compat/vue/index.d.ts +3 -0
- package/dist/compat/vue/index.js +12 -0
- package/dist/compat/vue/index.js.map +1 -0
- package/dist/compat/zustand/index.cjs +4931 -0
- package/dist/compat/zustand/index.cjs.map +1 -0
- package/dist/compat/zustand/index.d.cts +5 -0
- package/dist/compat/zustand/index.d.ts +5 -0
- package/dist/compat/zustand/index.js +12 -0
- package/dist/compat/zustand/index.js.map +1 -0
- package/dist/core/index.cjs +53 -4
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +26 -24
- package/dist/demo-shell-26p5fVxn.d.cts +102 -0
- package/dist/demo-shell-DEp-nMTl.d.ts +102 -0
- package/dist/extra/index.cjs +222 -110
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +5 -4
- package/dist/extra/index.d.ts +5 -4
- package/dist/extra/index.js +6 -5
- package/dist/extra/sources.cjs +2486 -0
- package/dist/extra/sources.cjs.map +1 -0
- package/dist/extra/sources.d.cts +465 -0
- package/dist/extra/sources.d.ts +465 -0
- package/dist/extra/sources.js +57 -0
- package/dist/extra/sources.js.map +1 -0
- package/dist/graph/index.cjs +408 -14
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +13 -5
- package/dist/{graph-B6NFqv3z.d.ts → graph-6tZ5jEzr.d.cts} +195 -4
- package/dist/{graph-D-3JIQme.d.cts → graph-DQ69XU0g.d.ts} +195 -4
- package/dist/index-B4MP_8V_.d.cts +37 -0
- package/dist/index-BEfE8H_G.d.cts +121 -0
- package/dist/{index-OXImXMq6.d.ts → index-BW1z3BN9.d.ts} +18 -196
- package/dist/index-BYOHF0zP.d.ts +34 -0
- package/dist/index-B_IP40nB.d.cts +36 -0
- package/dist/index-Bd_fwmLf.d.cts +45 -0
- package/dist/{index-Ds23Wvou.d.ts → index-BeIdBfcb.d.cts} +120 -573
- package/dist/index-BjI6ty9z.d.ts +121 -0
- package/dist/index-Bxb5ZYc9.d.cts +34 -0
- package/dist/{index-BJB7t9gg.d.cts → index-C0ZXMaXO.d.cts} +2 -2
- package/dist/{index-DKE1EATr.d.cts → index-C8mdwMXc.d.cts} +18 -196
- package/dist/index-CDAjUFIv.d.ts +36 -0
- package/dist/index-CPgZ5wRl.d.ts +44 -0
- package/dist/{index-AMWewNDe.d.cts → index-CUwyr1Kk.d.cts} +33 -4
- package/dist/index-CUyrtuOf.d.cts +127 -0
- package/dist/{index-C-TXEa7C.d.ts → index-CY2TljO4.d.ts} +2 -2
- package/dist/index-CmnuOibw.d.ts +37 -0
- package/dist/{index-DiobMNwE.d.ts → index-CuYwdKO-.d.ts} +3 -3
- package/dist/index-DFhjO4Gg.d.cts +44 -0
- package/dist/{index-Ch0IpIO0.d.cts → index-DdD5MVDL.d.ts} +120 -573
- package/dist/index-DrISNAOm.d.ts +45 -0
- package/dist/index-QBpffFW-.d.cts +86 -0
- package/dist/{index-J7Kc0oIQ.d.cts → index-_oMEWlDq.d.cts} +3 -3
- package/dist/{index-CYkjxu3s.d.ts → index-eJ6T_qGM.d.ts} +33 -4
- package/dist/index-qldRdbQw.d.ts +86 -0
- package/dist/index-xdGjv0nO.d.ts +127 -0
- package/dist/index.cjs +1780 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1007 -648
- package/dist/index.d.ts +1007 -648
- package/dist/index.js +1202 -1172
- package/dist/index.js.map +1 -1
- package/dist/{meta-CnkLA_43.d.ts → meta-BGqSZ7mt.d.ts} +1 -1
- package/dist/{meta-DWbkoq1s.d.cts → meta-C0-8XW6Q.d.cts} +1 -1
- package/dist/{node-B-f-Lu-k.d.cts → node-C_IBuvX2.d.cts} +26 -1
- package/dist/{node-B-f-Lu-k.d.ts → node-C_IBuvX2.d.ts} +26 -1
- package/dist/{observable-DBnrwcar.d.cts → observable-Crr1jgzx.d.cts} +1 -1
- package/dist/{observable-uP-wy_uK.d.ts → observable-DCk45RH5.d.ts} +1 -1
- package/dist/patterns/demo-shell.cjs +5604 -0
- package/dist/patterns/demo-shell.cjs.map +1 -0
- package/dist/patterns/demo-shell.d.cts +6 -0
- package/dist/patterns/demo-shell.d.ts +6 -0
- package/dist/patterns/demo-shell.js +15 -0
- package/dist/patterns/demo-shell.js.map +1 -0
- package/dist/patterns/reactive-layout/index.cjs +355 -13
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +6 -5
- package/dist/patterns/reactive-layout/index.d.ts +6 -5
- package/dist/patterns/reactive-layout/index.js +15 -12
- package/dist/reactive-layout-BaOQefHu.d.cts +183 -0
- package/dist/reactive-layout-D9gejYXE.d.ts +183 -0
- package/dist/{storage-BuTdpCI1.d.cts → storage-BMycWEh2.d.ts} +9 -1
- package/dist/{storage-F2X1U1x0.d.ts → storage-DiqWHzVI.d.cts} +9 -1
- package/package.json +32 -2
- package/dist/chunk-5DJTTKX3.js.map +0 -1
- package/dist/chunk-IAHGTNOZ.js.map +0 -1
- package/dist/chunk-L2GLW2U7.js.map +0 -1
- package/dist/chunk-MW4VAKAO.js +0 -47
- package/dist/chunk-MW4VAKAO.js.map +0 -1
- package/dist/chunk-TKE3JGOH.js.map +0 -1
- package/dist/chunk-XOFWRC73.js.map +0 -1
- /package/dist/{chunk-H4RVA4VE.js.map → chunk-VYPWMZ6H.js.map} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DATA,
|
|
3
|
+
DIRTY,
|
|
4
|
+
RESOLVED,
|
|
5
|
+
__export
|
|
6
|
+
} from "./chunk-SX52TAR4.js";
|
|
7
|
+
|
|
8
|
+
// src/compat/react/index.ts
|
|
9
|
+
var react_exports = {};
|
|
10
|
+
__export(react_exports, {
|
|
11
|
+
useStore: () => useStore,
|
|
12
|
+
useSubscribe: () => useSubscribe,
|
|
13
|
+
useSubscribeRecord: () => useSubscribeRecord
|
|
14
|
+
});
|
|
15
|
+
import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
|
|
16
|
+
function useSubscribe(node) {
|
|
17
|
+
return useSyncExternalStore(
|
|
18
|
+
(onStoreChange) => {
|
|
19
|
+
let disposed = false;
|
|
20
|
+
const unsub = node.subscribe(() => {
|
|
21
|
+
if (!disposed) onStoreChange();
|
|
22
|
+
});
|
|
23
|
+
return () => {
|
|
24
|
+
disposed = true;
|
|
25
|
+
unsub();
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
() => node.cache,
|
|
29
|
+
() => node.cache
|
|
30
|
+
// Server snapshot
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function useStore(node) {
|
|
34
|
+
const value = useSubscribe(node);
|
|
35
|
+
const setter = useCallback(
|
|
36
|
+
(v) => {
|
|
37
|
+
node.down([[DIRTY], [DATA, v]]);
|
|
38
|
+
},
|
|
39
|
+
[node]
|
|
40
|
+
);
|
|
41
|
+
return [value, setter];
|
|
42
|
+
}
|
|
43
|
+
function useSubscribeRecord(keysNode, factory) {
|
|
44
|
+
const factoryRef = useRef(factory);
|
|
45
|
+
factoryRef.current = factory;
|
|
46
|
+
const store = useMemo(() => {
|
|
47
|
+
const computeSnap = () => {
|
|
48
|
+
const snap = {};
|
|
49
|
+
const keys = keysNode.cache ?? [];
|
|
50
|
+
for (const key of keys) {
|
|
51
|
+
const nodes = factoryRef.current(key);
|
|
52
|
+
const values = {};
|
|
53
|
+
for (const field of Object.keys(nodes)) {
|
|
54
|
+
values[field] = nodes[field].cache;
|
|
55
|
+
}
|
|
56
|
+
snap[key] = values;
|
|
57
|
+
}
|
|
58
|
+
return snap;
|
|
59
|
+
};
|
|
60
|
+
let currentSnapshot = computeSnap();
|
|
61
|
+
return {
|
|
62
|
+
subscribe: (onStoreChange) => {
|
|
63
|
+
let disposed = false;
|
|
64
|
+
let entrySubs = [];
|
|
65
|
+
const cleanupEntries = () => {
|
|
66
|
+
for (const unsub of entrySubs) unsub();
|
|
67
|
+
entrySubs = [];
|
|
68
|
+
};
|
|
69
|
+
const sync = (nextKeys) => {
|
|
70
|
+
cleanupEntries();
|
|
71
|
+
for (const key of nextKeys) {
|
|
72
|
+
const nodes = factoryRef.current(key);
|
|
73
|
+
for (const field of Object.keys(nodes)) {
|
|
74
|
+
const unsub = nodes[field].subscribe(() => {
|
|
75
|
+
currentSnapshot = computeSnap();
|
|
76
|
+
if (!disposed) onStoreChange();
|
|
77
|
+
});
|
|
78
|
+
entrySubs.push(unsub);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
currentSnapshot = computeSnap();
|
|
82
|
+
if (!disposed) onStoreChange();
|
|
83
|
+
};
|
|
84
|
+
const keysUnsub = keysNode.subscribe((msgs) => {
|
|
85
|
+
const hasSettled = msgs.some((m) => m[0] === DATA || m[0] === RESOLVED);
|
|
86
|
+
if (!disposed && hasSettled) sync(keysNode.cache ?? []);
|
|
87
|
+
});
|
|
88
|
+
sync(keysNode.cache ?? []);
|
|
89
|
+
return () => {
|
|
90
|
+
disposed = true;
|
|
91
|
+
keysUnsub();
|
|
92
|
+
cleanupEntries();
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
getSnapshot: () => currentSnapshot
|
|
96
|
+
};
|
|
97
|
+
}, [keysNode]);
|
|
98
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
useSubscribe,
|
|
103
|
+
useStore,
|
|
104
|
+
useSubscribeRecord,
|
|
105
|
+
react_exports
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=chunk-J22W6HV3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/compat/react/index.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// React bindings — useStore / useSubscribe\n// ---------------------------------------------------------------------------\n// Bridges GraphReFly nodes into React via useSyncExternalStore.\n// Works with any Node<T>, including companion nodes (node.meta.status).\n//\n// Usage:\n// import { useStore, useSubscribe } from '@graphrefly/graphrefly-ts/compat/react';\n// // Optional peer install (only for this adapter): pnpm add react react-dom\n// const value = useSubscribe(myNode); // T | undefined (read-only)\n// const [count, setCount] = useStore(counter); // [T | undefined, setter]\n// ---------------------------------------------------------------------------\n\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport { DATA, DIRTY, type Messages, RESOLVED } from \"../../core/messages.js\";\nimport type { Node } from \"../../core/node.js\";\n\n/**\n * Subscribe to a read-only `Node<T>` as a React value. Re-renders on node value settlement.\n * Subscription lifecycle is tied to React mount/unmount (not node terminal messages).\n *\n * @param node - Any `Node<T>`.\n * @returns `T | undefined` — the current node value, kept in sync via `useSyncExternalStore`.\n */\nexport function useSubscribe<T>(node: Node<T>): T | undefined | null {\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => {\n\t\t\tlet disposed = false;\n\t\t\tconst unsub = node.subscribe(() => {\n\t\t\t\tif (!disposed) onStoreChange();\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tdisposed = true;\n\t\t\t\tunsub();\n\t\t\t};\n\t\t},\n\t\t() => node.cache,\n\t\t() => node.cache, // Server snapshot\n\t);\n}\n\n/**\n * Bind a writable `Node<T>` as a React `[value, setter]` tuple.\n * Setting the value always pushes `[[DIRTY], [DATA, value]]`, including `value === undefined`.\n * Subscription lifecycle is tied to React mount/unmount (not node terminal messages).\n *\n * @param node - A `Node<T>` (e.g. state node).\n * @returns `[T | undefined, (value: T) => void]` — current value and setter function.\n */\nexport function useStore<T>(node: Node<T>): [T | undefined | null, (value: T) => void] {\n\tconst value = useSubscribe(node);\n\tconst setter = useCallback(\n\t\t(v: T) => {\n\t\t\tnode.down([[DIRTY], [DATA, v]]);\n\t\t},\n\t\t[node],\n\t);\n\treturn [value, setter];\n}\n\n/** Maps a key to an object of nodes. Used by `useSubscribeRecord`. */\nexport type NodeFactory<K, R extends Record<string, any>> = (key: K) => {\n\t[P in keyof R]: Node<R[P]>;\n};\n\n/**\n * Subscribe to a dynamic set of keyed node records.\n * Re-subscribes all per-key fields whenever `keysNode` changes.\n * Key re-sync is gated to settled batches (`messageTier >= 3`) to avoid DIRTY-phase churn.\n * Guaranteed to clean up strictly with React hook lifecycle, utilizing no global mappings.\n *\n * @param keysNode - Node of current keys (e.g. node IDs)\n * @param factory - Function returning `{ [field]: Node<V> }` for each key.\n * @returns `Record<K, R>` — snapshot of resolved values for all keys.\n */\nexport function useSubscribeRecord<K extends string, R extends Record<string, any>>(\n\tkeysNode: Node<K[]>,\n\tfactory: NodeFactory<K, R>,\n): Record<K, R> {\n\tconst factoryRef = useRef(factory);\n\tfactoryRef.current = factory;\n\n\tconst store = useMemo(() => {\n\t\tconst computeSnap = () => {\n\t\t\tconst snap = {} as Record<K, R>;\n\t\t\tconst keys = keysNode.cache ?? [];\n\t\t\tfor (const key of keys) {\n\t\t\t\tconst nodes = factoryRef.current(key);\n\t\t\t\tconst values = {} as R;\n\t\t\t\tfor (const field of Object.keys(nodes) as (keyof R)[]) {\n\t\t\t\t\tvalues[field] = nodes[field].cache as R[keyof R];\n\t\t\t\t}\n\t\t\t\tsnap[key] = values;\n\t\t\t}\n\t\t\treturn snap;\n\t\t};\n\n\t\tlet currentSnapshot = computeSnap();\n\n\t\treturn {\n\t\t\tsubscribe: (onStoreChange: () => void) => {\n\t\t\t\tlet disposed = false;\n\t\t\t\tlet entrySubs: Array<() => void> = [];\n\n\t\t\t\tconst cleanupEntries = () => {\n\t\t\t\t\tfor (const unsub of entrySubs) unsub();\n\t\t\t\t\tentrySubs = [];\n\t\t\t\t};\n\n\t\t\t\tconst sync = (nextKeys: K[]) => {\n\t\t\t\t\tcleanupEntries();\n\t\t\t\t\tfor (const key of nextKeys) {\n\t\t\t\t\t\tconst nodes = factoryRef.current(key);\n\t\t\t\t\t\tfor (const field of Object.keys(nodes) as (keyof R)[]) {\n\t\t\t\t\t\t\tconst unsub = nodes[field].subscribe(() => {\n\t\t\t\t\t\t\t\tcurrentSnapshot = computeSnap();\n\t\t\t\t\t\t\t\tif (!disposed) onStoreChange();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tentrySubs.push(unsub);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcurrentSnapshot = computeSnap();\n\t\t\t\t\tif (!disposed) onStoreChange();\n\t\t\t\t};\n\n\t\t\t\tconst keysUnsub = keysNode.subscribe((msgs: Messages) => {\n\t\t\t\t\tconst hasSettled = msgs.some((m) => m[0] === DATA || m[0] === RESOLVED);\n\t\t\t\t\tif (!disposed && hasSettled) sync(keysNode.cache ?? []);\n\t\t\t\t});\n\t\t\t\tsync(keysNode.cache ?? []);\n\n\t\t\t\treturn () => {\n\t\t\t\t\tdisposed = true;\n\t\t\t\t\tkeysUnsub();\n\t\t\t\t\tcleanupEntries();\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetSnapshot: () => currentSnapshot,\n\t\t};\n\t}, [keysNode]);\n\n\treturn useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n}\n"],"mappings":";;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,SAAS,aAAa,SAAS,QAAQ,4BAA4B;AAW5D,SAAS,aAAgB,MAAqC;AACpE,SAAO;AAAA,IACN,CAAC,kBAAkB;AAClB,UAAI,WAAW;AACf,YAAM,QAAQ,KAAK,UAAU,MAAM;AAClC,YAAI,CAAC,SAAU,eAAc;AAAA,MAC9B,CAAC;AACD,aAAO,MAAM;AACZ,mBAAW;AACX,cAAM;AAAA,MACP;AAAA,IACD;AAAA,IACA,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA;AAAA,EACZ;AACD;AAUO,SAAS,SAAY,MAA2D;AACtF,QAAM,QAAQ,aAAa,IAAI;AAC/B,QAAM,SAAS;AAAA,IACd,CAAC,MAAS;AACT,WAAK,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAAA,IAC/B;AAAA,IACA,CAAC,IAAI;AAAA,EACN;AACA,SAAO,CAAC,OAAO,MAAM;AACtB;AAiBO,SAAS,mBACf,UACA,SACe;AACf,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,QAAQ,QAAQ,MAAM;AAC3B,UAAM,cAAc,MAAM;AACzB,YAAM,OAAO,CAAC;AACd,YAAM,OAAO,SAAS,SAAS,CAAC;AAChC,iBAAW,OAAO,MAAM;AACvB,cAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,cAAM,SAAS,CAAC;AAChB,mBAAW,SAAS,OAAO,KAAK,KAAK,GAAkB;AACtD,iBAAO,KAAK,IAAI,MAAM,KAAK,EAAE;AAAA,QAC9B;AACA,aAAK,GAAG,IAAI;AAAA,MACb;AACA,aAAO;AAAA,IACR;AAEA,QAAI,kBAAkB,YAAY;AAElC,WAAO;AAAA,MACN,WAAW,CAAC,kBAA8B;AACzC,YAAI,WAAW;AACf,YAAI,YAA+B,CAAC;AAEpC,cAAM,iBAAiB,MAAM;AAC5B,qBAAW,SAAS,UAAW,OAAM;AACrC,sBAAY,CAAC;AAAA,QACd;AAEA,cAAM,OAAO,CAAC,aAAkB;AAC/B,yBAAe;AACf,qBAAW,OAAO,UAAU;AAC3B,kBAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,uBAAW,SAAS,OAAO,KAAK,KAAK,GAAkB;AACtD,oBAAM,QAAQ,MAAM,KAAK,EAAE,UAAU,MAAM;AAC1C,kCAAkB,YAAY;AAC9B,oBAAI,CAAC,SAAU,eAAc;AAAA,cAC9B,CAAC;AACD,wBAAU,KAAK,KAAK;AAAA,YACrB;AAAA,UACD;AACA,4BAAkB,YAAY;AAC9B,cAAI,CAAC,SAAU,eAAc;AAAA,QAC9B;AAEA,cAAM,YAAY,SAAS,UAAU,CAAC,SAAmB;AACxD,gBAAM,aAAa,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,QAAQ,EAAE,CAAC,MAAM,QAAQ;AACtE,cAAI,CAAC,YAAY,WAAY,MAAK,SAAS,SAAS,CAAC,CAAC;AAAA,QACvD,CAAC;AACD,aAAK,SAAS,SAAS,CAAC,CAAC;AAEzB,eAAO,MAAM;AACZ,qBAAW;AACX,oBAAU;AACV,yBAAe;AAAA,QAChB;AAAA,MACD;AAAA,MACA,aAAa,MAAM;AAAA,IACpB;AAAA,EACD,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO,qBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AAClF;","names":[]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DATA,
|
|
3
|
-
DIRTY,
|
|
4
2
|
defaultConfig,
|
|
5
3
|
downWithBatch
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PHOUUNK7.js";
|
|
5
|
+
import {
|
|
6
|
+
DATA,
|
|
7
|
+
DIRTY
|
|
8
|
+
} from "./chunk-SX52TAR4.js";
|
|
7
9
|
|
|
8
10
|
// src/patterns/_internal.ts
|
|
9
11
|
function emitToMeta(metaNode, value) {
|
|
@@ -33,4 +35,4 @@ export {
|
|
|
33
35
|
domainMeta,
|
|
34
36
|
trackingKey
|
|
35
37
|
};
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
38
|
+
//# sourceMappingURL=chunk-JSCT3CR4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/patterns/_internal.ts"],"sourcesContent":["/**\n * Shared internal utilities for the patterns layer.\n *\n * These are private helpers used across multiple pattern modules. They are NOT\n * part of the public API — import from `./patterns/index.js` for public exports.\n *\n * General-purpose reactive utilities (`keepalive`, `reactiveCounter`) live in\n * `extra/sources.ts` and are re-exported here for convenience.\n *\n * @internal\n * @module\n */\n\nimport { downWithBatch } from \"../core/batch.js\";\nimport { DATA, DIRTY } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { defaultConfig } from \"../core/node.js\";\n\n// Re-export general-purpose utilities from extra (canonical home).\nexport { keepalive, reactiveCounter } from \"../extra/sources.js\";\n\n// ---------------------------------------------------------------------------\n// emitToMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Forward a single `[DATA, value]` to a meta companion node via tier-3\n * deferral, tolerating absent companions. Used by patterns that publish\n * per-wave statistics alongside their main output (cache-hit-rate,\n * segment-count, layout-time-ns, etc.) — subscribers see the parent's\n * DATA first because phase-2 completes before phase-3 during drain.\n *\n * // Expands to: `if (meta) downWithBatch(meta, [[Type, value]])` with null-guard.\n *\n * @internal\n */\nexport function emitToMeta<T>(metaNode: Node<T> | undefined, value: T): void {\n\tif (metaNode == null) return;\n\tdownWithBatch((msgs) => metaNode.down(msgs), [[DATA, value]], defaultConfig.tierOf);\n}\n\n// ---------------------------------------------------------------------------\n// tryIncrementBounded\n// ---------------------------------------------------------------------------\n\n/**\n * Bounded increment for a self-owned counter state node.\n *\n * Reads `counter.cache`, bumps by 1 if under `cap`, writes back. Returns\n * `false` when the cap is reached. Documented P3 exception: the counter is\n * not a declared dep of the caller — it's a private budget read+written from\n * a single call site. This helper keeps the `.cache` access in one named\n * place.\n *\n * **Safety today:**\n * 1. Single-threaded JS runner never invokes the caller concurrently.\n * 2. `counter.down` writes the cache synchronously before returning, so\n * synchronous re-entry through a downstream publish reads the\n * freshly-incremented value — no double-count.\n *\n * **Future risk:** under a free-threaded runner (PY no-GIL or hypothetical\n * concurrent TS runner), two concurrent firings could still race. Revisit\n * when that surfaces.\n *\n * @internal\n */\nexport function tryIncrementBounded(counter: Node<number>, cap: number): boolean {\n\tconst cur = (counter.cache as number | undefined) ?? 0;\n\tif (cur >= cap) return false;\n\tcounter.down([[DIRTY], [DATA, cur + 1]]);\n\treturn true;\n}\n\n// ---------------------------------------------------------------------------\n// domainMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Build a domain metadata object for pattern-layer nodes.\n *\n * Each domain (orchestration, messaging, reduction, ai, cqrs, domain_template)\n * follows the same shape: `{ [domain]: true, [domain]_type: kind, ...extra }`.\n *\n * @param domain - The domain tag (e.g. `\"orchestration\"`, `\"ai\"`, `\"cqrs\"`).\n * @param kind - The specific type within the domain (e.g. `\"gate\"`, `\"prompt\"`).\n * @param extra - Additional metadata to merge.\n * @returns Metadata object.\n *\n * @internal\n */\nexport function domainMeta(\n\tdomain: string,\n\tkind: string,\n\textra?: Record<string, unknown>,\n): Record<string, unknown> {\n\treturn {\n\t\t[domain]: true,\n\t\t[`${domain}_type`]: kind,\n\t\t...(extra ?? {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// trackingKey\n// ---------------------------------------------------------------------------\n\n/**\n * Stable tracking key for an item with retry/reingestion decoration.\n *\n * Uses `relatedTo[0]` if present (carries the original key forward through\n * retries and reingestions). Falls back to `summary` for first-time items.\n *\n * This avoids deriving keys from mutated summary strings — retries decorate\n * the summary with `[RETRY N/M]` and failure context, so regex-stripping\n * would be fragile and any new decoration pattern would risk infinite loops\n * by generating novel keys.\n *\n * @internal\n */\nexport function trackingKey(item: { summary: string; relatedTo?: string[] }): string {\n\treturn item.relatedTo?.[0] ?? item.summary;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/patterns/_internal.ts"],"sourcesContent":["/**\n * Shared internal utilities for the patterns layer.\n *\n * These are private helpers used across multiple pattern modules. They are NOT\n * part of the public API — import from `./patterns/index.js` for public exports.\n *\n * General-purpose reactive utilities (`keepalive`, `reactiveCounter`) live in\n * `extra/sources.ts` and are re-exported here for convenience.\n *\n * @internal\n * @module\n */\n\nimport { downWithBatch } from \"../core/batch.js\";\nimport { DATA, DIRTY } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { defaultConfig } from \"../core/node.js\";\n\n// Re-export general-purpose utilities from extra (canonical home).\nexport { keepalive, reactiveCounter } from \"../extra/sources.js\";\n\n// ---------------------------------------------------------------------------\n// emitToMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Forward a single `[DATA, value]` to a meta companion node via tier-3\n * deferral, tolerating absent companions. Used by patterns that publish\n * per-wave statistics alongside their main output (cache-hit-rate,\n * segment-count, layout-time-ns, etc.) — subscribers see the parent's\n * DATA first because phase-2 completes before phase-3 during drain.\n *\n * // Expands to: `if (meta) downWithBatch(meta, [[Type, value]])` with null-guard.\n *\n * @internal\n */\nexport function emitToMeta<T>(metaNode: Node<T> | undefined, value: T): void {\n\tif (metaNode == null) return;\n\tdownWithBatch((msgs) => metaNode.down(msgs), [[DATA, value]], defaultConfig.tierOf);\n}\n\n// ---------------------------------------------------------------------------\n// tryIncrementBounded\n// ---------------------------------------------------------------------------\n\n/**\n * Bounded increment for a self-owned counter state node.\n *\n * Reads `counter.cache`, bumps by 1 if under `cap`, writes back. Returns\n * `false` when the cap is reached. Documented P3 exception: the counter is\n * not a declared dep of the caller — it's a private budget read+written from\n * a single call site. This helper keeps the `.cache` access in one named\n * place.\n *\n * **Safety today:**\n * 1. Single-threaded JS runner never invokes the caller concurrently.\n * 2. `counter.down` writes the cache synchronously before returning, so\n * synchronous re-entry through a downstream publish reads the\n * freshly-incremented value — no double-count.\n *\n * **Future risk:** under a free-threaded runner (PY no-GIL or hypothetical\n * concurrent TS runner), two concurrent firings could still race. Revisit\n * when that surfaces.\n *\n * @internal\n */\nexport function tryIncrementBounded(counter: Node<number>, cap: number): boolean {\n\tconst cur = (counter.cache as number | undefined) ?? 0;\n\tif (cur >= cap) return false;\n\tcounter.down([[DIRTY], [DATA, cur + 1]]);\n\treturn true;\n}\n\n// ---------------------------------------------------------------------------\n// domainMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Build a domain metadata object for pattern-layer nodes.\n *\n * Each domain (orchestration, messaging, reduction, ai, cqrs, domain_template)\n * follows the same shape: `{ [domain]: true, [domain]_type: kind, ...extra }`.\n *\n * @param domain - The domain tag (e.g. `\"orchestration\"`, `\"ai\"`, `\"cqrs\"`).\n * @param kind - The specific type within the domain (e.g. `\"gate\"`, `\"prompt\"`).\n * @param extra - Additional metadata to merge.\n * @returns Metadata object.\n *\n * @internal\n */\nexport function domainMeta(\n\tdomain: string,\n\tkind: string,\n\textra?: Record<string, unknown>,\n): Record<string, unknown> {\n\treturn {\n\t\t[domain]: true,\n\t\t[`${domain}_type`]: kind,\n\t\t...(extra ?? {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// trackingKey\n// ---------------------------------------------------------------------------\n\n/**\n * Stable tracking key for an item with retry/reingestion decoration.\n *\n * Uses `relatedTo[0]` if present (carries the original key forward through\n * retries and reingestions). Falls back to `summary` for first-time items.\n *\n * This avoids deriving keys from mutated summary strings — retries decorate\n * the summary with `[RETRY N/M]` and failure context, so regex-stripping\n * would be fragile and any new decoration pattern would risk infinite loops\n * by generating novel keys.\n *\n * @internal\n */\nexport function trackingKey(item: { summary: string; relatedTo?: string[] }): string {\n\treturn item.relatedTo?.[0] ?? item.summary;\n}\n"],"mappings":";;;;;;;;;;AAoCO,SAAS,WAAc,UAA+B,OAAgB;AAC5E,MAAI,YAAY,KAAM;AACtB,gBAAc,CAAC,SAAS,SAAS,KAAK,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,cAAc,MAAM;AACnF;AA2BO,SAAS,oBAAoB,SAAuB,KAAsB;AAChF,QAAM,MAAO,QAAQ,SAAgC;AACrD,MAAI,OAAO,IAAK,QAAO;AACvB,UAAQ,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC;AACvC,SAAO;AACR;AAmBO,SAAS,WACf,QACA,MACA,OAC0B;AAC1B,SAAO;AAAA,IACN,CAAC,MAAM,GAAG;AAAA,IACV,CAAC,GAAG,MAAM,OAAO,GAAG;AAAA,IACpB,GAAI,SAAS,CAAC;AAAA,EACf;AACD;AAmBO,SAAS,YAAY,MAAyD;AACpF,SAAO,KAAK,YAAY,CAAC,KAAK,KAAK;AACpC;","names":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Graph
|
|
3
|
+
} from "./chunk-THTWHNU4.js";
|
|
4
|
+
import {
|
|
5
|
+
state
|
|
6
|
+
} from "./chunk-PHOUUNK7.js";
|
|
7
|
+
import {
|
|
8
|
+
DATA,
|
|
9
|
+
__export
|
|
10
|
+
} from "./chunk-SX52TAR4.js";
|
|
11
|
+
|
|
12
|
+
// src/compat/zustand/index.ts
|
|
13
|
+
var zustand_exports = {};
|
|
14
|
+
__export(zustand_exports, {
|
|
15
|
+
create: () => create
|
|
16
|
+
});
|
|
17
|
+
var alwaysDiffer = () => false;
|
|
18
|
+
function create(initializer) {
|
|
19
|
+
const g = new Graph("zustand");
|
|
20
|
+
const s = state(void 0, {
|
|
21
|
+
name: "state",
|
|
22
|
+
equals: alwaysDiffer
|
|
23
|
+
});
|
|
24
|
+
g.add("state", s);
|
|
25
|
+
const getState = () => s.cache;
|
|
26
|
+
const setState = (partial, replace) => {
|
|
27
|
+
const prev = s.cache;
|
|
28
|
+
const next = typeof partial === "function" ? partial(prev) : partial;
|
|
29
|
+
s.emit(replace ? next : { ...prev, ...next });
|
|
30
|
+
};
|
|
31
|
+
const api = {
|
|
32
|
+
getState,
|
|
33
|
+
setState,
|
|
34
|
+
getInitialState: () => initialValue,
|
|
35
|
+
subscribe: (listener) => {
|
|
36
|
+
let initial = true;
|
|
37
|
+
let prev = s.cache;
|
|
38
|
+
return s.subscribe((msgs) => {
|
|
39
|
+
for (const [t, v] of msgs) {
|
|
40
|
+
if (t === DATA) {
|
|
41
|
+
if (initial) {
|
|
42
|
+
initial = false;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
listener(v, prev);
|
|
46
|
+
prev = v;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
destroy: g.destroy.bind(g)
|
|
52
|
+
};
|
|
53
|
+
const initialValue = initializer(setState, getState, api);
|
|
54
|
+
s.emit(initialValue);
|
|
55
|
+
return Object.assign(g, api);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
create,
|
|
60
|
+
zustand_exports
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=chunk-JYXEWPH4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/compat/zustand/index.ts"],"sourcesContent":["import { DATA } from \"../../core/messages.js\";\nimport { state as stateNode } from \"../../core/sugar.js\";\nimport { Graph } from \"../../graph/graph.js\";\n\n// Zustand fires listeners on every setState, regardless of reference\n// equality. Configure the state node with a permissive equals so every\n// emit produces DATA (not RESOLVED). Diamond coordination still works\n// because `n.emit` routes through the framed pipeline which auto-\n// prefixes `[DIRTY]`.\nconst alwaysDiffer = () => false;\n\n/** Zustand-compatible Store API. */\nexport interface StoreApi<T> {\n\tgetState: () => T;\n\tsetState: (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean) => void;\n\tgetInitialState: () => T;\n\tsubscribe: (listener: (state: T, prevState: T) => void) => () => void;\n\tdestroy: () => void;\n}\n\n/** Function type for initializing the store. */\nexport type StateCreator<T> = (\n\tset: StoreApi<T>[\"setState\"],\n\tget: StoreApi<T>[\"getState\"],\n\tapi: StoreApi<T>,\n) => T;\n\n/**\n * Creates a Zustand-compatible store backed by a GraphReFly state node.\n * returns an object that is both a Graph and a StoreApi.\n *\n * @example\n * ```ts\n * const store = create((set) => ({\n * count: 0,\n * inc: () => set((s) => ({ count: s.count + 1 }))\n * }));\n * store.getState().inc();\n * ```\n *\n * @category compat\n */\nexport function create<T extends object>(initializer: StateCreator<T>): Graph & StoreApi<T> {\n\tconst g = new Graph(\"zustand\");\n\tconst s = stateNode<T>(undefined as unknown as T, {\n\t\tname: \"state\",\n\t\tequals: alwaysDiffer,\n\t});\n\tg.add(\"state\", s);\n\n\t// `getState` and `setState` read/write through `s` directly — the single\n\t// source of truth. `s.cache` is `undefined` (SENTINEL) until `emit()` is\n\t// called, but action closures (e.g. `inc: () => set(...)`) are only ever\n\t// invoked after initialization, so `s.cache` is valid by that time.\n\tconst getState = () => s.cache as T;\n\tconst setState = (partial: any, replace?: boolean): void => {\n\t\tconst prev = s.cache as T;\n\t\tconst next = typeof partial === \"function\" ? partial(prev) : partial;\n\t\t// `n.emit` goes through `_actionEmit` → `bundle()`, which auto-\n\t\t// prefixes `[DIRTY]` so diamond legs coordinate under downstream\n\t\t// composition. The `alwaysDiffer` equals keeps zustand's \"fire\n\t\t// on every setState\" semantics.\n\t\ts.emit(replace ? next : { ...prev, ...next });\n\t};\n\n\tconst api: StoreApi<T> = {\n\t\tgetState,\n\t\tsetState,\n\t\tgetInitialState: () => initialValue,\n\t\tsubscribe: (listener) => {\n\t\t\t// Skip the initial push-on-subscribe DATA — zustand subscribe fires on changes only.\n\t\t\tlet initial = true;\n\t\t\tlet prev = s.cache as T;\n\t\t\treturn s.subscribe((msgs) => {\n\t\t\t\tfor (const [t, v] of msgs) {\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\tif (initial) {\n\t\t\t\t\t\t\tinitial = false;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlistener(v as T, prev);\n\t\t\t\t\t\tprev = v as T;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tdestroy: g.destroy.bind(g),\n\t};\n\n\tconst initialValue = initializer(setState, getState, api);\n\ts.emit(initialValue);\n\n\treturn Object.assign(g, api);\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AASA,IAAM,eAAe,MAAM;AAiCpB,SAAS,OAAyB,aAAmD;AAC3F,QAAM,IAAI,IAAI,MAAM,SAAS;AAC7B,QAAM,IAAI,MAAa,QAA2B;AAAA,IACjD,MAAM;AAAA,IACN,QAAQ;AAAA,EACT,CAAC;AACD,IAAE,IAAI,SAAS,CAAC;AAMhB,QAAM,WAAW,MAAM,EAAE;AACzB,QAAM,WAAW,CAAC,SAAc,YAA4B;AAC3D,UAAM,OAAO,EAAE;AACf,UAAM,OAAO,OAAO,YAAY,aAAa,QAAQ,IAAI,IAAI;AAK7D,MAAE,KAAK,UAAU,OAAO,EAAE,GAAG,MAAM,GAAG,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,MAAmB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,iBAAiB,MAAM;AAAA,IACvB,WAAW,CAAC,aAAa;AAExB,UAAI,UAAU;AACd,UAAI,OAAO,EAAE;AACb,aAAO,EAAE,UAAU,CAAC,SAAS;AAC5B,mBAAW,CAAC,GAAG,CAAC,KAAK,MAAM;AAC1B,cAAI,MAAM,MAAM;AACf,gBAAI,SAAS;AACZ,wBAAU;AACV;AAAA,YACD;AACA,qBAAS,GAAQ,IAAI;AACrB,mBAAO;AAAA,UACR;AAAA,QACD;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,SAAS,EAAE,QAAQ,KAAK,CAAC;AAAA,EAC1B;AAEA,QAAM,eAAe,YAAY,UAAU,UAAU,GAAG;AACxD,IAAE,KAAK,YAAY;AAEnB,SAAO,OAAO,OAAO,GAAG,GAAG;AAC5B;","names":[]}
|