@beehexa/hexasync-template-model 2608.20.18 → 2608.20.31

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 (41) hide show
  1. package/dist/componentKey.d.ts +26 -0
  2. package/dist/componentKey.d.ts.map +1 -0
  3. package/dist/componentKey.js +32 -0
  4. package/dist/componentKey.js.map +1 -0
  5. package/dist/connectorSupport.d.ts +123 -0
  6. package/dist/connectorSupport.d.ts.map +1 -0
  7. package/dist/connectorSupport.js +116 -0
  8. package/dist/connectorSupport.js.map +1 -0
  9. package/dist/contract.d.ts +57 -0
  10. package/dist/contract.d.ts.map +1 -0
  11. package/dist/contract.js +68 -0
  12. package/dist/contract.js.map +1 -0
  13. package/dist/flowRender.d.ts +89 -0
  14. package/dist/flowRender.d.ts.map +1 -0
  15. package/dist/flowRender.js +316 -0
  16. package/dist/flowRender.js.map +1 -0
  17. package/dist/index.d.ts +30 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +28 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/nodeAddress.d.ts +105 -0
  22. package/dist/nodeAddress.d.ts.map +1 -0
  23. package/dist/nodeAddress.js +195 -0
  24. package/dist/nodeAddress.js.map +1 -0
  25. package/dist/references.d.ts +200 -0
  26. package/dist/references.d.ts.map +1 -0
  27. package/dist/references.js +368 -0
  28. package/dist/references.js.map +1 -0
  29. package/dist/stepGlyph.d.ts +67 -0
  30. package/dist/stepGlyph.d.ts.map +1 -0
  31. package/dist/stepGlyph.js +155 -0
  32. package/dist/stepGlyph.js.map +1 -0
  33. package/dist/templating.d.ts +88 -0
  34. package/dist/templating.d.ts.map +1 -0
  35. package/dist/templating.js +103 -0
  36. package/dist/templating.js.map +1 -0
  37. package/dist/uriPath.d.ts +43 -0
  38. package/dist/uriPath.d.ts.map +1 -0
  39. package/dist/uriPath.js +151 -0
  40. package/dist/uriPath.js.map +1 -0
  41. package/package.json +1 -1
