@graphrefly/graphrefly 0.9.0 → 0.11.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 (69) hide show
  1. package/dist/{chunk-WYI7YW54.js → chunk-2OTXEZQO.js} +3 -3
  2. package/dist/{chunk-TZLX4KIT.js → chunk-2VHNCFGG.js} +3 -3
  3. package/dist/{chunk-XCZPGOVP.js → chunk-3WACHRHV.js} +3 -3
  4. package/dist/{chunk-YWTP2XRJ.js → chunk-5WXTWOD7.js} +2 -2
  5. package/dist/{chunk-E7OH6ZAZ.js → chunk-FMVFRP7L.js} +62 -3
  6. package/dist/chunk-FMVFRP7L.js.map +1 -0
  7. package/dist/{chunk-LR2CLSEF.js → chunk-OHUECHWY.js} +2 -3
  8. package/dist/chunk-OHUECHWY.js.map +1 -0
  9. package/dist/{chunk-UCW3VWMN.js → chunk-PZCDQD2U.js} +4 -4
  10. package/dist/{chunk-A2AJJOSJ.js → chunk-U5HFZGAQ.js} +3 -3
  11. package/dist/{chunk-QTZSBQGJ.js → chunk-UG2QZMRN.js} +18 -1
  12. package/dist/chunk-UG2QZMRN.js.map +1 -0
  13. package/dist/compat/nestjs/index.cjs +10 -1
  14. package/dist/compat/nestjs/index.cjs.map +1 -1
  15. package/dist/compat/nestjs/index.d.cts +4 -4
  16. package/dist/compat/nestjs/index.d.ts +4 -4
  17. package/dist/compat/nestjs/index.js +7 -7
  18. package/dist/core/index.cjs +74 -1
  19. package/dist/core/index.cjs.map +1 -1
  20. package/dist/core/index.d.cts +2 -2
  21. package/dist/core/index.d.ts +2 -2
  22. package/dist/core/index.js +12 -3
  23. package/dist/extra/index.cjs +10 -0
  24. package/dist/extra/index.cjs.map +1 -1
  25. package/dist/extra/index.d.cts +4 -4
  26. package/dist/extra/index.d.ts +4 -4
  27. package/dist/extra/index.js +3 -3
  28. package/dist/graph/index.cjs +10 -1
  29. package/dist/graph/index.cjs.map +1 -1
  30. package/dist/graph/index.d.cts +3 -3
  31. package/dist/graph/index.d.ts +3 -3
  32. package/dist/graph/index.js +4 -4
  33. package/dist/{graph-DqTICAY2.d.cts → graph-BE10ujU9.d.cts} +1 -1
  34. package/dist/{graph-X9uwnD_z.d.ts → graph-DXT95WZ3.d.ts} +1 -1
  35. package/dist/{index-DLO8wnYU.d.ts → index-53cDGX7F.d.ts} +3 -3
  36. package/dist/{index-DMv1Etbi.d.ts → index-B10Q0sQB.d.ts} +2 -2
  37. package/dist/{index-a5gHmH5b.d.ts → index-Bbgvinsi.d.ts} +3 -3
  38. package/dist/{index-BPCeYDS4.d.ts → index-C0_7g9sj.d.ts} +1 -1
  39. package/dist/{index-3U0WxdD-.d.cts → index-CCvzN5GB.d.cts} +2 -2
  40. package/dist/{index-BP1t_38S.d.cts → index-DpZozxaJ.d.cts} +3 -3
  41. package/dist/{index-BVG5pjin.d.ts → index-Dzdm20sx.d.ts} +88 -3
  42. package/dist/{index-BYEgosAX.d.cts → index-QfbXNW1N.d.cts} +88 -3
  43. package/dist/{index-BYa2YMat.d.cts → index-aBZ2RoP0.d.cts} +3 -3
  44. package/dist/{index-DbwgQ4Cw.d.cts → index-nRulwTr-.d.cts} +1 -1
  45. package/dist/index.cjs +2009 -406
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +559 -14
  48. package/dist/index.d.ts +559 -14
  49. package/dist/index.js +1938 -406
  50. package/dist/index.js.map +1 -1
  51. package/dist/{meta-BJEU8fYz.d.cts → meta-BcuDhtwu.d.cts} +33 -1
  52. package/dist/{meta-BJEU8fYz.d.ts → meta-BcuDhtwu.d.ts} +33 -1
  53. package/dist/patterns/reactive-layout/index.cjs +10 -1
  54. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  55. package/dist/patterns/reactive-layout/index.d.cts +3 -3
  56. package/dist/patterns/reactive-layout/index.d.ts +3 -3
  57. package/dist/patterns/reactive-layout/index.js +4 -4
  58. package/dist/{reactive-log-RhgIog2Z.d.ts → reactive-log-Cu0VdqkT.d.ts} +2 -2
  59. package/dist/{reactive-log-BfX6bOSZ.d.cts → reactive-log-OULQssZg.d.cts} +2 -2
  60. package/package.json +7 -2
  61. package/dist/chunk-E7OH6ZAZ.js.map +0 -1
  62. package/dist/chunk-LR2CLSEF.js.map +0 -1
  63. package/dist/chunk-QTZSBQGJ.js.map +0 -1
  64. /package/dist/{chunk-WYI7YW54.js.map → chunk-2OTXEZQO.js.map} +0 -0
  65. /package/dist/{chunk-TZLX4KIT.js.map → chunk-2VHNCFGG.js.map} +0 -0
  66. /package/dist/{chunk-XCZPGOVP.js.map → chunk-3WACHRHV.js.map} +0 -0
  67. /package/dist/{chunk-YWTP2XRJ.js.map → chunk-5WXTWOD7.js.map} +0 -0
  68. /package/dist/{chunk-UCW3VWMN.js.map → chunk-PZCDQD2U.js.map} +0 -0
  69. /package/dist/{chunk-A2AJJOSJ.js.map → chunk-U5HFZGAQ.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeNode,
3
3
  resolveDescribeFields
4
- } from "./chunk-LR2CLSEF.js";
4
+ } from "./chunk-OHUECHWY.js";
5
5
  import {
6
6
  COMPLETE,
7
7
  DATA,
@@ -16,7 +16,7 @@ import {
16
16
  messageTier,
17
17
  monotonicNs,
18
18
  state
19
- } from "./chunk-QTZSBQGJ.js";
19
+ } from "./chunk-UG2QZMRN.js";
20
20
 
