@graphrefly/graphrefly 0.21.0 → 0.23.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 (101) hide show
  1. package/README.md +7 -5
  2. package/dist/chunk-263BEJJO.js +115 -0
  3. package/dist/chunk-263BEJJO.js.map +1 -0
  4. package/dist/chunk-2GQLMQVJ.js +47 -0
  5. package/dist/chunk-2GQLMQVJ.js.map +1 -0
  6. package/dist/chunk-32N5A454.js +36 -0
  7. package/dist/chunk-32N5A454.js.map +1 -0
  8. package/dist/chunk-7TAQJHQV.js +103 -0
  9. package/dist/chunk-7TAQJHQV.js.map +1 -0
  10. package/dist/{chunk-VOQFK7YN.js → chunk-CWYPA63G.js} +109 -259
  11. package/dist/chunk-CWYPA63G.js.map +1 -0
  12. package/dist/{chunk-7IGHIFTT.js → chunk-HVBX5KIW.js} +15 -26
  13. package/dist/chunk-HVBX5KIW.js.map +1 -0
  14. package/dist/chunk-JFONSPNF.js +391 -0
  15. package/dist/chunk-JFONSPNF.js.map +1 -0
  16. package/dist/chunk-NZMBRXQV.js +2330 -0
  17. package/dist/chunk-NZMBRXQV.js.map +1 -0
  18. package/dist/{chunk-XWBVAO2R.js → chunk-PNUZM7PC.js} +20 -30
  19. package/dist/chunk-PNUZM7PC.js.map +1 -0
  20. package/dist/{chunk-ZTCDY5NQ.js → chunk-PX6PDUJ5.js} +34 -50
  21. package/dist/chunk-PX6PDUJ5.js.map +1 -0
  22. package/dist/chunk-XRFJJ2IU.js +2417 -0
  23. package/dist/chunk-XRFJJ2IU.js.map +1 -0
  24. package/dist/chunk-XTLYW4FR.js +6829 -0
  25. package/dist/chunk-XTLYW4FR.js.map +1 -0
  26. package/dist/compat/nestjs/index.cjs +3489 -2286
  27. package/dist/compat/nestjs/index.cjs.map +1 -1
  28. package/dist/compat/nestjs/index.d.cts +6 -4
  29. package/dist/compat/nestjs/index.d.ts +6 -4
  30. package/dist/compat/nestjs/index.js +10 -8
  31. package/dist/core/index.cjs +1706 -1217
  32. package/dist/core/index.cjs.map +1 -1
  33. package/dist/core/index.d.cts +3 -2
  34. package/dist/core/index.d.ts +3 -2
  35. package/dist/core/index.js +37 -34
  36. package/dist/extra/index.cjs +7519 -6125
  37. package/dist/extra/index.cjs.map +1 -1
  38. package/dist/extra/index.d.cts +4 -4
  39. package/dist/extra/index.d.ts +4 -4
  40. package/dist/extra/index.js +63 -34
  41. package/dist/graph/index.cjs +3199 -2212
  42. package/dist/graph/index.cjs.map +1 -1
  43. package/dist/graph/index.d.cts +5 -3
  44. package/dist/graph/index.d.ts +5 -3
  45. package/dist/graph/index.js +24 -11
  46. package/dist/graph-BtdSRHUc.d.cts +1128 -0
  47. package/dist/graph-CEO2FkLY.d.ts +1128 -0
  48. package/dist/{index-DuN3bhtm.d.ts → index-B0tfuXwV.d.cts} +1697 -586
  49. package/dist/index-BFGjXbiP.d.cts +315 -0
  50. package/dist/{index-CgSiUouz.d.ts → index-BPlWVAKY.d.cts} +4 -4
  51. package/dist/index-BUj3ASVe.d.cts +406 -0
  52. package/dist/{index-VHA43cGP.d.cts → index-C59uSJAH.d.cts} +2 -2
  53. package/dist/index-CkElcUY6.d.ts +315 -0
  54. package/dist/index-DSPc5rkv.d.ts +406 -0
  55. package/dist/{index-BjtlNirP.d.cts → index-DgscL7v0.d.ts} +4 -4
  56. package/dist/{index-SFzE_KTa.d.cts → index-RXN94sHK.d.ts} +1697 -586
  57. package/dist/{index-8a605sg9.d.ts → index-jEtF4N7L.d.ts} +2 -2
  58. package/dist/index.cjs +9947 -7949
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.d.cts +214 -37
  61. package/dist/index.d.ts +214 -37
  62. package/dist/index.js +919 -648
  63. package/dist/index.js.map +1 -1
  64. package/dist/meta-3QjzotRv.d.ts +41 -0
  65. package/dist/meta-B-Lbs4-O.d.cts +41 -0
  66. package/dist/node-C7PD3sn9.d.cts +1188 -0
  67. package/dist/node-C7PD3sn9.d.ts +1188 -0
  68. package/dist/{observable-DcBwQY7t.d.ts → observable-EyO-moQY.d.ts} +1 -1
  69. package/dist/{observable-C8Kx_O6k.d.cts → observable-axpzv1K2.d.cts} +1 -1
  70. package/dist/patterns/reactive-layout/index.cjs +3205 -2138
  71. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  72. package/dist/patterns/reactive-layout/index.d.cts +5 -3
  73. package/dist/patterns/reactive-layout/index.d.ts +5 -3
  74. package/dist/patterns/reactive-layout/index.js +7 -4
  75. package/dist/storage-CHT5WE9m.d.ts +182 -0
  76. package/dist/storage-DIgAr7M_.d.cts +182 -0
  77. package/package.json +2 -1
  78. package/dist/chunk-2UDLYZHT.js +0 -2117
  79. package/dist/chunk-2UDLYZHT.js.map +0 -1
  80. package/dist/chunk-4MQ2J6IG.js +0 -1631
  81. package/dist/chunk-4MQ2J6IG.js.map +0 -1
  82. package/dist/chunk-7IGHIFTT.js.map +0 -1
  83. package/dist/chunk-DOSLSFKL.js +0 -162
  84. package/dist/chunk-DOSLSFKL.js.map +0 -1
  85. package/dist/chunk-ECN37NVS.js +0 -6227
  86. package/dist/chunk-ECN37NVS.js.map +0 -1
  87. package/dist/chunk-G66H6ZRK.js +0 -111
  88. package/dist/chunk-G66H6ZRK.js.map +0 -1
  89. package/dist/chunk-VOQFK7YN.js.map +0 -1
  90. package/dist/chunk-WZ2Z2CRV.js +0 -32
  91. package/dist/chunk-WZ2Z2CRV.js.map +0 -1
  92. package/dist/chunk-XWBVAO2R.js.map +0 -1
  93. package/dist/chunk-ZTCDY5NQ.js.map +0 -1
  94. package/dist/graph-KsTe57nI.d.cts +0 -750
  95. package/dist/graph-mILUUqW8.d.ts +0 -750
  96. package/dist/index-B2SvPEbc.d.ts +0 -257
  97. package/dist/index-BHfg_Ez3.d.ts +0 -629
  98. package/dist/index-Bc_diYYJ.d.cts +0 -629
  99. package/dist/index-UudxGnzc.d.cts +0 -257
  100. package/dist/meta-BnG7XAaE.d.cts +0 -778
  101. package/dist/meta-BnG7XAaE.d.ts +0 -778