@@ -0,0 +1,316 @@
1
+ /**
2
+ * Mermaid and Markdown emission — the primitives both flow packages render through (Story 4.3).
3
+ *
4
+ * ### Why this is in `model` rather than a package of its own
5
+ *
6
+ * `PACKAGE-CONTRACT.md` §5 says the renderers are *"exported from both flow packages over the shared model"*, and
7
+ * AD-21 forbids those two packages importing each other — so the shared half cannot live in either. A package of its
8
+ * own would make both flow packages depend on it, contradicting Story 4.1 Task 1's *"zero runtime dependencies beyond
9
+ * `hexasync-template-model`"*.
10
+ *
11
+ * It belongs here on its own merits: `renderedNodeId` — the `:` → `__` projection every diagram id goes through — is
12
+ * already in this package and is already half a renderer. The address algebra and the emission algebra are one
13
+ * subject.
14
+ *
15
+ * ### What each rule below cost to learn
16
+ *
17
+ * **1. Every subgraph emits its OWN direction.** Mermaid ignores the parent chart's direction inside a subgraph, so a
18
+ * `TD` chart with `LR` stages needs the statement repeated per subgraph. (`PACKAGE-CONTRACT.md` §5 rule 1.)
19
+ *
20
+ * **2. Styling is PER ELEMENT — `style` and `linkStyle`, not `class`/`classDef`.** dashboard's own comment is the
21
+ * evidence: *"`classDef` did NOT reliably apply to node shapes in v11 — edges highlighted but nodes/diamonds did
22
+ * not."* A class-based overlay silently highlights the arrows and leaves the boxes plain.
23
+ *
24
+ * **3. …with ONE exception, and it is not a contradiction.** The VS Code extension uses `classDef` successfully — for
25
+ * `stroke-width` only, never a fill — precisely so the **webview's stylesheet** can colour it from theme variables. A
26
+ * literal colour would be wrong in one of light or dark. So: per-element `style` for anything carrying a COLOUR (which
27
+ * the caller supplies), `classDef` for a shape hint a stylesheet should own. Both are offered; neither is guessed.
28
+ *
29
+ * **4. A `classDef` inside a `subgraph` is a PARSE ERROR in mermaid 11**, which is why class declarations are hoisted
30
+ * to the end of the chart rather than emitted beside the nodes they name.
31
+ *
32
+ * **5. A colour is VALIDATED, and an unusable one drops the highlight rather than the chart.** Measured with the real
33
+ * mermaid 11 parser: `#hex` and a bare identifier (`red`) parse; `rgba(…)`, `rgb(…)`, `hsl(…)` and `var(--x)` are
34
+ * **parse errors** in `style` and `linkStyle` alike. dashboard's comment — ported here verbatim at first — said such
35
+ * colours *"fall back to a stroke-only highlight"*, and that was false in both directions: a named colour never broke
36
+ * anything, and an `rgba` did not degrade, it destroyed the diagram. A fill tint still needs exactly `#rrggbb`,
37
+ * because the tint is 8-digit-hex alpha and has nothing to append to otherwise.
38
+ *
39
+ * **6. The same `(model, opts)` always produces the same string.** No clock, no randomness, no ambient state — the
40
+ * golden-diagram suite depends on it (AD-29), which is also why the overlay is an ARGUMENT and never state.
41
+ */
42
+ import { renderedNodeId } from './nodeAddress.js';
43
+ /**
44
+ * Words mermaid's flowchart grammar owns. A node id or class name spelled as one is a parse error.
45
+ *
46
+ * Verified against mermaid 11 by the Story 4.3 review: `end`, `graph`, `subgraph`, `style` and `class` each break the
47
+ * parse, while `direction`, `o`, `x` and `0` do not — so this is the measured set rather than a cautious guess.
48
+ */
49
+ const MERMAID_RESERVED = new Set([
50
+ 'end',
51
+ 'graph',
52
+ 'subgraph',
53
+ 'style',
54
+ 'class',
55
+ 'classdef',
56
+ 'linkstyle',
57
+ 'click',
58
+ 'flowchart',
59
+ ]);
60
+ /** Mermaid's own spelling: a chart is `TD`, a subgraph is `TB`. */
61
+ const subgraphDirection = (direction) => direction === 'TD' ? 'TB' : 'LR';
62
+ /**
63
+ * A label, safe inside `["…"]`.
64
+ *
65
+ * ⚠️ Escaping lives HERE, and Story 4.2's review is why it is written down: the frontend port moved escaping out of
66
+ * the model layer without recording that it had moved, and **4 real labels carry a raw newline**
67
+ * (`ShoplinePublicApp.yaml`). A renderer that forgets breaks a real connector's diagram.
68
+ *
69
+ * The `&` replacement comes FIRST, or the entities the later rules produce would themselves be re-escaped.
70
+ */
71
+ export function escapeLabel(value) {
72
+ return value
73
+ .replace(/[\r\n]+/g, ' ')
74
+ .replace(/&/g, '&')
75
+ .replace(/"/g, '"')
76
+ .replace(/</g, '&lt;')
77
+ .replace(/>/g, '&gt;')
78
+ .trim();
79
+ }
80
+ /**
81
+ * A label guaranteed non-empty — because an empty one is a **mermaid parse error that kills the whole diagram**.
82
+ *
83
+ * ⛔ Story 4.3 review, CRITICAL-1, found with the real mermaid 11 parser. `escapeLabel` ends in `.trim()`, so a label
84
+ * that is non-empty in the model can become `''`, and `["${''}"]` is rejected outright: *"Expecting …, got
85
+ * 'STADIUMEND'"*. Not one blank node — **no chart at all**.
86
+ *
87
+ * Four reachable inputs, each verified end to end through the real builders: `if: ""` on an IF step (the route graph
88
+ * maps it to the label `''`, since only `null`/`undefined` become `'?'`), `next: ' '`, `next: '\n'`, and a SWITCH
89
+ * whose case key is `' '`. One keystroke of YAML.
90
+ *
91
+ * A regression relative to the authorities rather than a ported flaw: neither dashboard's nor the CLI's `escapeLabel`
92
+ * trims, so neither can manufacture an empty label.
93
+ */
94
+ function safeLabel(value, fallback) {
95
+ const escaped = escapeLabel(value);
96
+ if (escaped !== '')
97
+ return escaped;
98
+ // The fallback is escaped too, and if THAT is empty the node still needs something a reader can see.
99
+ const escapedFallback = escapeLabel(fallback);
100
+ return escapedFallback === '' ? '?' : escapedFallback;
101
+ }
102
+ /**
103
+ * A colour mermaid's grammar accepts in a `style` / `linkStyle` declaration.
104
+ *
105
+ * ⛔ Story 4.3 review, CRITICAL-2. Rule 5 below used to claim a non-hex colour *"falls back to a stroke-only
106
+ * highlight, which is still clearly visible"*. Measured against the real parser, that is false in **both**
107
+ * directions: a bare identifier like `red` parses fine (so withholding its fill achieved nothing), while
108
+ * `rgba(255,0,0,.5)`, `rgb(…)`, `hsl(…)` and `var(--x)` are **parse errors** — in `style` AND in `linkStyle`, which
109
+ * had no guard at all. So the documented safety net did not exist, and the chart died instead of degrading.
110
+ *
111
+ * It matters more here than in the Vue caller it was ported from: this is a published library whose contract invites
112
+ * the caller to supply a colour, and a theme token (`var(--vscode-focusBorder)`, an `rgba` from a palette) is the most
113
+ * likely thing a webview or dashboard reaches for.
114
+ *
115
+ * So an unusable colour drops the whole highlight rather than emitting a declaration that cannot parse.
116
+ */
117
+ function usableColor(color) {
118
+ if (color === undefined)
119
+ return undefined;
120
+ const trimmed = color.trim();
121
+ // `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, or a bare identifier — the two forms the grammar takes.
122
+ return /^#[0-9a-fA-F]{3,8}$/.test(trimmed) ||
123
+ /^[A-Za-z][A-Za-z0-9-]*$/.test(trimmed)
124
+ ? trimmed
125
+ : undefined;
126
+ }
127
+ /** One node line, shaped by what the node is. */
128
+ function nodeLine(node) {
129
+ const id = renderedNodeId(node.address);
130
+ // The address is the fallback: never empty, and it names the node a reader can look up.
131
+ const label = safeLabel(node.label, node.address);
132
+ if (node.decides === true)
133
+ return ` ${id}{"${label}"}`;
134
+ if (node.terminal === true)
135
+ return ` ${id}(["${label}"])`;
136
+ return ` ${id}["${label}"]`;
137
+ }
138
+ function edgeLine(edge) {
139
+ const from = renderedNodeId(edge.from);
140
+ const to = renderedNodeId(edge.to);
141
+ /**
142
+ * Emptiness is tested on the ESCAPED value, not the raw one (CRITICAL-1).
143
+ *
144
+ * The guard used to read the raw label and then emit the escaped one, so `label: ' '` took the labelled branch and
145
+ * emitted `-->|""|` — a parse error. An unlabelled arrow is the right answer for a label that escapes to nothing.
146
+ */
147
+ const label = edge.label === undefined ? '' : escapeLabel(edge.label);
148
+ return label === ''
149
+ ? ` ${from} --> ${to}`
150
+ : ` ${from} -->|"${label}"| ${to}`;
151
+ }
152
+ /**
153
+ * A per-element node style: a strong border, plus a fill tint only when the colour admits one.
154
+ *
155
+ * The fill is 8-digit-hex alpha, so it needs exactly 6 hex digits to append to — which is the REAL reason a named
156
+ * colour gets no fill. (Rule 5's comma story is true of `rgba(…)` and was never true of `red`; the caller's colour is
157
+ * validated by `usableColor` before it reaches here, so the comma case can no longer arrive at all.)
158
+ */
159
+ function nodeStyle(address, color) {
160
+ const fill = /^#[0-9a-fA-F]{6}$/.test(color) ? `,fill:${color}24` : '';
161
+ return ` style ${renderedNodeId(address)} stroke:${color},stroke-width:3px${fill}`;
162
+ }
163
+ /**
164
+ * The diagram.
165
+ *
166
+ * Deterministic for a given `(groups, edges, opts)`: every list is emitted in the order given, duplicates are
167
+ * collapsed by first appearance, and nothing consults the clock or the environment.
168
+ */
169
+ export function renderMermaid(groups, edges, opts = {}) {
170
+ const direction = opts.direction ?? 'TD';
171
+ const multiStage = opts.multiStage ?? groups.length > 1;
172
+ const lines = [`flowchart ${direction}`];
173
+ /**
174
+ * Nothing to draw ⇒ SAY SO (Story 4.3 review, MED-1 / MEDIUM-3).
175
+ *
176
+ * A bare `flowchart TD` parses and renders a blank box, and a titled Markdown section wrapping one is
177
+ * indistinguishable from a failure. Measured against `epic-4-ground-truth.md`: the shipped renderer had invented a
178
+ * fourth answer where the note says one of three must be chosen.
179
+ */
180
+ if (groups.every((group) => group.nodes.length === 0)) {
181
+ return [
182
+ ...lines,
183
+ ` empty["${safeLabel(opts.emptyLabel ?? 'No steps', 'No steps')}"]`,
184
+ ].join('\n');
185
+ }
186
+ const emitted = new Set();
187
+ const push = (line) => {
188
+ if (emitted.has(line))
189
+ return;
190
+ emitted.add(line);
191
+ lines.push(line);
192
+ };
193
+ const drawn = new Set();
194
+ for (const group of groups) {
195
+ if (multiStage && group.title !== undefined) {
196
+ lines.push(` subgraph ${renderedNodeId(group.key)}["${escapeLabel(group.title)}"]`);
197
+ // Rule 1: its OWN direction, because the parent's is ignored inside a subgraph.
198
+ lines.push(` direction ${subgraphDirection(direction)}`);
199
+ }
200
+ for (const node of group.nodes) {
201
+ push(nodeLine(node));
202
+ drawn.add(node.address);
203
+ }
204
+ if (multiStage && group.title !== undefined)
205
+ lines.push(' end');
206
+ }
207
+ for (const edge of edges) {
208
+ // An edge naming a node no group drew would render mermaid's own placeholder box, silently inventing a node.
209
+ if (!drawn.has(edge.from) || !drawn.has(edge.to))
210
+ continue;
211
+ push(edgeLine(edge));
212
+ }
213
+ /**
214
+ * The overlay — per element, and AFTER the nodes so a style statement always names something already drawn.
215
+ *
216
+ * `errored` is applied second deliberately: a node that both ran and failed should read as failed.
217
+ */
218
+ /**
219
+ * Class declarations come BEFORE the overlay (Story 4.3 review, MED-4).
220
+ *
221
+ * The commit claimed *"a chart rendered with an overlay still begins with the chart rendered without one"* — true
222
+ * only while `shapeClasses` was absent, because the class block was emitted after the overlay and so shifted when an
223
+ * overlay appeared. Classes first makes the overlay genuinely the last thing in the file, so the additive property
224
+ * holds for every combination rather than the subset the tests happened to cover.
225
+ *
226
+ * Still hoisted out of every subgraph, which is what rule 4 is about, and still declared once per class name.
227
+ */
228
+ for (const shapeClass of opts.shapeClasses ?? []) {
229
+ const members = shapeClass.addresses.filter((a) => drawn.has(a));
230
+ if (members.length === 0)
231
+ continue;
232
+ /**
233
+ * The class NAME reaches mermaid verbatim, so a space or a RESERVED WORD is a parse error (review LOW). Refused
234
+ * rather than emitted, because one bad class name would cost the whole chart rather than one style.
235
+ *
236
+ * `end` is the one a caller would plausibly reach for — a terminal-node class — and it is exactly the word that
237
+ * closes a subgraph.
238
+ */
239
+ if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(shapeClass.name) ||
240
+ MERMAID_RESERVED.has(shapeClass.name.toLowerCase())) {
241
+ continue;
242
+ }
243
+ push(` classDef ${shapeClass.name} ${shapeClass.declaration}`);
244
+ push(` class ${members.map((a) => renderedNodeId(a)).join(',')} ${shapeClass.name}`);
245
+ }
246
+ const overlay = opts.overlay;
247
+ if (overlay) {
248
+ const traversedColor = usableColor(overlay.colors?.traversed);
249
+ const erroredColor = usableColor(overlay.colors?.errored);
250
+ if (traversedColor !== undefined) {
251
+ for (const address of overlay.traversed ?? []) {
252
+ if (drawn.has(address))
253
+ push(nodeStyle(address, traversedColor));
254
+ }
255
+ }
256
+ if (erroredColor !== undefined) {
257
+ for (const address of overlay.errored ?? []) {
258
+ if (drawn.has(address))
259
+ push(nodeStyle(address, erroredColor));
260
+ }
261
+ }
262
+ /**
263
+ * Edges are styled by INDEX (`linkStyle 3 …`), which is why the index has to be the one mermaid will assign — the
264
+ * position of the edge among those actually emitted, not among those the model holds.
265
+ */
266
+ const highlight = new Set([
267
+ ...(overlay.traversed ?? []),
268
+ ...(overlay.errored ?? []),
269
+ ]);
270
+ const drawnEdges = edges.filter((e) => drawn.has(e.from) && drawn.has(e.to));
271
+ const seenEdge = new Set();
272
+ let index = -1;
273
+ for (const edge of drawnEdges) {
274
+ const key = edgeLine(edge);
275
+ if (seenEdge.has(key))
276
+ continue;
277
+ seenEdge.add(key);
278
+ index += 1;
279
+ if (!highlight.has(edge.from) || !highlight.has(edge.to))
280
+ continue;
281
+ const color = (overlay.errored ?? []).includes(edge.to) ||
282
+ (overlay.errored ?? []).includes(edge.from)
283
+ ? erroredColor
284
+ : traversedColor;
285
+ if (color !== undefined) {
286
+ push(` linkStyle ${index} stroke:${color},stroke-width:3px`);
287
+ }
288
+ }
289
+ }
290
+ return lines.join('\n');
291
+ }
292
+ /**
293
+ * A titled section with a fenced diagram, and nothing else (rule 3).
294
+ *
295
+ * What the composition report embeds and what an MCP resource serves — the same string, because two surfaces
296
+ * describing one flow disagreeing is the defect this epic exists to remove.
297
+ */
298
+ export function renderMarkdown(title, groups, edges, opts = {}) {
299
+ return [
300
+ /**
301
+ * The title is COLLAPSED, not HTML-escaped (Story 4.3 review, MEDIUM-4).
302
+ *
303
+ * A newline would end the heading and turn the diagram into body text, so collapsing is required. Entity-escaping
304
+ * is not: §5 says this string is what an MCP resource and the composition report both serve, and served as text
305
+ * `Orders &amp; Returns` reads as visible noise. Only an HTML consumer would decode it, and a heading is not a
306
+ * mermaid label.
307
+ */
308
+ `### ${title.replace(/[\r\n]+/g, ' ').trim()}`,
309
+ '',
310
+ '```mermaid',
311
+ renderMermaid(groups, edges, opts),
312
+ '```',
313
+ '',
314
+ ].join('\n');
315
+ }
316
+ //# sourceMappingURL=flowRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowRender.js","sourceRoot":"","sources":["../src/flowRender.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export { normalizeUri, joinUri, dirnameUri, basenameUri, resolveUri, relativeUri, isAbsoluteUri, isInsideUri, } from './uriPath.js';
2
+ export { normalizeComponentKey } from './componentKey.js';
3
+ export { ADDRESS_SEPARATOR, RENDERED_SEPARATOR, keySegment, identitySegment, entrySegment, nodeAddress, renderedNodeId, addressSegments, addressMatches, addressForRenderedId, type AddressSegment, } from './nodeAddress.js';
4
+ /**
5
+ * A token rename applied to an inherited component (`replacements` on an external).
6
+ *
7
+ * Moved here from `apps/cli/src/helpers/@types` in Story 1.2: it is part of the composer's
8
+ * domain vocabulary, and leaving it in the binary would have made every relocated core module
9
+ * depend on the app — the exact direction AD-3 forbids.
10
+ */
11
+ export interface IExternalReplacement {
12
+ fromKey: string;
13
+ toKey: string;
14
+ value: string | number | null;
15
+ }
16
+ export { COMPOSE_CONTRACT_VERSION, compareComposeContract, type ContractComparison, } from './contract.js';
17
+ export { classifyTemplating, hasComposeTimeTemplating, composeTimeKeys, type TemplatingLayer, type RuntimeReference, type TemplateOccurrence, } from './templating.js';
18
+ /**
19
+ * Which properties name another component (Phase 2 Story 1.2).
20
+ *
21
+ * Lives in `template-model` rather than in the index because reference kinds are domain VOCABULARY,
22
+ * not index machinery: the validation rules need them as much as the graph does, and a registry
23
+ * reachable from only one of the two surfaces is how a rule gets wired into the CLI and forgotten in
24
+ * the editor (FR-54, counter-metric C3). `template-model` is the base package both already depend on.
25
+ */
26
+ export * from './references.js';
27
+ export * from './connectorSupport.js';
28
+ export { renderMermaid as renderFlowMermaid, renderMarkdown as renderFlowMarkdown, escapeLabel, type RenderNode, type RenderEdge, type RenderGroup, type RenderOptions, type RenderOverlay, type FlowDirection, } from './flowRender.js';
29
+ export { composeNodeLabel, glyphOfStepType, familyOfStepType, } from './stepGlyph.js';
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAI1D,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,kBAAkB,GACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,cAAc,iBAAiB,CAAC;AAEhC,cAAc,uBAAuB,CAAC;AAItC,OAAO,EACL,aAAa,IAAI,iBAAiB,EAClC,cAAc,IAAI,kBAAkB,EACpC,WAAW,EACX,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ // Domain types for HexaSync templates, and the URI path algebra the whole system shares.
2
+ //
3
+ // The algebra lives in core because AD-18 requires ONE canonical identity: if each adapter
4
+ // canonicalized paths its own way, the Node host and the web host could disagree about whether
5
+ // two references point at the same file, and cycle detection and diamond dedupe would silently
6
+ // differ between them.
7
+ export { normalizeUri, joinUri, dirnameUri, basenameUri, resolveUri, relativeUri, isAbsoluteUri, isInsideUri, } from './uriPath.js';
8
+ export { normalizeComponentKey } from './componentKey.js';
9
+ // AD-33 — a node is addressed by its path. One scheme for the diagram click target, the provenance anchor and an
10
+ // MCP citation, which is why it is here and not in a flow package.
11
+ export { ADDRESS_SEPARATOR, RENDERED_SEPARATOR, keySegment, identitySegment, entrySegment, nodeAddress, renderedNodeId, addressSegments, addressMatches, addressForRenderedId, } from './nodeAddress.js';
12
+ export { COMPOSE_CONTRACT_VERSION, compareComposeContract, } from './contract.js';
13
+ export { classifyTemplating, hasComposeTimeTemplating, composeTimeKeys, } from './templating.js';
14
+ /**
15
+ * Which properties name another component (Phase 2 Story 1.2).
16
+ *
17
+ * Lives in `template-model` rather than in the index because reference kinds are domain VOCABULARY,
18
+ * not index machinery: the validation rules need them as much as the graph does, and a registry
19
+ * reachable from only one of the two surfaces is how a rule gets wired into the CLI and forgotten in
20
+ * the editor (FR-54, counter-metric C3). `template-model` is the base package both already depend on.
21
+ */
22
+ export * from './references.js';
23
+ export * from './connectorSupport.js';
24
+ // Story 4.3 — the emission algebra, beside the address algebra it shares a subject with. Both flow packages render
25
+ // through these, which is how "one renderer set" holds without them importing each other (AD-21).
26
+ export { renderMermaid as renderFlowMermaid, renderMarkdown as renderFlowMarkdown, escapeLabel, } from './flowRender.js';
27
+ export { composeNodeLabel, glyphOfStepType, familyOfStepType, } from './stepGlyph.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,EAAE;AACF,2FAA2F;AAC3F,+FAA+F;AAC/F,+FAA+F;AAC/F,uBAAuB;AACvB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,iHAAiH;AACjH,mEAAmE;AACnE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,oBAAoB,GAErB,MAAM,kBAAkB,CAAC;AAe1B,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GAEvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,GAIhB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,cAAc,iBAAiB,CAAC;AAEhC,cAAc,uBAAuB,CAAC;AAEtC,mHAAmH;AACnH,kGAAkG;AAClG,OAAO,EACL,aAAa,IAAI,iBAAiB,EAClC,cAAc,IAAI,kBAAkB,EACpC,WAAW,GAOZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,105 @@
1
+ /** The separator between address segments. Measured absent from all 2,144+ authored keys. */
2
+ export declare const ADDRESS_SEPARATOR = ":";
3
+ /** What a `:` becomes when rendered into a mermaid id, which admits only `[A-Za-z0-9_]`. */
4
+ export declare const RENDERED_SEPARATOR = "__";
5
+ /**
6
+ * One step along a path.
7
+ *
8
+ * `kind` is what makes the segment self-describing, which is why an address can be read by a human and matched by a
9
+ * machine without a side map — the thing dashboard's word-boundary regex and the extension's `MermaidFlow.steps`
10
+ * payload both existed to supply.
11
+ */
12
+ export type AddressSegment =
13
+ /** A document key at that level: `pullers`, `pullSteps`, `metrics`, `next`, `if`. */
14
+ {
15
+ readonly kind: 'key';
16
+ readonly name: string;
17
+ }
18
+ /** A component carrying an `id` (AD-33 rule 2) → `id_<value>`. */
19
+ | {
20
+ readonly kind: 'id';
21
+ readonly value: string;
22
+ }
23
+ /** A component with no `id` but a `key` (rule 3) → `key_<value>`. */
24
+ | {
25
+ readonly kind: 'componentKey';
26
+ readonly value: string;
27
+ }
28
+ /** A dictionary tail, named by the bare dictionary key (rule 5). */
29
+ | {
30
+ readonly kind: 'entry';
31
+ readonly value: string;
32
+ };
33
+ /** A key segment — `pullers`, `pullSteps`, `next`, `if`. */
34
+ export declare const keySegment: (name: string) => AddressSegment;
35
+ /**
36
+ * An identity segment, from a component's raw `id` or `key` value.
37
+ *
38
+ * ### `id_` carries the AUTHORED value, tokens and all
39
+ *
40
+ * Jazz's own example is `pullers:id_**LightspeedXSeriesPullerId**`, not the composed GUID. An address describes the
41
+ * **source**, and the authored form is identical across environments where a resolved GUID is not. It renders as
42
+ * `id___LightspeedXSeriesPullerId__`, which is ugly and harmless: nothing parses a rendered id for navigation,
43
+ * because the node index carries file, location and source text.
44
+ *
45
+ * Returns `undefined` for an absent identity, and for a value whose `!` marks it **removed** — a node the composer
46
+ * deletes has no address in the composed document, and minting one would be a citation to something that is not
47
+ * there.
48
+ */
49
+ export declare function identitySegment(raw: unknown, which: 'id' | 'key'): AddressSegment | undefined;
50
+ /** A dictionary tail, e.g. a metric facet's key. */
51
+ export declare function entrySegment(raw: unknown): AddressSegment | undefined;
52
+ /**
53
+ * The canonical address for a path.
54
+ *
55
+ * `undefined` segments are dropped rather than rendered as blanks, so a caller can pass
56
+ * `identitySegment(step.key, 'key')` without first checking it — a step with no key still gets the address of the
57
+ * stage that holds it, which is a true statement about a lesser-known node rather than an address with a hole in it.
58
+ *
59
+ * A segment whose TEXT is empty is dropped for the same reason, and this is the structural home of that rule (Story
60
+ * 4.6 review, LOW-1). `identitySegment` already refuses an empty id, but `keySegment('')` is a defined segment holding
61
+ * no text, so an empty `collection` or an empty base string produced `:creationSteps:key_FORM` — an address whose
62
+ * separator claims a level that was never there. That was first patched at one call site in `frontend-flow`; the class
63
+ * belongs here, where every caller gets it. Whitespace counts as empty: a segment of spaces is not a level either.
64
+ */
65
+ export declare function nodeAddress(segments: readonly (AddressSegment | undefined)[]): string;
66
+ /**
67
+ * The rendered form for a mermaid node id.
68
+ *
69
+ * Two steps, in this order: `:` → `__`, then sanitise anything still outside `[A-Za-z0-9_]`. Sanitising first would
70
+ * turn a stray character into `_` and make it indistinguishable from a separator.
71
+ */
72
+ export declare function renderedNodeId(address: string): string;
73
+ /** The segments of a canonical address, as text. */
74
+ export declare function addressSegments(address: string): readonly string[];
75
+ /**
76
+ * Does `address` name this node, or one inside it?
77
+ *
78
+ * **Whole-segment**, which is what makes AD-33's prefix-capture fix structural rather than a rule. The corpus has
79
+ * **924 pairs** of unique step keys where one prefixes another, and fixture 01 contains one directly:
80
+ * `SAVE_SALES_RETURN` and `SAVE_SALES_RETURN_DETAILS`, both named in one Scriban expression. As segments they are
81
+ * simply different, so `includes()`-style capture cannot happen — no word-boundary regex, no side payload map.
82
+ */
83
+ export declare function addressMatches(address: string, candidate: string): boolean;
84
+ /**
85
+ * The address, among those a caller already knows, that a rendered mermaid id refers to.
86
+ *
87
+ * ### There is deliberately NO reverse function, and the first draft of this module had one
88
+ *
89
+ * `addressOfRenderedId` looked reasonable and was unsound. It reversed `__` → `:` and accepted the result if it
90
+ * re-rendered to the same id — but that check proves round-trip *consistency*, not *uniqueness*, and the projection
91
+ * is genuinely many-to-one once sanitisation is involved. Its own test caught it: both
92
+ *
93
+ * ```
94
+ * pullers:id_**XPullerId**:pullSteps:key_GET_ORDERS:next:if ← the real address
95
+ * pullers:id:_XPullerId::pullSteps:key_GET_ORDERS:next:if ← a different node entirely
96
+ * ```
97
+ *
98
+ * render to `pullers__id___XPullerId____pullSteps__key_GET_ORDERS__next__if`. So it would have returned the second
99
+ * for a click on the first: precisely the wrong-node navigation its own docblock claimed to prevent.
100
+ *
101
+ * The direction that IS sound is forward-only, and it is all a consumer needs — Story 4.1 AC-4 puts the address on
102
+ * every node in the index, so a click handler always has the candidates in hand and never has to invert anything.
103
+ */
104
+ export declare function addressForRenderedId(rendered: string, known: readonly string[]): string | undefined;
105
+ //# sourceMappingURL=nodeAddress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeAddress.d.ts","sourceRoot":"","sources":["../src/nodeAddress.ts"],"names":[],"mappings":"AAuCA,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,MAAM,cAAc;AACxB,qFAAqF;AACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACjD,kEAAkE;GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACjD,qEAAqE;GACnE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC3D,oEAAoE;GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,4DAA4D;AAC5D,eAAO,MAAM,UAAU,SAAU,MAAM,KAAG,cAGxC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,GAAG,KAAK,GAClB,cAAc,GAAG,SAAS,CAQ5B;AAED,oDAAoD;AACpD,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAMrE;AAiCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,SAAS,CAAC,cAAc,GAAG,SAAS,CAAC,EAAE,GAChD,MAAM,CAMR;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAElE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAY1E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,GAAG,SAAS,CAMpB"}