21
21
  // src/graph/graph.ts
22
22
  var PATH_SEP = "::";
@@ -1902,4 +1902,4 @@ export {
1902
1902
  Graph,
1903
1903
  reachable
1904
1904
  };
1905
- //# sourceMappingURL=chunk-WYI7YW54.js.map
1905
+ //# sourceMappingURL=chunk-2OTXEZQO.js.map
@@ -32,7 +32,7 @@ import {
32
32
  toArray,
33
33
  toMessages$,
34
34
  toObservable
35
- } from "./chunk-YWTP2XRJ.js";
35
+ } from "./chunk-5WXTWOD7.js";
36
36
  import {
37
37
  ResettableTimer
38
38
  } from "./chunk-WZ2Z2CRV.js";
@@ -59,7 +59,7 @@ import {
59
59
  producer,
60
60
  state,
61
61
  wallClockNs
62
- } from "./chunk-QTZSBQGJ.js";
62
+ } from "./chunk-UG2QZMRN.js";
63
63
 
64
64
  // src/extra/index.ts
65
65
  var extra_exports = {};
@@ -6265,4 +6265,4 @@ export {
6265
6265
  workerSelf,
6266
6266
  extra_exports
6267
6267
  };
6268
- //# sourceMappingURL=chunk-TZLX4KIT.js.map
6268
+ //# sourceMappingURL=chunk-2VHNCFGG.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Graph
3
- } from "./chunk-WYI7YW54.js";
3
+ } from "./chunk-2OTXEZQO.js";
4
4
  import {
5
5
  DATA,
6
6
  INVALIDATE,
@@ -10,7 +10,7 @@ import {
10
10
  emitWithBatch,
11
11
  monotonicNs,
12
12
  state
13
- } from "./chunk-QTZSBQGJ.js";
13
+ } from "./chunk-UG2QZMRN.js";
14
14
 
15
15
  // src/patterns/reactive-layout/index.ts
16
16
  var reactive_layout_exports = {};
@@ -1094,4 +1094,4 @@ export {
1094
1094
  reactiveBlockLayout,
1095
1095
  reactive_layout_exports
1096
1096
  };
1097
- //# sourceMappingURL=chunk-XCZPGOVP.js.map
1097
+ //# sourceMappingURL=chunk-3WACHRHV.js.map
@@ -11,7 +11,7 @@ import {
11
11
  producer,
12
12
  state,
13
13
  wallClockNs
14
- } from "./chunk-QTZSBQGJ.js";
14
+ } from "./chunk-UG2QZMRN.js";
15
15
 
16
16
  // src/extra/observable.ts
17
17
  import { Observable } from "rxjs";
@@ -778,4 +778,4 @@ export {
778
778
  reactiveLog,
779
779
  logSlice
780
780
  };