package/README.md CHANGED
@@ -200,10 +200,10 @@ import { node, map, Graph } from "@graphrefly/graphrefly";
200
200
 
201
201
  ## Resilience & checkpoints
202
202
 
203
- Built-in retry, circuit breakers, rate limiters, and persistent checkpoints:
203
+ Built-in retry, circuit breakers, rate limiters, and persistent storage:
204
204
 
205
205
  ```ts
206
- import { retry, circuitBreaker, saveGraphCheckpoint, FileCheckpointAdapter } from "@graphrefly/graphrefly";
206
+ import { retry, circuitBreaker, fileStorage, memoryStorage } from "@graphrefly/graphrefly";
207
207
 
208
208
  // Retry with exponential backoff
209
209
  const resilient = pipe(source, retry({ strategy: "exponential" }));
@@ -211,9 +211,11 @@ const resilient = pipe(source, retry({ strategy: "exponential" }));
211
211
  // Circuit breaker
212
212
  const breaker = circuitBreaker({ threshold: 5, resetTimeout: 30_000 });
213
213
 
214
- // Checkpoint to file system
215
- const adapter = new FileCheckpointAdapter("./checkpoints");
216
- await saveGraphCheckpoint(graph, adapter);
214
+ // Multi-tier storage with auto-restore: hot in-memory + warm on disk.
215
+ graph.attachStorage(
216
+ [memoryStorage(), fileStorage("./checkpoints")],
217
+ { autoRestore: true },
218
+ );
217
219
  ```
