@beehexa/hexasync-template-model 2608.20.18 → 2608.20.32
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/dist/componentKey.d.ts +26 -0
- package/dist/componentKey.d.ts.map +1 -0
- package/dist/componentKey.js +32 -0
- package/dist/componentKey.js.map +1 -0
- package/dist/connectorSupport.d.ts +123 -0
- package/dist/connectorSupport.d.ts.map +1 -0
- package/dist/connectorSupport.js +116 -0
- package/dist/connectorSupport.js.map +1 -0
- package/dist/contract.d.ts +57 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +68 -0
- package/dist/contract.js.map +1 -0
- package/dist/flowRender.d.ts +89 -0
- package/dist/flowRender.d.ts.map +1 -0
- package/dist/flowRender.js +316 -0
- package/dist/flowRender.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/nodeAddress.d.ts +105 -0
- package/dist/nodeAddress.d.ts.map +1 -0
- package/dist/nodeAddress.js +195 -0
- package/dist/nodeAddress.js.map +1 -0
- package/dist/references.d.ts +200 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +368 -0
- package/dist/references.js.map +1 -0
- package/dist/stepGlyph.d.ts +67 -0
- package/dist/stepGlyph.d.ts.map +1 -0
- package/dist/stepGlyph.js +155 -0
- package/dist/stepGlyph.js.map +1 -0
- package/dist/templating.d.ts +88 -0
- package/dist/templating.d.ts.map +1 -0
- package/dist/templating.js +103 -0
- package/dist/templating.js.map +1 -0
- package/dist/uriPath.d.ts +43 -0
- package/dist/uriPath.d.ts.map +1 -0
- package/dist/uriPath.js +151 -0
- package/dist/uriPath.js.map +1 -0
- 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, '<')
|
|
77
|
+
.replace(/>/g, '>')
|
|
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 & 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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwElD;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,KAAK;IACL,OAAO;IACP,UAAU;IACV,OAAO;IACP,OAAO;IACP,UAAU;IACV,WAAW;IACX,OAAO;IACP,WAAW;CACZ,CAAC,CAAC;AAEH,mEAAmE;AACnE,MAAM,iBAAiB,GAAG,CAAC,SAAwB,EAAU,EAAE,CAC7D,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK;SACT,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,SAAS,CAAC,KAAa,EAAE,QAAgB;IAChD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,OAAO,CAAC;IACnC,qGAAqG;IACrG,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9C,OAAO,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC;AACxD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,WAAW,CAAC,KAAyB;IAC5C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,mGAAmG;IACnG,OAAO,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QACxC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC;QACvC,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,iDAAiD;AACjD,SAAS,QAAQ,CAAC,IAAgB;IAChC,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,wFAAwF;IACxF,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1D,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;IAC7D,OAAO,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;AACjC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAgB;IAChC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC;;;;;OAKG;IACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtE,OAAO,KAAK,KAAK,EAAE;QACjB,CAAC,CAAC,OAAO,IAAI,QAAQ,EAAE,EAAE;QACzB,CAAC,CAAC,OAAO,IAAI,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,OAAe,EAAE,KAAa;IAC/C,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,OAAO,WAAW,cAAc,CAAC,OAAO,CAAC,WAAW,KAAK,oBAAoB,IAAI,EAAE,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,MAA8B,EAC9B,KAA4B,EAC5B,IAAI,GAAkB,EAAE;IAExB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACxD,MAAM,KAAK,GAAa,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO;YACL,GAAG,KAAK;YACR,cAAc,SAAS,CAAC,IAAI,CAAC,UAAU,IAAI,UAAU,EAAE,UAAU,CAAC,IAAI;SACvE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAQ,EAAE;QAClC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,UAAU,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CACR,cAAc,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CACzE,CAAC;YACF,gFAAgF;YAChF,KAAK,CAAC,IAAI,CAAC,iBAAiB,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YACrB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,UAAU,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,6GAA6G;QAC7G,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAS;QAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH;;;;;;;;;OASG;IACH,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC;;;;;;WAMG;QACH,IACE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACjD,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EACnD,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,cAAc,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;QAChE,IAAI,CACF,WAAW,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,CAChF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC9D,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;gBAC9C,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QACD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBAC5C,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QACD;;;WAGG;QACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;YACxB,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;YAC5B,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;SAC3B,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAC5C,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAChC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClB,KAAK,IAAI,CAAC,CAAC;YACX,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YACnE,MAAM,KAAK,GACT,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;gBACzC,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,cAAc,CAAC;YACrB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,eAAe,KAAK,WAAW,KAAK,mBAAmB,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,MAA8B,EAC9B,KAA4B,EAC5B,IAAI,GAAkB,EAAE;IAExB,OAAO;QACL;;;;;;;WAOG;QACH,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC9C,EAAE;QACF,YAAY;QACZ,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC;QAClC,KAAK;QACL,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|