781
- //# sourceMappingURL=chunk-YWTP2XRJ.js.map
781
+ //# sourceMappingURL=chunk-5WXTWOD7.js.map
@@ -5,8 +5,9 @@ import {
5
5
  describeNode,
6
6
  metaSnapshot,
7
7
  resolveDescribeFields
8
- } from "./chunk-LR2CLSEF.js";
8
+ } from "./chunk-OHUECHWY.js";
9
9
  import {
10
+ CLEANUP_RESULT,
10
11
  COMPLETE,
11
12
  DATA,
12
13
  DEFAULT_ACTOR,
@@ -23,6 +24,7 @@ import {
23
24
  accessHintForGuard,
24
25
  advanceVersion,
25
26
  batch,
27
+ cleanupResult,
26
28
  createVersioning,
27
29
  defaultHash,
28
30
  derived,
@@ -47,14 +49,16 @@ import {
47
49
  propagatesToMeta,
48
50
  state,
49
51
  wallClockNs
50
- } from "./chunk-QTZSBQGJ.js";
52
+ } from "./chunk-UG2QZMRN.js";
51
53
 
52
54
  // src/core/index.ts
53
55
  var core_exports = {};
54
56
  __export(core_exports, {
57
+ CLEANUP_RESULT: () => CLEANUP_RESULT,
55
58
  COMPLETE: () => COMPLETE,
56
59
  DATA: () => DATA,
57
60
  DEFAULT_ACTOR: () => DEFAULT_ACTOR,
61
+ DEFAULT_DOWN: () => DEFAULT_DOWN,
58
62
  DIRTY: () => DIRTY,
59
63
  DynamicNodeImpl: () => DynamicNodeImpl,
60
64
  ERROR: () => ERROR,
@@ -68,6 +72,8 @@ __export(core_exports, {
68
72
  accessHintForGuard: () => accessHintForGuard,
69
73
  advanceVersion: () => advanceVersion,
70
74
  batch: () => batch,
75
+ bridge: () => bridge,
76
+ cleanupResult: () => cleanupResult,
71
77
  createVersioning: () => createVersioning,
72
78
  defaultHash: () => defaultHash,
73
79
  derived: () => derived,
@@ -97,7 +103,60 @@ __export(core_exports, {
97
103
  wallClockNs: () => wallClockNs
98
104
  });
99
105
 
106
+ // src/core/bridge.ts
107
+ var DEFAULT_DOWN = [
108
+ DATA,
109
+ DIRTY,
110
+ RESOLVED,
111
+ COMPLETE,
112
+ ERROR,
113
+ TEARDOWN,
114
+ PAUSE,
115
+ RESUME,
116
+ INVALIDATE
117
+ ];
118
+ var STANDARD_TYPES = /* @__PURE__ */ new Set([
119
+ DATA,
120
+ DIRTY,
121
+ RESOLVED,
122
+ COMPLETE,
123
+ ERROR,
124
+ TEARDOWN,
125
+ PAUSE,
126
+ RESUME,
127
+ INVALIDATE
128
+ ]);
129
+ function bridge(from, to, opts) {
130
+ const allowedDown = new Set(opts?.down ?? DEFAULT_DOWN);
131
+ const onMessage = (msg, _depIndex, _actions) => {
132
+ const type = msg[0];
133
+ if (!STANDARD_TYPES.has(type)) {
134
+ to.down([msg]);
135
+ return true;
136
+ }
137
+ if (type === COMPLETE || type === ERROR) {
138
+ if (allowedDown.has(type)) {
139
+ to.down([msg]);
140
+ }
141
+ return false;
142
+ }
143
+ if (!allowedDown.has(type)) {
144
+ return true;
145
+ }
146
+ to.down([msg]);
147
+ return true;
148
+ };
149
+ return node([from], void 0, {
150
+ name: opts?.name,
151
+ describeKind: "effect",
152
+ onMessage,
153
+ meta: { _internal: true }
154
+ });
155
+ }
156
+
100
157
  export {
158
+ DEFAULT_DOWN,
159
+ bridge,
101
160
  core_exports
102
161
  };
103
- //# sourceMappingURL=chunk-E7OH6ZAZ.js.map
162
+ //# sourceMappingURL=chunk-FMVFRP7L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/index.ts","../src/core/bridge.ts"],"sourcesContent":["/**\n * Core layer: message protocol, node primitive, lifecycle (Phase 0).\n */\nexport * from \"./actor.js\";\nexport * from \"./batch.js\";\nexport { type BridgeOptions, bridge, DEFAULT_DOWN } from \"./bridge.js\";\nexport { monotonicNs, wallClockNs } from \"./clock.js\";\nexport * from \"./dynamic-node.js\";\nexport * from \"./guard.js\";\nexport * from \"./messages.js\";\nexport * from \"./meta.js\";\nexport {\n\tCLEANUP_RESULT,\n\ttype CleanupResult,\n\tcleanupResult,\n\ttype Node,\n\ttype NodeActions,\n\ttype NodeDescribeKind,\n\ttype NodeFn,\n\ttype NodeOptions,\n\ttype NodeSink,\n\ttype NodeStatus,\n\ttype NodeTransportOptions,\n\tnode,\n\ttype OnMessageHandler,\n\ttype SubscribeHints,\n} from \"./node.js\";\nexport * from \"./sugar.js\";\nexport { ResettableTimer } from \"./timer.js\";\nexport {\n\tadvanceVersion,\n\tcreateVersioning,\n\tdefaultHash,\n\ttype HashFn,\n\tisV1,\n\ttype NodeVersionInfo,\n\ttype V0,\n\ttype V1,\n\ttype VersioningLevel,\n\ttype VersioningOptions,\n} from \"./versioning.js\";\n","/**\n * bridge — graph-visible message forwarding between two nodes.\n *\n * Replaces ad-hoc `subscribe()` bridges that bypass graph topology.\n * The returned node is an effect that intercepts messages from `from`\n * and forwards them to `to.down()`. Register it with `graph.add()` to\n * make the bridge visible in `describe()` and `snapshot()`.\n *\n * **Upstream path:** The bridge node has `from` as its dep, so anything\n * downstream of the bridge that calls `up()` naturally reaches `from`.\n * If `to` is used as a dep by other nodes and those nodes send `up()`,\n * the messages reach `to`'s deps (not `from`). For full upstream relay\n * across the bridge boundary, wire the bridge as a dep of `to`'s\n * consumers or use `graph.connect()`.\n *\n * **ABAC / guards:** `to.down()` is called without `NodeTransportOptions`,\n * so any ABAC guard on `to` receives `actor = undefined`. Upstream (`up()`)\n * messages propagate through the dep chain the same way — no actor is\n * injected on either path. Both paths are intentionally unguarded; if `to`\n * requires a specific actor, provide a guarded wrapper node and bridge to\n * that instead.\n *\n * **Default forwarding:** All standard message types are forwarded by\n * default, including TEARDOWN, PAUSE, RESUME, and INVALIDATE. Use the\n * `down` option to restrict which types are forwarded. Callers that need\n * to exclude TEARDOWN (e.g. inter-stage wiring in `funnel()`) pass an\n * explicit `down` array without TEARDOWN.\n *\n * @module\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tINVALIDATE,\n\ttype Message,\n\tPAUSE,\n\tRESOLVED,\n\tRESUME,\n\tTEARDOWN,\n} from \"./messages.js\";\nimport { type Node, type NodeActions, node, type OnMessageHandler } from \"./node.js\";\n\n/** Options for {@link bridge}. */\nexport type BridgeOptions = {\n\t/** Node name (for graph registration / describe). */\n\tname?: string;\n\t/**\n\t * Standard message types to forward downstream. Default: all standard\n\t * types. Unknown (non-standard) types always forward per spec §1.3.6\n\t * regardless of this option.\n\t */\n\tdown?: readonly symbol[];\n};\n\n/** All standard types forwarded by default. Export for callers that\n * need to customize (e.g. exclude TEARDOWN). */\nexport const DEFAULT_DOWN: readonly symbol[] = [\n\tDATA,\n\tDIRTY,\n\tRESOLVED,\n\tCOMPLETE,\n\tERROR,\n\tTEARDOWN,\n\tPAUSE,\n\tRESUME,\n\tINVALIDATE,\n];\n\n/**\n * All standard message types the bridge understands. Types outside this set\n * are \"unknown\" and must always be forwarded (spec §1.3.6).\n */\nconst STANDARD_TYPES = new Set<symbol>([\n\tDATA,\n\tDIRTY,\n\tRESOLVED,\n\tCOMPLETE,\n\tERROR,\n\tTEARDOWN,\n\tPAUSE,\n\tRESUME,\n\tINVALIDATE,\n]);\n\n/**\n * Create a graph-visible bridge node that forwards messages from `from` to `to`.\n *\n * The bridge is a real node (effect) — it shows up in `describe()`, participates\n * in two-phase push, and cleans up on TEARDOWN. Register it via `graph.add()`\n * to make it part of the graph topology.\n *\n * **Unknown message types** (custom domain signals not in the standard protocol\n * set) are always forwarded to `to`, regardless of the `down` option. This\n * satisfies spec §1.3.6 (\"unknown types forward unchanged\").\n *\n * **COMPLETE / ERROR**: when forwarded, the bridge also transitions to terminal\n * state so graph-wide completion detection works correctly.\n *\n * @param from - Source node to observe.\n * @param to - Target node to forward messages to via `to.down()`.\n * @param opts - Optional configuration.\n * @returns A bridge effect node. Add it to a graph with `graph.add(name, bridge(...))`.\n *\n * @example\n * ```ts\n * import { bridge, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const a = state(0);\n * const b = state(0);\n * const br = bridge(a, b, { name: \"__bridge_a_b\" });\n * graph.add(\"__bridge_a_b\", br);\n * // Now a's messages flow to b, visible in describe()\n * ```\n *\n * @category core\n */\nexport function bridge<T = unknown>(from: Node<T>, to: Node, opts?: BridgeOptions): Node<unknown> {\n\tconst allowedDown = new Set(opts?.down ?? DEFAULT_DOWN);\n\n\tconst onMessage: OnMessageHandler = (\n\t\tmsg: Message,\n\t\t_depIndex: number,\n\t\t_actions: NodeActions,\n\t): boolean => {\n\t\tconst type = msg[0];\n\n\t\t// Unknown types (custom domain signals) always forward — spec §1.3.6.\n\t\tif (!STANDARD_TYPES.has(type)) {\n\t\t\tto.down([msg]);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Terminal types: always transition the bridge to terminal state\n\t\t// (return false → default dispatch). Only forward to `to` if allowed.\n\t\tif (type === COMPLETE || type === ERROR) {\n\t\t\tif (allowedDown.has(type)) {\n\t\t\t\tto.down([msg]);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Known type, not in allowedDown — consume without forwarding.\n\t\tif (!allowedDown.has(type)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Forward the message to the target.\n\t\tto.down([msg]);\n\t\treturn true;\n\t};\n\n\treturn node([from as Node], undefined, {\n\t\tname: opts?.name,\n\t\tdescribeKind: \"effect\",\n\t\tonMessage,\n\t\tmeta: { _internal: true },\n\t});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC2DO,IAAM,eAAkC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAMA,IAAM,iBAAiB,oBAAI,IAAY;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAkCM,SAAS,OAAoB,MAAe,IAAU,MAAqC;AACjG,QAAM,cAAc,IAAI,IAAI,MAAM,QAAQ,YAAY;AAEtD,QAAM,YAA8B,CACnC,KACA,WACA,aACa;AACb,UAAM,OAAO,IAAI,CAAC;AAGlB,QAAI,CAAC,eAAe,IAAI,IAAI,GAAG;AAC9B,SAAG,KAAK,CAAC,GAAG,CAAC;AACb,aAAO;AAAA,IACR;AAIA,QAAI,SAAS,YAAY,SAAS,OAAO;AACxC,UAAI,YAAY,IAAI,IAAI,GAAG;AAC1B,WAAG,KAAK,CAAC,GAAG,CAAC;AAAA,MACd;AACA,aAAO;AAAA,IACR;AAGA,QAAI,CAAC,YAAY,IAAI,IAAI,GAAG;AAC3B,aAAO;AAAA,IACR;AAGA,OAAG,KAAK,CAAC,GAAG,CAAC;AACb,WAAO;AAAA,EACR;AAEA,SAAO,KAAK,CAAC,IAAY,GAAG,QAAW;AAAA,IACtC,MAAM,MAAM;AAAA,IACZ,cAAc;AAAA,IACd;AAAA,IACA,MAAM,EAAE,WAAW,KAAK;AAAA,EACzB,CAAC;AACF;","names":[]}
@@ -2,7 +2,7 @@ import {
2
2
  DynamicNodeImpl,
3
3
  NodeImpl,
4
4
  accessHintForGuard
5
- } from "./chunk-QTZSBQGJ.js";
5
+ } from "./chunk-UG2QZMRN.js";
6
6
 
7
7
  // src/core/meta.ts
8
8
  function resolveDescribeFields(detail, fields) {
@@ -13,7 +13,6 @@ function resolveDescribeFields(detail, fields) {
13
13
  case "full":
14
14
  return null;
15
15
  // null = include everything
16
- case "minimal":
17
16
  default:
18
17
  return /* @__PURE__ */ new Set(["type", "deps"]);
19
18
  }
@@ -103,4 +102,4 @@ export {
103
102
  metaSnapshot,
104
103
  describeNode
105
104
  };
106
- //# sourceMappingURL=chunk-LR2CLSEF.js.map
105
+ //# sourceMappingURL=chunk-OHUECHWY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/meta.ts"],"sourcesContent":["import type { Actor } from \"./actor.js\";\nimport { DynamicNodeImpl } from \"./dynamic-node.js\";\nimport { accessHintForGuard } from \"./guard.js\";\nimport { type Node, NodeImpl } from \"./node.js\";\n\n/** JSON-shaped slice of a node for Phase 1 `Graph.describe()` (GRAPHREFLY-SPEC §3.6, Appendix B). */\nexport type DescribeNodeOutput = {\n\ttype: \"state\" | \"derived\" | \"producer\" | \"operator\" | \"effect\";\n\tstatus?: Node[\"status\"];\n\tdeps: string[];\n\tmeta?: Record<string, unknown>;\n\tname?: string;\n\tvalue?: unknown;\n\t/** Node versioning info (GRAPHREFLY-SPEC §7). Present only when versioning is enabled. */\n\tv?: { id: string; version: number; cid?: string; prev?: string | null };\n\t/** Guard info (full detail). */\n\tguard?: string;\n\t/** Last mutation attribution (full detail). */\n\tlastMutation?: Readonly<{ actor: Actor; timestamp_ns: number }>;\n};\n\n/**\n * Detail level for `describe()` progressive disclosure (Phase 3.3b).\n * - `\"minimal\"` — type + deps only (default). LLM-friendly.\n * - `\"standard\"` — type, status, value, deps, meta, versioning (`v`).\n * - `\"full\"` — standard + guard, lastMutation.\n */\nexport type DescribeDetail = \"minimal\" | \"standard\" | \"full\";\n\n/**\n * Valid field names for `describe({ fields: [...] })` (Phase 3.3b).\n * Dotted paths like `\"meta.label\"` select specific meta keys.\n */\nexport type DescribeField =\n\t| \"type\"\n\t| \"status\"\n\t| \"value\"\n\t| \"deps\"\n\t| \"meta\"\n\t| \"v\"\n\t| \"guard\"\n\t| \"lastMutation\"\n\t| `meta.${string}`;\n\n/** Resolve which fields to include based on detail level or explicit field list. */\nexport function resolveDescribeFields(\n\tdetail?: DescribeDetail,\n\tfields?: readonly DescribeField[],\n): Set<string> | null {\n\t// Explicit fields override detail level\n\tif (fields != null && fields.length > 0) return new Set(fields);\n\tswitch (detail) {\n\t\tcase \"standard\":\n\t\t\treturn new Set([\"type\", \"status\", \"value\", \"deps\", \"meta\", \"v\"]);\n\t\tcase \"full\":\n\t\t\treturn null; // null = include everything\n\t\tdefault:\n\t\t\treturn new Set([\"type\", \"deps\"]);\n\t}\n}\n\nfunction inferDescribeType(n: NodeImpl): DescribeNodeOutput[\"type\"] {\n\tif (n._describeKind != null) return n._describeKind;\n\tif (!n._hasDeps) return n._fn != null ? \"producer\" : \"state\";\n\tif (n._fn == null) return \"derived\";\n\tif (n._manualEmitUsed) return \"operator\";\n\treturn \"derived\";\n}\n\n/**\n * Reads the current cached value of every companion meta field on a node,\n * suitable for merging into `describe()`-style JSON (GRAPHREFLY-SPEC §2.3, §3.6).\n *\n * @remarks\n * Values come from {@link Node.get}, which returns the **last settled** cache.\n * If a meta field is in `\"dirty\"` status (DIRTY received, DATA pending), the\n * snapshot contains the *previous* value — check `node.meta[key].status` when\n * freshness matters. Avoid calling mid-batch for the same reason.\n *\n * Meta nodes are **not** terminated when their parent receives COMPLETE or\n * ERROR — they remain writable so callers can record post-mortem metadata\n * (e.g. `meta.error`). They *are* torn down when the parent receives TEARDOWN.\n *\n * @param node - The node whose meta fields to snapshot.\n * @returns Plain object of `{ key: value }` pairs (empty if no meta defined).\n * Keys whose companion node's {@link Node.get} throws are omitted.\n *\n * @example\n * ```ts\n * import { core } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = core.node({ initial: 0, meta: { tag: \"a\" } });\n * core.metaSnapshot(n); // { tag: \"a\" }\n * ```\n */\nexport function metaSnapshot(node: Node): Record<string, unknown> {\n\tconst out: Record<string, unknown> = {};\n\tfor (const [key, child] of Object.entries(node.meta)) {\n\t\ttry {\n\t\t\tout[key] = child.get();\n\t\t} catch {\n\t\t\t/* omit key — describe tooling still gets other fields */\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Builds a single-node slice of `Graph.describe()` JSON (structure + `meta` snapshot).\n * Parity with graphrefly-py `describe_node`.\n *\n * `type` is inferred from factory configuration, optional `describeKind` in node options,\n * and the last `manualEmitUsed` hint (operator vs derived). {@link effect} sets\n * `describeKind: \"effect\"`. Nodes not created by {@link node} fall back to `type: \"state\"` and empty `deps`.\n *\n * @param node - Any `Node` to introspect.\n * @returns `DescribeNodeOutput` suitable for merging into graph describe maps.\n *\n * @example\n * ```ts\n * import { describeNode, state } from \"@graphrefly/graphrefly-ts\";\n *\n * describeNode(state(0));\n * ```\n */\n/**\n * Builds a single-node slice for `Graph.describe()`.\n *\n * @param node - Node to introspect.\n * @param includeFields - Set of fields to include, or `null` for all. When omitted, all fields are included (legacy behavior).\n */\nexport function describeNode(node: Node, includeFields?: Set<string> | null): DescribeNodeOutput {\n\tconst all = includeFields == null; // null or undefined → include everything\n\n\t// Specific meta keys requested via dotted paths (e.g. \"meta.label\")\n\tconst metaKeys: string[] | null =\n\t\t!all && includeFields != null\n\t\t\t? [...includeFields].filter((f) => f.startsWith(\"meta.\")).map((f) => f.slice(5))\n\t\t\t: null;\n\tconst wantsMeta = all || includeFields!.has(\"meta\") || (metaKeys != null && metaKeys.length > 0);\n\n\tlet type: DescribeNodeOutput[\"type\"] = \"state\";\n\tlet deps: string[] = [];\n\n\tif (node instanceof NodeImpl) {\n\t\ttype = inferDescribeType(node);\n\t\tdeps = node._deps.map((d) => d.name ?? \"\");\n\t} else if (node instanceof DynamicNodeImpl) {\n\t\ttype = node._describeKind ?? \"derived\";\n\t\tdeps = [];\n\t}\n\n\tconst out: DescribeNodeOutput = { type, deps };\n\n\t// status\n\tif (all || includeFields!.has(\"status\")) {\n\t\tout.status = node.status;\n\t}\n\n\t// Resolve guard once — used by both meta.access hint and standalone guard field\n\tconst guard =\n\t\t(node instanceof NodeImpl && node._guard) ||\n\t\t(node instanceof DynamicNodeImpl && node._guard) ||\n\t\tundefined;\n\n\t// meta\n\tif (wantsMeta) {\n\t\tconst rawMeta: Record<string, unknown> = { ...metaSnapshot(node) };\n\t\tif (guard != null && rawMeta.access === undefined) {\n\t\t\trawMeta.access = accessHintForGuard(guard);\n\t\t}\n\n\t\tif (metaKeys != null && metaKeys.length > 0 && !includeFields!.has(\"meta\")) {\n\t\t\t// Only specific meta keys\n\t\t\tconst filtered: Record<string, unknown> = {};\n\t\t\tfor (const k of metaKeys) {\n\t\t\t\tif (k in rawMeta) filtered[k] = rawMeta[k];\n\t\t\t}\n\t\t\tout.meta = filtered;\n\t\t} else {\n\t\t\tout.meta = rawMeta;\n\t\t}\n\t}\n\n\t// name (always include when present — it's identity, not detail)\n\tif (node.name != null) {\n\t\tout.name = node.name;\n\t}\n\n\t// value\n\tif (all || includeFields!.has(\"value\")) {\n\t\ttry {\n\t\t\tout.value = node.get();\n\t\t} catch {\n\t\t\t/* omit value */\n\t\t}\n\t}\n\n\t// Versioning (GRAPHREFLY-SPEC §7)\n\tif ((all || includeFields!.has(\"v\")) && node.v != null) {\n\t\tconst vInfo: DescribeNodeOutput[\"v\"] = { id: node.v.id, version: node.v.version };\n\t\tif (\"cid\" in node.v) {\n\t\t\tvInfo!.cid = (node.v as { cid: string }).cid;\n\t\t\tvInfo!.prev = (node.v as { prev: string | null }).prev;\n\t\t}\n\t\tout.v = vInfo;\n\t}\n\n\t// Guard info (full detail)\n\tif (all || includeFields!.has(\"guard\")) {\n\t\tif (guard != null) {\n\t\t\tout.guard = accessHintForGuard(guard);\n\t\t}\n\t}\n\n\t// Last mutation attribution (full detail)\n\tif (all || includeFields!.has(\"lastMutation\")) {\n\t\tif (node.lastMutation != null) {\n\t\t\tout.lastMutation = node.lastMutation;\n\t\t}\n\t}\n\n\treturn out;\n}\n"],"mappings":"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","names":[]}
@@ -7,10 +7,10 @@ import {
7
7
  reactiveLog,
8
8
  toMessages$,
9
9
  toObservable
10
- } from "./chunk-YWTP2XRJ.js";
10
+ } from "./chunk-5WXTWOD7.js";
11
11
  import {
12
12
  Graph
13
- } from "./chunk-WYI7YW54.js";
13
+ } from "./chunk-2OTXEZQO.js";
14
14
  import {
15
15
  COMPLETE,
16
16
  DATA,
@@ -28,7 +28,7 @@ import {
28
28
  policy,
29
29
  state,
30
30
  wallClockNs
31
- } from "./chunk-QTZSBQGJ.js";
31
+ } from "./chunk-UG2QZMRN.js";
32
32
 
33
33
  // src/compat/nestjs/index.ts
34
34
  var nestjs_exports = {};
@@ -1369,4 +1369,4 @@ export {
1369
1369
  GraphReflyModule,
1370
1370
  nestjs_exports
1371
1371
  };
1372
- //# sourceMappingURL=chunk-UCW3VWMN.js.map
1372
+ //# sourceMappingURL=chunk-PZCDQD2U.js.map
@@ -2,10 +2,10 @@ import {
2
2
  GRAPH_META_SEGMENT,
3
3
  Graph,
4
4
  reachable
5
- } from "./chunk-WYI7YW54.js";
5
+ } from "./chunk-2OTXEZQO.js";
6
6
  import {
7
7
  __export
8
- } from "./chunk-QTZSBQGJ.js";
8
+ } from "./chunk-UG2QZMRN.js";
9
9
 
10
10
  // src/graph/index.ts
11
11
  var graph_exports = {};
@@ -104,4 +104,4 @@ export {
104
104
  replayWAL,
105
105
  graph_exports
106
106
  };
107
- //# sourceMappingURL=chunk-A2AJJOSJ.js.map
107
+ //# sourceMappingURL=chunk-U5HFZGAQ.js.map
@@ -454,6 +454,7 @@ function isV1(info) {
454
454
 
455
455
  // src/core/node.ts
456
456
  var NO_VALUE = /* @__PURE__ */ Symbol.for("graphrefly/NO_VALUE");
457
+ var CLEANUP_RESULT = /* @__PURE__ */ Symbol.for("graphrefly/CLEANUP_RESULT");
457
458
  function createIntBitSet() {
458
459
  let bits = 0;
459
460
  return {
@@ -516,6 +517,12 @@ function createBitSet(size) {
516
517
  }
517
518
  var isNodeArray = (value) => Array.isArray(value);
518
519
  var isNodeOptions = (value) => typeof value === "object" && value != null && !Array.isArray(value);
520
+ function cleanupResult(cleanup, ...args) {
521
+ const r = { [CLEANUP_RESULT]: true, cleanup };
522
+ if (args.length > 0) r.value = args[0];
523
+ return r;
524
+ }
525
+ var isCleanupResult = (value) => typeof value === "object" && value !== null && CLEANUP_RESULT in value;
519
526
  var isCleanupFn = (value) => typeof value === "function";
520
527
  var statusAfterMessage = (status, msg) => {
521
528
  const t = msg[0];
@@ -931,6 +938,14 @@ var NodeImpl = class {
931
938
  this._lastDepValues = depValues;
932
939
  this._inspectorHook?.({ kind: "run", depValues });
933
940
  const out = this._fn(depValues, this._actions);
941
+ if (isCleanupResult(out)) {
942
+ this._cleanup = out.cleanup;
943
+ if (this._manualEmitUsed) return;
944
+ if ("value" in out) {
945
+ this._emitAutoValue(out.value);
946
+ }
947
+ return;
948
+ }
934
949
  if (isCleanupFn(out)) {
935
950
  this._cleanup = out;
936
951
  return;
@@ -1617,6 +1632,8 @@ export {
1617
1632
  createVersioning,
1618
1633
  advanceVersion,
1619
1634
  isV1,
1635
+ CLEANUP_RESULT,
1636
+ cleanupResult,
1620
1637
  NodeImpl,
1621
1638
  node,
1622
1639
  dynamicNode,
@@ -1627,4 +1644,4 @@ export {
1627
1644
  effect,
1628
1645
  pipe
1629
1646
  };
1630
- //# sourceMappingURL=chunk-QTZSBQGJ.js.map
1647
+ //# sourceMappingURL=chunk-UG2QZMRN.js.map