218
220
 
219
221
  ## Project layout
@@ -0,0 +1,115 @@
1
+ import {
2
+ resolveDescribeFields
3
+ } from "./chunk-HVBX5KIW.js";
4
+ import {
5
+ COMPLETE,
6
+ COMPLETE_MSG,
7
+ COMPLETE_ONLY_BATCH,
8
+ DATA,
9
+ DEFAULT_ACTOR,
10
+ DIRTY,
11
+ DIRTY_MSG,
12
+ DIRTY_ONLY_BATCH,
13
+ ERROR,
14
+ GraphReFlyConfig,
15
+ GuardDenied,
16
+ INVALIDATE,
17
+ INVALIDATE_MSG,
18
+ INVALIDATE_ONLY_BATCH,
19
+ NodeImpl,
20
+ PAUSE,
21
+ RESOLVED,
22
+ RESOLVED_MSG,
23
+ RESOLVED_ONLY_BATCH,
24
+ RESUME,
25
+ START,
26
+ START_MSG,
27
+ TEARDOWN,
28
+ TEARDOWN_MSG,
29
+ TEARDOWN_ONLY_BATCH,
30
+ __export,
31
+ accessHintForGuard,
32
+ advanceVersion,
33
+ autoTrackNode,
34
+ batch,
35
+ configure,
36
+ createVersioning,
37
+ defaultConfig,
38
+ defaultHash,
39
+ derived,
40
+ downWithBatch,
41
+ dynamicNode,
42
+ effect,
43
+ isBatching,
44
+ isV1,
45
+ monotonicNs,
46
+ node,
47
+ normalizeActor,
48
+ pipe,
49
+ policy,
50
+ policyFromRules,
51
+ producer,
52
+ registerBuiltins,
53
+ state,
54
+ wallClockNs
55
+ } from "./chunk-NZMBRXQV.js";
56
+
57
+ // src/core/index.ts
58
+ var core_exports = {};
59
+ __export(core_exports, {
60
+ COMPLETE: () => COMPLETE,
61
+ COMPLETE_MSG: () => COMPLETE_MSG,
62
+ COMPLETE_ONLY_BATCH: () => COMPLETE_ONLY_BATCH,
63
+ DATA: () => DATA,
64
+ DEFAULT_ACTOR: () => DEFAULT_ACTOR,
65
+ DIRTY: () => DIRTY,
66
+ DIRTY_MSG: () => DIRTY_MSG,
67
+ DIRTY_ONLY_BATCH: () => DIRTY_ONLY_BATCH,
68
+ ERROR: () => ERROR,
69
+ GraphReFlyConfig: () => GraphReFlyConfig,
70
+ GuardDenied: () => GuardDenied,
71
+ INVALIDATE: () => INVALIDATE,
72
+ INVALIDATE_MSG: () => INVALIDATE_MSG,
73
+ INVALIDATE_ONLY_BATCH: () => INVALIDATE_ONLY_BATCH,
74
+ NodeImpl: () => NodeImpl,
75
+ PAUSE: () => PAUSE,
76
+ RESOLVED: () => RESOLVED,
77
+ RESOLVED_MSG: () => RESOLVED_MSG,
78
+ RESOLVED_ONLY_BATCH: () => RESOLVED_ONLY_BATCH,
79
+ RESUME: () => RESUME,
80
+ START: () => START,
81
+ START_MSG: () => START_MSG,
82
+ TEARDOWN: () => TEARDOWN,
83
+ TEARDOWN_MSG: () => TEARDOWN_MSG,
84
+ TEARDOWN_ONLY_BATCH: () => TEARDOWN_ONLY_BATCH,
85
+ accessHintForGuard: () => accessHintForGuard,
86
+ advanceVersion: () => advanceVersion,
87
+ autoTrackNode: () => autoTrackNode,
88
+ batch: () => batch,
89
+ configure: () => configure,
90
+ createVersioning: () => createVersioning,
91
+ defaultConfig: () => defaultConfig,
92
+ defaultHash: () => defaultHash,
93
+ derived: () => derived,
94
+ downWithBatch: () => downWithBatch,
95
+ dynamicNode: () => dynamicNode,
96
+ effect: () => effect,
97
+ isBatching: () => isBatching,
98
+ isV1: () => isV1,
99
+ monotonicNs: () => monotonicNs,
100
+ node: () => node,
101
+ normalizeActor: () => normalizeActor,
102
+ pipe: () => pipe,
103
+ policy: () => policy,
104
+ policyFromRules: () => policyFromRules,
105
+ producer: () => producer,
106
+ registerBuiltins: () => registerBuiltins,
107
+ resolveDescribeFields: () => resolveDescribeFields,
108
+ state: () => state,
109
+ wallClockNs: () => wallClockNs
110
+ });
111
+
112
+ export {
113
+ core_exports
114
+ };
115
+ //# sourceMappingURL=chunk-263BEJJO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/index.ts"],"sourcesContent":["/**\n * Core layer: message protocol, node primitive, lifecycle (Phase 0).\n */\nexport * from \"./actor.js\";\nexport { batch, downWithBatch, isBatching } from \"./batch.js\";\nexport { monotonicNs, wallClockNs } from \"./clock.js\";\nexport {\n\ttype GlobalInspectorEvent,\n\ttype GlobalInspectorHook,\n\tGraphReFlyConfig,\n\ttype MessageContext,\n\ttype NodeActions,\n\ttype NodeCtx,\n\ttype OnMessageHandler,\n\ttype OnSubscribeHandler,\n\tregisterBuiltins,\n\ttype SubscribeContext,\n} from \"./config.js\";\nexport * from \"./guard.js\";\nexport {\n\tCOMPLETE,\n\tCOMPLETE_MSG,\n\tCOMPLETE_ONLY_BATCH,\n\tDATA,\n\tDIRTY,\n\tDIRTY_MSG,\n\tDIRTY_ONLY_BATCH,\n\tERROR,\n\tINVALIDATE,\n\tINVALIDATE_MSG,\n\tINVALIDATE_ONLY_BATCH,\n\ttype Message,\n\ttype Messages,\n\ttype MessageTypeRegistration,\n\ttype MessageTypeRegistrationInput,\n\tPAUSE,\n\tRESOLVED,\n\tRESOLVED_MSG,\n\tRESOLVED_ONLY_BATCH,\n\tRESUME,\n\tSTART,\n\tSTART_MSG,\n\tTEARDOWN,\n\tTEARDOWN_MSG,\n\tTEARDOWN_ONLY_BATCH,\n} from \"./messages.js\";\nexport {\n\ttype DescribeDetail,\n\ttype DescribeField,\n\ttype DescribeNodeOutput,\n\tresolveDescribeFields,\n} from \"./meta.js\";\nexport {\n\tconfigure,\n\ttype DepRecord,\n\tdefaultConfig,\n\ttype FnCtx,\n\ttype Node,\n\ttype NodeDescribeKind,\n\ttype NodeFn,\n\ttype NodeFnCleanup,\n\tNodeImpl,\n\ttype NodeInspectorHook,\n\ttype NodeInspectorHookEvent,\n\ttype NodeOptions,\n\ttype NodeSink,\n\ttype NodeStatus,\n\ttype NodeTransportOptions,\n\tnode,\n} from \"./node.js\";\nexport {\n\ttype AutoTrackOptions,\n\tautoTrackNode,\n\ttype DerivedFn,\n\ttype DynamicFn,\n\tderived,\n\tdynamicNode,\n\ttype EffectFn,\n\teffect,\n\ttype PipeOperator,\n\ttype ProducerFn,\n\tpipe,\n\tproducer,\n\tstate,\n\ttype TrackFn,\n} from \"./sugar.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"],"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;AAAA;AAAA;AAAA;","names":[]}
@@ -0,0 +1,47 @@
1
+ import {
2
+ GRAPH_META_SEGMENT,
3
+ Graph,
4
+ OVERHEAD,
5
+ SIZEOF_SYMBOL,
6
+ diffForWAL,
7
+ graphProfile,
8
+ reachable,
9
+ sizeof
10
+ } from "./chunk-XRFJJ2IU.js";
11
+ import {
12
+ ENVELOPE_VERSION,
13
+ JsonCodec,
14
+ __export,
15
+ createDagCborCodec,
16
+ createDagCborZstdCodec,
17
+ decodeEnvelope,
18
+ encodeEnvelope,
19
+ registerBuiltinCodecs,
20
+ replayWAL
21
+ } from "./chunk-NZMBRXQV.js";
22
+
23
+ // src/graph/index.ts
24
+ var graph_exports = {};
25
+ __export(graph_exports, {
26
+ ENVELOPE_VERSION: () => ENVELOPE_VERSION,
27
+ GRAPH_META_SEGMENT: () => GRAPH_META_SEGMENT,
28
+ Graph: () => Graph,
29
+ JsonCodec: () => JsonCodec,
30
+ SIZEOF_OVERHEAD: () => OVERHEAD,
31
+ SIZEOF_SYMBOL: () => SIZEOF_SYMBOL,
32
+ createDagCborCodec: () => createDagCborCodec,
33
+ createDagCborZstdCodec: () => createDagCborZstdCodec,
34
+ decodeEnvelope: () => decodeEnvelope,
35
+ diffForWAL: () => diffForWAL,
36
+ encodeEnvelope: () => encodeEnvelope,
37
+ graphProfile: () => graphProfile,
38
+ reachable: () => reachable,
39
+ registerBuiltinCodecs: () => registerBuiltinCodecs,
40
+ replayWAL: () => replayWAL,
41
+ sizeof: () => sizeof
42
+ });
43
+
44
+ export {
45
+ graph_exports
46
+ };
47
+ //# sourceMappingURL=chunk-2GQLMQVJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/graph/index.ts"],"sourcesContent":["/**\n * Graph container: registry, wiring, introspection (Phase 1).\n */\n\nexport { OVERHEAD as SIZEOF_OVERHEAD, SIZEOF_SYMBOL, sizeof } from \"../extra/utils/sizeof.js\";\nexport {\n\tcreateDagCborCodec,\n\tcreateDagCborZstdCodec,\n\tdecodeEnvelope,\n\tENVELOPE_VERSION,\n\ttype EvictedSubgraphInfo,\n\ttype EvictionPolicy,\n\tencodeEnvelope,\n\ttype GraphCodec,\n\tJsonCodec,\n\ttype LazyGraphCodec,\n\tregisterBuiltinCodecs,\n\treplayWAL,\n\ttype WALEntry,\n} from \"./codec.js\";\nexport {\n\ttype DescribeFilter,\n\tdiffForWAL,\n\tGRAPH_META_SEGMENT,\n\tGraph,\n\ttype GraphActorOptions,\n\ttype GraphAttachStorageOptions,\n\ttype GraphCheckpointRecord,\n\ttype GraphDescribeOptions,\n\ttype GraphDescribeOutput,\n\ttype GraphDiagramDirection,\n\ttype GraphDiagramOptions,\n\ttype GraphDiffChange,\n\ttype GraphDiffResult,\n\ttype GraphFactoryContext,\n\ttype GraphNodeFactory,\n\ttype GraphObserveAll,\n\ttype GraphObserveOne,\n\ttype GraphOptions,\n\ttype GraphPersistSnapshot,\n\ttype GraphVersionChange,\n\ttype GraphWALDiff,\n\ttype ObserveDetail,\n\ttype ObserveEvent,\n\ttype ObserveOptions,\n\ttype ObserveResult,\n\ttype ObserveTheme,\n\ttype ObserveThemeName,\n\ttype ReachableDirection,\n\ttype ReachableOptions,\n\treachable,\n\ttype TraceEntry,\n} from \"./graph.js\";\nexport {\n\ttype GraphProfileOptions,\n\ttype GraphProfileResult,\n\tgraphProfile,\n\ttype NodeProfile,\n} from \"./profile.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -0,0 +1,36 @@
1
+ import {
2
+ DATA,
3
+ DIRTY,
4
+ defaultConfig,
5
+ downWithBatch
6
+ } from "./chunk-NZMBRXQV.js";
7
+
8
+ // src/patterns/_internal.ts
9
+ function emitToMeta(metaNode, value) {
10
+ if (metaNode == null) return;
11
+ downWithBatch((msgs) => metaNode.down(msgs), [[DATA, value]], defaultConfig.tierOf);
12
+ }
13
+ function tryIncrementBounded(counter, cap) {
14
+ const cur = counter.cache ?? 0;
15
+ if (cur >= cap) return false;
16
+ counter.down([[DIRTY], [DATA, cur + 1]]);
17
+ return true;
18
+ }
19
+ function domainMeta(domain, kind, extra) {
20
+ return {
21
+ [domain]: true,
22
+ [`${domain}_type`]: kind,
23
+ ...extra ?? {}
24
+ };
25
+ }
26
+ function trackingKey(item) {
27
+ return item.relatedTo?.[0] ?? item.summary;
28
+ }
29
+
30
+ export {
31
+ emitToMeta,
32
+ tryIncrementBounded,
33
+ domainMeta,
34
+ trackingKey
35
+ };
36
+ //# sourceMappingURL=chunk-32N5A454.js.map
@@ -0,0 +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 * Equivalent to the expanded form:\n * ```ts\n * downWithBatch((msgs) => metaNode?.down(msgs), [[DATA, value]], tierOf);\n * ```\n * but captures the \"meta may not be mounted\" null guard and the\n * `defaultConfig.tierOf` boilerplate in one name.\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":";;;;;;;;AAyCO,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,103 @@
1
+ // src/extra/timer.ts
2
+ var ResettableTimer = class {
3
+ _timer;
4
+ _gen = 0;
5
+ /** Schedule callback after delayMs. Cancels any pending timer. */
6
+ start(delayMs, callback) {
7
+ this.cancel();
8
+ this._gen += 1;
9
+ const gen = this._gen;
10
+ this._timer = setTimeout(() => {
11
+ this._timer = void 0;
12
+ if (gen !== this._gen) return;
13
+ callback();
14
+ }, delayMs);
15
+ }
16
+ /** Cancel the pending timer (if any). */
17
+ cancel() {
18
+ if (this._timer !== void 0) {
19
+ clearTimeout(this._timer);
20
+ this._timer = void 0;
21
+ }
22
+ }
23
+ /** Whether a timer is currently pending. */
24
+ get pending() {
25
+ return this._timer !== void 0;
26
+ }
27
+ };
28
+
29
+ // src/extra/utils/ring-buffer.ts
30
+ var RingBuffer = class {
31
+ constructor(capacity) {
32
+ this.capacity = capacity;
33
+ if (!Number.isInteger(capacity) || capacity <= 0) {
34
+ throw new Error(`RingBuffer capacity must be a positive integer (got ${capacity})`);
35
+ }
36
+ this.buf = new Array(capacity);
37
+ }
38
+ buf;
39
+ head = 0;
40
+ _size = 0;
41
+ /** Current number of stored entries. */
42
+ get size() {
43
+ return this._size;
44
+ }
45
+ /** Configured maximum before drop-oldest eviction fires. */
46
+ get maxSize() {
47
+ return this.capacity;
48
+ }
49
+ /**
50
+ * Append an item. If size equals capacity, drops the oldest entry and
51
+ * advances the head pointer.
52
+ */
53
+ push(item) {
54
+ const idx = (this.head + this._size) % this.capacity;
55
+ this.buf[idx] = item;
56
+ if (this._size < this.capacity) this._size++;
57
+ else this.head = (this.head + 1) % this.capacity;
58
+ }
59
+ /** Remove and return the oldest entry; `undefined` when empty. */
60
+ shift() {
61
+ if (this._size === 0) return void 0;
62
+ const item = this.buf[this.head];
63
+ this.buf[this.head] = void 0;
64
+ this.head = (this.head + 1) % this.capacity;
65
+ this._size--;
66
+ return item;
67
+ }
68
+ /**
69
+ * O(1) index lookup. Negative indices count from the tail (Python-style).
70
+ * Returns `undefined` for out-of-range.
71
+ */
72
+ at(i) {
73
+ if (this._size === 0) return void 0;
74
+ const n = i < 0 ? this._size + i : i;
75
+ if (n < 0 || n >= this._size) return void 0;
76
+ return this.buf[(this.head + n) % this.capacity];
77
+ }
78
+ /**
79
+ * Materialize the contents in insertion order (oldest → newest).
80
+ * Returns a new array each call.
81
+ */
82
+ toArray() {
83
+ const result = new Array(this._size);
84
+ for (let i = 0; i < this._size; i++) {
85
+ result[i] = this.buf[(this.head + i) % this.capacity];
86
+ }
87
+ return result;
88
+ }
89
+ /** Reset to empty. Storage slots are released so held refs can GC. */
90
+ clear() {
91
+ for (let i = 0; i < this._size; i++) {
92
+ this.buf[(this.head + i) % this.capacity] = void 0;
93
+ }
94
+ this.head = 0;
95
+ this._size = 0;
96
+ }
97
+ };
98
+
99
+ export {
100
+ ResettableTimer,
101
+ RingBuffer
102
+ };
103
+ //# sourceMappingURL=chunk-7TAQJHQV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extra/timer.ts","../src/extra/utils/ring-buffer.ts"],"sourcesContent":["/**\n * Creates a resettable deadline timer for internal timeout, retry, and rate-limiting use.\n *\n * @remarks **Centralised primitive:** wraps `setTimeout`/`clearTimeout` with a generation guard\n * so that stale callbacks never fire after `cancel()` or a new `start()`.\n *\n * @remarks **Spec §5.10 exception:** resilience operators (`timeout`, `retry`, `rateLimiter`)\n * need raw timers — `fromTimer` creates a new Node per reset, which is too heavy here.\n * Lives in `src/extra/` (not `src/core/`) because it is a documented escape hatch from\n * the protocol-pure core layer.\n *\n * @example\n * ```ts\n * import { ResettableTimer } from \"@graphrefly/graphrefly-ts\";\n *\n * const timer = new ResettableTimer();\n * timer.start(1000, () => console.log(\"fired\"));\n * timer.cancel(); // cancels before firing\n * timer.start(500, () => console.log(\"new deadline\"));\n * console.log(timer.pending); // true\n * ```\n *\n * @category extra\n */\nexport class ResettableTimer {\n\tprivate _timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate _gen = 0;\n\n\t/** Schedule callback after delayMs. Cancels any pending timer. */\n\tstart(delayMs: number, callback: () => void): void {\n\t\tthis.cancel();\n\t\tthis._gen += 1;\n\t\tconst gen = this._gen;\n\t\tthis._timer = setTimeout(() => {\n\t\t\tthis._timer = undefined;\n\t\t\tif (gen !== this._gen) return;\n\t\t\tcallback();\n\t\t}, delayMs);\n\t}\n\n\t/** Cancel the pending timer (if any). */\n\tcancel(): void {\n\t\tif (this._timer !== undefined) {\n\t\t\tclearTimeout(this._timer);\n\t\t\tthis._timer = undefined;\n\t\t}\n\t}\n\n\t/** Whether a timer is currently pending. */\n\tget pending(): boolean {\n\t\treturn this._timer !== undefined;\n\t}\n}\n","/**\n * Fixed-capacity ring buffer — O(1) push and drop-oldest eviction.\n *\n * Used by `Graph._traceRing` (reasoning trace), `reactiveLog` (append-only\n * log backend), and `reactiveSink` (drop-oldest backpressure buffer). One\n * implementation, three use sites.\n *\n * @module\n * @internal\n */\n\n/**\n * Fixed-capacity ring buffer. Once `capacity` entries are stored, subsequent\n * `push` calls evict the oldest entry (drop-oldest / FIFO eviction).\n *\n * Operations:\n * - `push(item)` — O(1).\n * - `shift()` — O(1) remove oldest (returns `undefined` when empty).\n * - `at(i)` — O(1) index lookup, with Python-style negative indexing.\n * - `toArray()` — O(n) materialize in insertion order.\n * - `clear()` — O(1) reset to empty.\n *\n * Not thread-safe; JS semantics assumed (single-threaded within a sync call).\n */\nexport class RingBuffer<T> {\n\tprivate buf: (T | undefined)[];\n\tprivate head = 0;\n\tprivate _size = 0;\n\n\tconstructor(private capacity: number) {\n\t\tif (!Number.isInteger(capacity) || capacity <= 0) {\n\t\t\tthrow new Error(`RingBuffer capacity must be a positive integer (got ${capacity})`);\n\t\t}\n\t\tthis.buf = new Array(capacity);\n\t}\n\n\t/** Current number of stored entries. */\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\t/** Configured maximum before drop-oldest eviction fires. */\n\tget maxSize(): number {\n\t\treturn this.capacity;\n\t}\n\n\t/**\n\t * Append an item. If size equals capacity, drops the oldest entry and\n\t * advances the head pointer.\n\t */\n\tpush(item: T): void {\n\t\tconst idx = (this.head + this._size) % this.capacity;\n\t\tthis.buf[idx] = item;\n\t\tif (this._size < this.capacity) this._size++;\n\t\telse this.head = (this.head + 1) % this.capacity;\n\t}\n\n\t/** Remove and return the oldest entry; `undefined` when empty. */\n\tshift(): T | undefined {\n\t\tif (this._size === 0) return undefined;\n\t\tconst item = this.buf[this.head];\n\t\tthis.buf[this.head] = undefined;\n\t\tthis.head = (this.head + 1) % this.capacity;\n\t\tthis._size--;\n\t\treturn item;\n\t}\n\n\t/**\n\t * O(1) index lookup. Negative indices count from the tail (Python-style).\n\t * Returns `undefined` for out-of-range.\n\t */\n\tat(i: number): T | undefined {\n\t\tif (this._size === 0) return undefined;\n\t\tconst n = i < 0 ? this._size + i : i;\n\t\tif (n < 0 || n >= this._size) return undefined;\n\t\treturn this.buf[(this.head + n) % this.capacity];\n\t}\n\n\t/**\n\t * Materialize the contents in insertion order (oldest → newest).\n\t * Returns a new array each call.\n\t */\n\ttoArray(): T[] {\n\t\tconst result: T[] = new Array(this._size);\n\t\tfor (let i = 0; i < this._size; i++) {\n\t\t\tresult[i] = this.buf[(this.head + i) % this.capacity]!;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Reset to empty. Storage slots are released so held refs can GC. */\n\tclear(): void {\n\t\tfor (let i = 0; i < this._size; i++) {\n\t\t\tthis.buf[(this.head + i) % this.capacity] = undefined;\n\t\t}\n\t\tthis.head = 0;\n\t\tthis._size = 0;\n\t}\n}\n"],"mappings":";AAwBO,IAAM,kBAAN,MAAsB;AAAA,EACpB;AAAA,EACA,OAAO;AAAA;AAAA,EAGf,MAAM,SAAiB,UAA4B;AAClD,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,UAAM,MAAM,KAAK;AACjB,SAAK,SAAS,WAAW,MAAM;AAC9B,WAAK,SAAS;AACd,UAAI,QAAQ,KAAK,KAAM;AACvB,eAAS;AAAA,IACV,GAAG,OAAO;AAAA,EACX;AAAA;AAAA,EAGA,SAAe;AACd,QAAI,KAAK,WAAW,QAAW;AAC9B,mBAAa,KAAK,MAAM;AACxB,WAAK,SAAS;AAAA,IACf;AAAA,EACD;AAAA;AAAA,EAGA,IAAI,UAAmB;AACtB,WAAO,KAAK,WAAW;AAAA,EACxB;AACD;;;AC5BO,IAAM,aAAN,MAAoB;AAAA,EAK1B,YAAoB,UAAkB;AAAlB;AACnB,QAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,GAAG;AACjD,YAAM,IAAI,MAAM,uDAAuD,QAAQ,GAAG;AAAA,IACnF;AACA,SAAK,MAAM,IAAI,MAAM,QAAQ;AAAA,EAC9B;AAAA,EATQ;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA;AAAA,EAUhB,IAAI,OAAe;AAClB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,IAAI,UAAkB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,MAAe;AACnB,UAAM,OAAO,KAAK,OAAO,KAAK,SAAS,KAAK;AAC5C,SAAK,IAAI,GAAG,IAAI;AAChB,QAAI,KAAK,QAAQ,KAAK,SAAU,MAAK;AAAA,QAChC,MAAK,QAAQ,KAAK,OAAO,KAAK,KAAK;AAAA,EACzC;AAAA;AAAA,EAGA,QAAuB;AACtB,QAAI,KAAK,UAAU,EAAG,QAAO;AAC7B,UAAM,OAAO,KAAK,IAAI,KAAK,IAAI;AAC/B,SAAK,IAAI,KAAK,IAAI,IAAI;AACtB,SAAK,QAAQ,KAAK,OAAO,KAAK,KAAK;AACnC,SAAK;AACL,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,GAAG,GAA0B;AAC5B,QAAI,KAAK,UAAU,EAAG,QAAO;AAC7B,UAAM,IAAI,IAAI,IAAI,KAAK,QAAQ,IAAI;AACnC,QAAI,IAAI,KAAK,KAAK,KAAK,MAAO,QAAO;AACrC,WAAO,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAe;AACd,UAAM,SAAc,IAAI,MAAM,KAAK,KAAK;AACxC,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,KAAK;AACpC,aAAO,CAAC,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,QAAQ;AAAA,IACrD;AACA,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,QAAc;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,KAAK;AACpC,WAAK,KAAK,KAAK,OAAO,KAAK,KAAK,QAAQ,IAAI;AAAA,IAC7C;AACA,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACd;AACD;","names":[]}