@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.
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,368 @@
1
+ /**
2
+ * Which properties name another component — measured, not assumed (Stories 3.4 and 3.7).
3
+ *
4
+ * This list was originally guessed from what the collections are called, and the guess was wrong
5
+ * in both directions. It is now derived from the corpus: every `*Id` / `*Ids` property in nine
6
+ * real projects was resolved against the effective graph and kept only if its values are actually
7
+ * component ids. The measured figures are recorded here because a list like this decays silently
8
+ * — a property added next year will not announce itself — and the next person needs to know how
9
+ * to re-derive it rather than how to guess again.
10
+ *
11
+ * Resolution rates, measured over real projects (hits / occurrences):
12
+ *
13
+ * taskId 651/651 100% metricId 0/651 0%
14
+ * connectorId 413/413 100% providerId 0/27 0%
15
+ * connectionId 284/284 100% columnIds 0/11 0%
16
+ * entityId 115/115 100% credentialId 0/5 0%
17
+ * objectIds 90/90 100% profileId 0/5 0%
18
+ * targetId 59/59 100% systemId 0/4 0%
19
+ * fromConnectionId 54/54 100% integrationAppId 0/4 0%
20
+ * objectId 50/50 100% itemIds 0/3 0%
21
+ * object_id 13/13 100%
22
+ * pusherId 5/5 100%
23
+ * tableId 4/4 100%
24
+ * pullerId 2/2 100%
25
+ *
26
+ * Two findings worth stating plainly, because both contradict what was written down before:
27
+ *
28
+ * 1. **`taskId` is real, and is the most-used reference property in the corpus.** Story 3.7's AC
29
+ * calls it "the ideation document's illustrative `taskId`, which does not exist" — that is
30
+ * false. It appears 291 times in authored partials and resolves 651/651. The AC's underlying
31
+ * instruction — key these to REAL property names — is right, and following it is what turned
32
+ * up the error in its own example.
33
+ * 2. **`validationId`, `transformationId`, `pullerIds` and `pusherIds` were invented** from the
34
+ * collection names and have zero authored occurrences. Removed. `pullerId` was on the same
35
+ * guessed list but turned out to be real (2/2), so it is kept — on the measurement, not on
36
+ * the fact that a `pullers` collection exists.
37
+ *
38
+ * The values are often COMPOSE-TIME TOKENS — `taskId: "**Sapo_Orders_Task_Id**"` — and they
39
+ * resolve because the graph keys components in token form (Story 3.1). Keying on substituted
40
+ * values would have made every one of these references dangle.
41
+ */
42
+ /**
43
+ * CORRECTED 2026-08-02, and the correction is about METHOD, not about three names.
44
+ *
45
+ * The resolution rates in the table above were measured by asking *"is this value some
46
+ * component's id?"* — never *"does it point into the collection we claim?"*. Three consequences,
47
+ * each of which shipped:
48
+ *
49
+ * 1. **`connectionId` and `fromConnectionId` pointed at `connections`, a collection that does
50
+ * not exist.** Corpus-wide: **0** authored files declare `connections:`, **281** declare
51
+ * `connectors:`, and its ids are exactly the `**…ConnectionId**` tokens these properties
52
+ * hold. `connectionId`, `fromConnectionId` and `connectorId` are three spellings of one
53
+ * target: `connectors[*].id`. A method that only checked "is an id" scored the wrong
54
+ * collection at 100%.
55
+ * 2. **`entityId` and `targetId` have no fixed collection — it comes from a SIBLING.** Measured
56
+ * `entityType`: `SELF` 261 · `TASK` 118 · `PROFILE` 9. Measured `targetType`: `PULLER` 144 ·
57
+ * `SCHEDULER` 105 · `REPORT` 44 · `SCHEMA` 43. `entityType: SELF` means "this task" and
58
+ * carries no `entityId` at all. Absent, the type defaults to Task. A single `collection` field
59
+ * cannot express this, which is why both were left collection-less — and a collection-less
60
+ * entry matched a component in ANY collection and reported it resolved.
61
+ * 3. **They resolve only in `**Token**` form.** Authored value shapes: `entityId` 175 token /
62
+ * 1 raw UUID, `targetId` 151 / 0. The rule is not about volume — it is that the graph keys
63
+ * components in TOKEN form (FR-45), so a raw UUID cannot match a component however it is
64
+ * spelled. Reporting it as an unresolved reference would be noise; declining says the true
65
+ * thing, and is a different answer from "a reference that does not resolve".
66
+ *
67
+ * CORRECTED 2026-08-03. This first read "178 token-form vs 268 raw UUID … 437 legitimate
68
+ * authored values" — measured over a population that included GENERATED `output.yaml`, where
69
+ * compose has already substituted each token for the real id. The index never reads those
70
+ * files, so those values were never at risk. The mistake is the same one this whole note is
71
+ * about: a count that did not say precisely enough what it was counting.
72
+ *
73
+ * The lesson generalises: a reference is a property, a target collection AND a value shape. Any
74
+ * future re-derivation must assert all three, or it will score a wrong answer at 100% again.
75
+ */
76
+ /**
77
+ * Values that are `**Token**` form — the only shape a conditional reference resolves in.
78
+ *
79
+ * TRIMMED, as of the Epic 2 review. It was not, while a second copy of this predicate 350 lines below was — so
80
+ * a quoted `" **Token** "` was a token to one and a literal to the other. One definition, one answer.
81
+ */
82
+ const TOKEN_FORM = /^\*\*[^*]+\*\*$/;
83
+ export const isTokenForm = (value) => TOKEN_FORM.test(value.trim());
84
+ /** `entityType` → the collection an `entityId` beside it points into. */
85
+ const ENTITY_TYPE_TARGETS = new Map([
86
+ ['TASK', 'objects'],
87
+ // "this task" — the entity IS the enclosing one, so there is no id to resolve.
88
+ ['SELF', undefined],
89
+ // A profile is not a template collection; the id is resolved outside the project.
90
+ ['PROFILE', undefined],
91
+ ]);
92
+ /** `targetType` → the collection a `targetId` beside it points into. */
93
+ const TARGET_TYPE_TARGETS = new Map([
94
+ ['PULLER', 'pullers'],
95
+ ['REPORT', 'reports'],
96
+ ['SCHEMA', 'schemas'],
97
+ ['SCHEDULER', 'startupTasks'],
98
+ ]);
99
+ export const REFERENCE_PROPERTY_LIST = [
100
+ { property: 'taskId', collection: 'objects' },
101
+ { property: 'objectId', collection: 'objects' },
102
+ { property: 'object_id', collection: 'objects' },
103
+ { property: 'objectIds', collection: 'objects' },
104
+ { property: 'pusherId', collection: 'pushers' },
105
+ { property: 'pullerId', collection: 'pullers' },
106
+ { property: 'tableId', collection: 'tables' },
107
+ /**
108
+ * ADDED 2026-08-05, on measurement. A dependency names the Task it waits on with `dependedOn`.
109
+ *
110
+ * It was missing, and the omission was invisible because nothing asked for it: **910 authored
111
+ * occurrences across 665 files**, of which **271 of 272 (99.6%) resolve to a Task** when measured
112
+ * against composed graphs for all 33 buildable corpus projects. That is the same standard
113
+ * `NON_REFERENCE_ID_PROPERTIES` below applies in the other direction — a property measured at 0%
114
+ * resolution is not a reference, and one measured at 99.6% plainly is.
115
+ *
116
+ * The single miss is a REAL broken reference, in `001-projects/elly`: a `dependedOn` naming
117
+ * `**SapoProductPuller**`, a token that resolves to nothing and, by its name, aims at a puller
118
+ * where a Task belongs. Until now no validation, Find References or impact query could see it,
119
+ * because this row did not exist.
120
+ */
121
+ { property: 'dependedOn', collection: 'objects' },
122
+ // One target, three spellings. See the CORRECTED note above.
123
+ { property: 'connectionId', collection: 'connectors' },
124
+ { property: 'fromConnectionId', collection: 'connectors' },
125
+ // ...except on a `connectors[]` entry, where it is that connection's own platform identity rather
126
+ // than a reference to one. See `opaqueInCollections` on `ReferenceProperty`.
127
+ {
128
+ property: 'connectorId',
129
+ collection: 'connectors',
130
+ opaqueInCollections: ['connectors'],
131
+ },
132
+ {
133
+ property: 'entityId',
134
+ tokenFormOnly: true,
135
+ discriminator: {
136
+ siblings: ['entityType'],
137
+ byValue: ENTITY_TYPE_TARGETS,
138
+ fallback: 'objects',
139
+ },
140
+ },
141
+ {
142
+ property: 'targetId',
143
+ tokenFormOnly: true,
144
+ discriminator: {
145
+ // `targetType` decides; `entityType` is the fallback discriminator where the block carries
146
+ // one instead, and a Task is the default when neither is written.
147
+ siblings: ['targetType', 'entityType'],
148
+ byValue: new Map([...TARGET_TYPE_TARGETS, ...ENTITY_TYPE_TARGETS]),
149
+ fallback: 'objects',
150
+ },
151
+ },
152
+ ];
153
+ /**
154
+ * Resolve what a reference property means beside its siblings.
155
+ *
156
+ * Returns `undefined` when this property/value/context is NOT a component reference — a raw UUID
157
+ * in `entityId`, or `entityType: SELF`. That is a distinct answer from "a reference that does not
158
+ * resolve", and collapsing the two is what puts diagnostics on correct files.
159
+ */
160
+ export function resolveReferenceKind(property, value, siblings,
161
+ /**
162
+ * The collection whose entry this property sits inside — `connectors`, `pullers`, `objects`, … — as the
163
+ * walker already tracks it. Optional so existing callers keep compiling; supplying it is what lets a
164
+ * property mean one thing in a step argument and another on a component of its own collection (FR-47).
165
+ */
166
+ enclosingCollection) {
167
+ const entry = BY_NAME.get(property);
168
+ if (!entry)
169
+ return undefined;
170
+ if (entry.tokenFormOnly && !isTokenForm(value))
171
+ return undefined;
172
+ // Checked BEFORE the discriminator: position decides whether there is a reference at all, and only then
173
+ // does anything ask what it points into.
174
+ if (enclosingCollection !== undefined &&
175
+ entry.opaqueInCollections?.includes(enclosingCollection)) {
176
+ return undefined;
177
+ }
178
+ if (!entry.discriminator) {
179
+ return {
180
+ property,
181
+ ...(entry.collection ? { collection: entry.collection } : {}),
182
+ };
183
+ }
184
+ const { siblings: names, byValue, fallback } = entry.discriminator;
185
+ for (const name of names) {
186
+ const raw = siblings?.[name];
187
+ if (raw === undefined || raw === null)
188
+ continue;
189
+ const key = String(raw);
190
+ // `has` rather than `get`, because a MAPPED `undefined` ("`SELF` references nothing") and an
191
+ // UNMAPPED value ("a type nobody has measured yet") are different answers that both come back
192
+ // as `undefined` from `get`. Claiming a collection for an unknown type is how this registry
193
+ // was wrong the first time.
194
+ if (!byValue.has(key))
195
+ return undefined;
196
+ const collection = byValue.get(key);
197
+ // Present, measured, and not a component reference — `entityType: SELF`, `PROFILE`.
198
+ if (collection === undefined)
199
+ return undefined;
200
+ return { property, collection };
201
+ }
202
+ return { property, ...(fallback ? { collection: fallback } : {}) };
203
+ }
204
+ /** Fast membership test for the walk in `queries.ts`. */
205
+ export const REFERENCE_PROPERTIES = REFERENCE_PROPERTY_LIST.map((r) => r.property);
206
+ const BY_NAME = new Map(REFERENCE_PROPERTY_LIST.map((r) => [r.property, r]));
207
+ export const referencePropertyFor = (property) => BY_NAME.get(property);
208
+ /**
209
+ * `*Id` properties MEASURED at 0% resolution — not references, recorded so their absence reads
210
+ * as a decision rather than an oversight.
211
+ *
212
+ * They hold runtime UUIDs, environment tokens or payload field names. Without this list the next
213
+ * reader sees `metricId` missing from the set above and adds it, and every metric configuration
214
+ * in the corpus grows a dangling-reference diagnostic.
215
+ *
216
+ * Every entry here has a row in the table above. `templateId` and `reportId` were previously
217
+ * listed and have been REMOVED: they never occurred in the sampled projects at all, so "resolved
218
+ * 0%" was never true of them — no-occurrences is not the same measurement as never-resolves, and
219
+ * a list whose stated basis is measurement must not carry entries that were only assumed. They
220
+ * do appear elsewhere in the corpus (`reportId` ~91 authored occurrences), so they are left
221
+ * deliberately unclassified until someone measures them.
222
+ */
223
+ export const NON_REFERENCE_ID_PROPERTIES = [
224
+ 'metricId',
225
+ 'providerId',
226
+ 'columnIds',
227
+ 'systemId',
228
+ 'integrationAppId',
229
+ 'credentialId',
230
+ 'profileId',
231
+ 'itemIds',
232
+ ];
233
+ /**
234
+ * Blocks whose `id` names a component — the corpus's DOMINANT reference form.
235
+ *
236
+ * `objectAssociations` wires a Task to its entities like this:
237
+ *
238
+ * objectAssociations:
239
+ * "**Orders_Task_Id**":
240
+ * table: { id: "**Orders_Table_Id**" }
241
+ * puller: { id: "**Orders_Puller_Id**", resultKey: rows }
242
+ *
243
+ * Counted across the corpus's AUTHORED partials (`output.yaml` and `__configs` excluded):
244
+ *
245
+ * nested `table:` 1,575 flat `tableId:` 308
246
+ * nested `puller:` 1,695 flat `pullerId:` 38
247
+ * nested `pusher:` 912 flat `pusherId:` 48
248
+ * ----- ---
249
+ * 4,182 394
250
+ *
251
+ * The nested form outnumbers the flat one by roughly 10:1 — it is how the corpus wires a Task to
252
+ * its entities, and a registry built only on flat property names saw NONE of it. The flat form is
253
+ * a real minority, not noise, so both are supported.
254
+ *
255
+ * (An earlier draft of this comment said "4 / 2 / 5" and "three orders of magnitude". Those were
256
+ * the nine-project RESOLUTION sample from the table above, quoted under a corpus-wide heading —
257
+ * a different measurement of a different population. Corrected 2026-08-02.)
258
+ *
259
+ * The block carries more than the id (`resultKey`, for one), so the reference is the block's
260
+ * `id` specifically, reported as `table.id` rather than as `table`.
261
+ */
262
+ export const NESTED_REFERENCE_BLOCKS = [
263
+ { property: 'table', collection: 'tables' },
264
+ { property: 'puller', collection: 'pullers' },
265
+ { property: 'pusher', collection: 'pushers' },
266
+ ];
267
+ const NESTED_BY_NAME = new Map(NESTED_REFERENCE_BLOCKS.map((r) => [r.property, r]));
268
+ export const nestedReferenceBlockFor = (property) => NESTED_BY_NAME.get(property);
269
+ /**
270
+ * Collections whose component KEY is itself a reference into another collection.
271
+ *
272
+ * An `objectAssociations` entry is keyed BY the objectId it describes — that is what makes it
273
+ * that object's association rather than a component that merely shares its name. Modelling it
274
+ * matters twice: `getRelatedTask` can answer for an association, and renaming a Task has to
275
+ * carry the association key with it, which only shows up in a blast radius if the key is an edge.
276
+ */
277
+ export const COLLECTIONS_KEYED_BY_REFERENCE = new Map([
278
+ ['objectAssociations', 'objects'],
279
+ /**
280
+ * ADDED 2026-08-06, on a reported bug: a Task's transformations and validations were invisible.
281
+ *
282
+ * Both are keyed by the Task they belong to, exactly as an association is — the key IS the objectId, and
283
+ * the value is that Task's list:
284
+ *
285
+ * transformations:
286
+ * "**MisaAmisSapoWeb__Inventories_Task_Id**":
287
+ * - id: "**…_GetProductVariant_Transformation_Id**"
288
+ * type: SQL
289
+ *
290
+ * Without the key modelled as a reference there is no edge between the two, so nothing could answer
291
+ * "which transformations does this Task have". Probed on `001-projects/catafa/sapo-misa`: the graph held
292
+ * 2 transformation and 5 validation components, and the Task's incoming relations were the association
293
+ * alone. The components were there; the edge was not.
294
+ *
295
+ * It matters twice, as the association's entry says: a query can answer for a Task, and renaming a Task
296
+ * carries its transformations and validations with it — which only shows up in a blast radius if the key
297
+ * is an edge.
298
+ */
299
+ ['transformations', 'objects'],
300
+ ['validations', 'objects'],
301
+ ]);
302
+ /** The property name reported for a reference carried by a component's own key. */
303
+ export const KEY_REFERENCE_PROPERTY = '(key)';
304
+ /**
305
+ * The connector a connection names — `connectorId` first, `providerId` second (FR-1, AD-24).
306
+ *
307
+ * The read order exists in four places: `BaseStepExecutor` (untyped), `ConnectorDefinition.ResolvedConnectorId`
308
+ * (typed), `WebhookPartitioner` (via the accessor) and — found missing by the Epic 1 review — the CLI's task
309
+ * tooling. FR-1 says *every* runtime path, and the CLI reading only the legacy spelling meant a
310
+ * `connectorId`-only connection, exactly what FR-3's rename produces at scale, hard-stopped task generation
311
+ * with *"Connector undefined not found"*.
312
+ *
313
+ * Blank counts as absent, matching the untyped path: `Guid.Empty` has no equivalent here, but an empty string
314
+ * does, and a half-written `connectorId: ""` must not beat a real legacy value.
315
+ */
316
+ export function resolvedConnectorIdOf(connection) {
317
+ const usable = (value) => {
318
+ const text = typeof value === 'string'
319
+ ? value
320
+ : typeof value === 'number'
321
+ ? String(value)
322
+ : undefined;
323
+ if (text === undefined || text.trim() === '')
324
+ return undefined;
325
+ // All-zeros counts as absent, matching `ConnectorIdentity.IsDeclared` in C#. The Epic 1 review found the
326
+ // two sides disagreeing about exactly this literal.
327
+ return text.trim() === '00000000-0000-0000-0000-000000000000'
328
+ ? undefined
329
+ : text;
330
+ };
331
+ return usable(connection?.connectorId) ?? usable(connection?.providerId);
332
+ }
333
+ /**
334
+ * A connector identity that is written but cannot be used (FR-9, Story 2.1).
335
+ *
336
+ * "Well formed" means a GUID. Not a name, not a slug, not a URL — the platform's connector registry is keyed by
337
+ * GUID, so anything else cannot resolve however plausible it looks.
338
+ *
339
+ * ⛔ ONE definition, deliberately. The same rule is expressed as a `pattern` in the shipped connection schema
340
+ * and as `ConnectorIdentity` in C#, and Epic 1's review found what happens when a rule this small gets written
341
+ * three times: the copies disagreed about an all-zeros GUID and nobody noticed, because the disagreeing input
342
+ * was the one case no suite covered. The schema, the rule and the runtime must answer the same question the
343
+ * same way.
344
+ *
345
+ * A compose-time TOKEN is not judged here. In composed output an unresolved `**Token**` means the VARIABLE
346
+ * failed to resolve, which `VAR-1` already reports — and two findings for one cause is how a Problems panel
347
+ * stops being read.
348
+ */
349
+ const GUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
350
+ /**
351
+ * An identity that is STILL a token after composition — the variable failed, and `VAR-1` owns that.
352
+ *
353
+ * ⛔ A NAME for `isTokenForm`, not a second implementation. It shipped as a byte-identical copy of the regex
354
+ * 350 lines above its original, in the file whose own docstring says *"ONE definition, deliberately … Epic 1's
355
+ * review found what happens when a rule this small gets written three times."* Found by the Epic 2 review; kept
356
+ * as an alias rather than deleted because the two names say different things at their call sites — one asks
357
+ * "is this the shape a reference resolves in", the other "did substitution fail here".
358
+ */
359
+ export const isUnresolvedToken = isTokenForm;
360
+ export function isWellFormedConnectorIdentity(value) {
361
+ const trimmed = value.trim();
362
+ if (!GUID.test(trimmed))
363
+ return false;
364
+ // All-zeros is what an undeclared identity deserialises to on the typed side. It parses as a GUID and names
365
+ // no connector, so it is "absent" rather than "malformed" — `resolvedConnectorIdOf` already declines it.
366
+ return trimmed !== '00000000-0000-0000-0000-000000000000';
367
+ }
368
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAW,EAAE,CACpD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAmDhC,yEAAyE;AACzE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAA6B;IAC9D,CAAC,MAAM,EAAE,SAAS,CAAC;IACnB,+EAA+E;IAC/E,CAAC,MAAM,EAAE,SAAS,CAAC;IACnB,kFAAkF;IAClF,CAAC,SAAS,EAAE,SAAS,CAAC;CACvB,CAAC,CAAC;AAEH,wEAAwE;AACxE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAA6B;IAC9D,CAAC,QAAQ,EAAE,SAAS,CAAC;IACrB,CAAC,QAAQ,EAAE,SAAS,CAAC;IACrB,CAAC,QAAQ,EAAE,SAAS,CAAC;IACrB,CAAC,WAAW,EAAE,cAAc,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAiC;IACnE,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;IAC7C,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE;IAC/C,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE;IAChD,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE;IAChD,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE;IAC/C,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE;IAC/C,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;IAC7C;;;;;;;;;;;;;OAaG;IACH,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE;IACjD,6DAA6D;IAC7D,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE;IACtD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE;IAC1D,kGAAkG;IAClG,6EAA6E;IAC7E;QACE,QAAQ,EAAE,aAAa;QACvB,UAAU,EAAE,YAAY;QACxB,mBAAmB,EAAE,CAAC,YAAY,CAAC;KACpC;IACD;QACE,QAAQ,EAAE,UAAU;QACpB,aAAa,EAAE,IAAI;QACnB,aAAa,EAAE;YACb,QAAQ,EAAE,CAAC,YAAY,CAAC;YACxB,OAAO,EAAE,mBAAmB;YAC5B,QAAQ,EAAE,SAAS;SACpB;KACF;IACD;QACE,QAAQ,EAAE,UAAU;QACpB,aAAa,EAAE,IAAI;QACnB,aAAa,EAAE;YACb,2FAA2F;YAC3F,kEAAkE;YAClE,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;YACtC,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,CAAC,CAAC;YAClE,QAAQ,EAAE,SAAS;SACpB;KACF;CACF,CAAC;AAUF;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,KAAa,EACb,QAAkC;AAClC;;;;GAIG;AACH,mBAA4B;IAE5B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACjE,wGAAwG;IACxG,yCAAyC;IACzC,IACE,mBAAmB,KAAK,SAAS;QACjC,KAAK,CAAC,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,EACxD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QACzB,OAAO;YACL,QAAQ;YACR,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC;IACnE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,SAAS;QAChD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,6FAA6F;QAC7F,8FAA8F;QAC9F,4FAA4F;QAC5F,4BAA4B;QAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,oFAAoF;QACpF,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC/C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAC/B,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAgB,EACe,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC5D,UAAU;IACV,YAAY;IACZ,WAAW;IACX,UAAU;IACV,kBAAkB;IAClB,cAAc;IACd,WAAW;IACX,SAAS;CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAiC;IACnE,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE;IAC3C,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;IAC7C,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;CAC9C,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,GAAG,CAC5B,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CACpD,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,QAAgB,EACe,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEjE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,8BAA8B,GACzC,IAAI,GAAG,CAAC;IACN,CAAC,oBAAoB,EAAE,SAAS,CAAC;IACjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,CAAC,iBAAiB,EAAE,SAAS,CAAC;IAC9B,CAAC,aAAa,EAAE,SAAS,CAAC;CAC3B,CAAC,CAAC;AAEL,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,UACoE;IAEpE,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE;QAChC,MAAM,IAAI,GACR,OAAO,KAAK,KAAK,QAAQ;YACvB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;gBACzB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBACf,CAAC,CAAC,SAAS,CAAC;QAClB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,SAAS,CAAC;QAC/D,yGAAyG;QACzG,oDAAoD;QACpD,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,sCAAsC;YAC3D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,GACR,+EAA+E,CAAC;AAElF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,MAAM,UAAU,6BAA6B,CAAC,KAAa;IACzD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,4GAA4G;IAC5G,yGAAyG;IACzG,OAAO,OAAO,KAAK,sCAAsC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * A node's label: name, then key, then the step type — with a glyph standing in for an icon.
3
+ *
4
+ * ### What was wrong, and it was one line in each renderer
5
+ *
6
+ * Both `render.ts` files built a label as `node.label ?? node.name ?? node.stepKey ?? node.address` — a
7
+ * FALLBACK chain, so a step with a name showed its name and nothing else. The key and the type were computed,
8
+ * carried on every node, and then dropped at the last step before drawing. A reader looking at a diagram
9
+ * beside the YAML could not tell which `key:` a box was, which is the one thing they need in order to jump to
10
+ * it, and `next:`/`outputs:` reference steps BY KEY.
11
+ *
12
+ * The brainstorm that started this feature asked for exactly this: *"each node is missing its `key` and
13
+ * `type/displayType` … The key must be after the node's `name`, and the `type/displayType` must be shown as an
14
+ * icon in the node"*.
15
+ *
16
+ * ### Why a glyph and not the SVG set
17
+ *
18
+ * ⚠️ Stated rather than quietly downgraded. `ux/step-icons/` holds 12 authored SVGs, and they cannot go inside
19
+ * a mermaid node here: the webview renders with `securityLevel: 'strict'`, which sanitises label HTML through
20
+ * DOMPurify (`renderHtml.ts:493` records the same constraint for the report), and an inline `<svg>` does not
21
+ * survive that. Raising it to `'loose'` to admit one would also admit mermaid's `click … call fn()` — which is
22
+ * precisely why `flowDiagram.ts` chose strict.
23
+ *
24
+ * So the icon slot is filled by a per-FAMILY unicode glyph, which survives sanitising, needs no asset
25
+ * pipeline, and renders identically in the editor, the report and the browser host. The type name is drawn
26
+ * beside it, so the glyph is a hint and never the only signal — that is the "fallback to text", present
27
+ * always rather than only when something fails.
28
+ *
29
+ * Wiring the real SVG set belongs with the shared step-icon package the toolchain PRD lists under
30
+ * *"Unblocks"*, where a `<span class="step-icon step-icon--api">` and CSS can do it without loosening mermaid.
31
+ */
32
+ /**
33
+ * Which family a step type belongs to.
34
+ *
35
+ * Matched on the type name because that is what both runtimes carry — a worker step's `displayType` and a
36
+ * frontend step's `type` are the same idea spelled twice (AD-21 keeps the vocabularies apart, not the
37
+ * concept). Unknown types get the neutral glyph rather than no glyph, so a box never loses its icon slot and
38
+ * start shifting the text alignment of its neighbours.
39
+ */
40
+ export declare function familyOfStepType(type: string): string;
41
+ /**
42
+ * The glyph for a step type.
43
+ *
44
+ * Empty for a step with NO type — there is no icon to stand in for, and a placeholder would render as a
45
+ * second separator (`name · · KEY`), which is how this was caught.
46
+ */
47
+ export declare function glyphOfStepType(type: string | undefined): string;
48
+ /**
49
+ * The three lines a reader needs, in the order the brainstorm asked for: name, then key, then type.
50
+ *
51
+ * ⚠️ ONE LINE, not `<br/>`, and that was measured rather than assumed. The first version used `<br/>`; the
52
+ * shared renderer's `escapeLabel` turns `<` into `&lt;` — correctly, it is what stops an authored step name
53
+ * injecting markup — so mermaid received `&lt;br/&gt;` and would have drawn it as visible text in every box.
54
+ * Weakening `escapeLabel` to admit one tag would trade a real safety property for a cosmetic one.
55
+ *
56
+ * A junction (START/END) has its own label and no key or type — it returns unchanged, because decorating a
57
+ * terminal with an empty key line would put a blank row in every diagram.
58
+ */
59
+ export declare function composeNodeLabel(node: {
60
+ readonly label?: string;
61
+ readonly name?: string;
62
+ readonly stepKey?: string;
63
+ readonly address: string;
64
+ readonly type?: string;
65
+ readonly displayType?: string;
66
+ }): string;
67
+ //# sourceMappingURL=stepGlyph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepGlyph.d.ts","sourceRoot":"","sources":["../src/stepGlyph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA4CH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BrD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B,GAAG,MAAM,CAYT"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * A node's label: name, then key, then the step type — with a glyph standing in for an icon.
3
+ *
4
+ * ### What was wrong, and it was one line in each renderer
5
+ *
6
+ * Both `render.ts` files built a label as `node.label ?? node.name ?? node.stepKey ?? node.address` — a
7
+ * FALLBACK chain, so a step with a name showed its name and nothing else. The key and the type were computed,
8
+ * carried on every node, and then dropped at the last step before drawing. A reader looking at a diagram
9
+ * beside the YAML could not tell which `key:` a box was, which is the one thing they need in order to jump to
10
+ * it, and `next:`/`outputs:` reference steps BY KEY.
11
+ *
12
+ * The brainstorm that started this feature asked for exactly this: *"each node is missing its `key` and
13
+ * `type/displayType` … The key must be after the node's `name`, and the `type/displayType` must be shown as an
14
+ * icon in the node"*.
15
+ *
16
+ * ### Why a glyph and not the SVG set
17
+ *
18
+ * ⚠️ Stated rather than quietly downgraded. `ux/step-icons/` holds 12 authored SVGs, and they cannot go inside
19
+ * a mermaid node here: the webview renders with `securityLevel: 'strict'`, which sanitises label HTML through
20
+ * DOMPurify (`renderHtml.ts:493` records the same constraint for the report), and an inline `<svg>` does not
21
+ * survive that. Raising it to `'loose'` to admit one would also admit mermaid's `click … call fn()` — which is
22
+ * precisely why `flowDiagram.ts` chose strict.
23
+ *
24
+ * So the icon slot is filled by a per-FAMILY unicode glyph, which survives sanitising, needs no asset
25
+ * pipeline, and renders identically in the editor, the report and the browser host. The type name is drawn
26
+ * beside it, so the glyph is a hint and never the only signal — that is the "fallback to text", present
27
+ * always rather than only when something fails.
28
+ *
29
+ * Wiring the real SVG set belongs with the shared step-icon package the toolchain PRD lists under
30
+ * *"Unblocks"*, where a `<span class="step-icon step-icon--api">` and CSS can do it without loosening mermaid.
31
+ */
32
+ /**
33
+ * Families, taken from the authored icon set (`ux/step-icons/_family-*.svg`) so the two cannot diverge.
34
+ *
35
+ * ⚠️ EVERY glyph must come from Arrows (U+2190–U+21FF), Geometric Shapes (U+25A0–U+25FF) or Mathematical
36
+ * Operators (U+2200–U+22FF), and `stepGlyph.spec.ts` enforces it. Those three blocks have near-universal
37
+ * coverage in the fonts a webview actually gets; anything outside them draws as a tofu box on some machine,
38
+ * and a box is indistinguishable from "this node has no icon".
39
+ *
40
+ * Two of the first ten broke that rule and a reader saw both: *"why are some nodes have icons, but some are
41
+ * not?"*
42
+ *
43
+ * * `query` was `?` — a plain ASCII question mark. It has perfect coverage and reads as a MISSING
44
+ * CHARACTER, which is worse: the glyph rendered exactly as intended and still looked like a failure.
45
+ * * `control` was `⑂` (U+2442), in the Optical Character Recognition block. Rare enough that common fonts
46
+ * omit it, so it drew as a box.
47
+ *
48
+ * The lesson is that "does this codepoint exist" is the wrong question. The right one is "does it read as an
49
+ * icon on a machine I have never seen", and the answer is only reliable inside those three blocks.
50
+ */
51
+ const GLYPHS = {
52
+ /** An outbound request. */
53
+ call: '↗',
54
+ /** A branch. The diamond shape the flow already draws for a decision, in the label. */
55
+ control: '◆',
56
+ /** Fan-out — dispatch, loop, batch. */
57
+ orchestrate: '↻',
58
+ /** Rows read back. Was `?`, which read as a missing character. */
59
+ query: '≡',
60
+ /** Something remembered for the rest of the run. */
61
+ state: '▣',
62
+ /** A start or an end. */
63
+ terminal: '◉',
64
+ /** Shape in, different shape out. */
65
+ transform: '⇄',
66
+ /** A screen the operator sees. */
67
+ ui: '▤',
68
+ /** Time passing. */
69
+ wait: '◔',
70
+ /** Data pushed somewhere. */
71
+ write: '⇩',
72
+ };
73
+ /**
74
+ * Which family a step type belongs to.
75
+ *
76
+ * Matched on the type name because that is what both runtimes carry — a worker step's `displayType` and a
77
+ * frontend step's `type` are the same idea spelled twice (AD-21 keeps the vocabularies apart, not the
78
+ * concept). Unknown types get the neutral glyph rather than no glyph, so a box never loses its icon slot and
79
+ * start shifting the text alignment of its neighbours.
80
+ */
81
+ export function familyOfStepType(type) {
82
+ const t = type.toUpperCase();
83
+ if (/FORM|SHOW|SELECT|REDIRECT|BROWSER|MESSAGE|INFO/.test(t))
84
+ return 'ui';
85
+ if (/^API$|HTTP|REQUEST|WEBHOOK|CALL/.test(t))
86
+ return 'call';
87
+ /**
88
+ * WAIT before everything else that could claim it.
89
+ *
90
+ * `SLEEP` is a real corpus type (`MisaAmisCustomerCallbackMessagePusher.yaml` carries one) and the authored
91
+ * set drew it its own clock. Ahead of `query` because `POLL` contains no query word but reads as one, and
92
+ * ahead of `state` because `WAIT_FOR_RECENT_USER_CREATED` — an authored KEY, not a type — must not be
93
+ * classified by a substring of its name if it ever reaches here as one.
94
+ */
95
+ if (/SLEEP|WAIT|DELAY|POLL|RETRY|SCHEDULE/.test(t))
96
+ return 'wait';
97
+ if (/SQL|QUERY|FIND|GET|READ|FETCH/.test(t))
98
+ return 'query';
99
+ /**
100
+ * WRITE before STATE, because the authored set separates them and the words overlap.
101
+ *
102
+ * `write` is a step that PUSHES data somewhere — insert, upsert, seed, push. `state` is a step that
103
+ * remembers something for the rest of the run — `SET_STORAGE`, `REGISTER_*`. `SAVE` and `WRITE` were in
104
+ * the state bucket and belong here; `SET_` and `STORAGE` stay there.
105
+ */
106
+ if (/WRITE|INSERT|UPSERT|SEED|PUSH|CREATE|DELETE/.test(t))
107
+ return 'write';
108
+ if (/SET_|STORAGE|SAVE|UPDATE|REGISTER/.test(t))
109
+ return 'state';
110
+ if (/MAP|TRANSFORM|CONVERT|FORMAT/.test(t))
111
+ return 'transform';
112
+ if (/FORWARD|DISPATCH|LOOP|EACH|BATCH/.test(t))
113
+ return 'orchestrate';
114
+ if (/IF|SWITCH|CONDITION|BRANCH/.test(t))
115
+ return 'control';
116
+ if (/END|STOP|FAIL|COMPLETE|START/.test(t))
117
+ return 'terminal';
118
+ return 'orchestrate';
119
+ }
120
+ /**
121
+ * The glyph for a step type.
122
+ *
123
+ * Empty for a step with NO type — there is no icon to stand in for, and a placeholder would render as a
124
+ * second separator (`name · · KEY`), which is how this was caught.
125
+ */
126
+ export function glyphOfStepType(type) {
127
+ if (!type)
128
+ return '';
129
+ return GLYPHS[familyOfStepType(type)] ?? '·';
130
+ }
131
+ /**
132
+ * The three lines a reader needs, in the order the brainstorm asked for: name, then key, then type.
133
+ *
134
+ * ⚠️ ONE LINE, not `<br/>`, and that was measured rather than assumed. The first version used `<br/>`; the
135
+ * shared renderer's `escapeLabel` turns `<` into `&lt;` — correctly, it is what stops an authored step name
136
+ * injecting markup — so mermaid received `&lt;br/&gt;` and would have drawn it as visible text in every box.
137
+ * Weakening `escapeLabel` to admit one tag would trade a real safety property for a cosmetic one.
138
+ *
139
+ * A junction (START/END) has its own label and no key or type — it returns unchanged, because decorating a
140
+ * terminal with an empty key line would put a blank row in every diagram.
141
+ */
142
+ export function composeNodeLabel(node) {
143
+ const type = node.type ?? node.displayType;
144
+ const heading = node.label ?? node.name ?? node.stepKey ?? node.address;
145
+ // A junction, or a node carrying neither of the two facts this function exists to add.
146
+ if (!node.stepKey && !type)
147
+ return heading;
148
+ // The glyph leads the added half rather than the whole label, so the NAME stays what the eye lands on.
149
+ // Every part is filtered, so a key with no type (or the reverse) yields ONE separator, not an empty slot.
150
+ const second = [glyphOfStepType(type), [node.stepKey, type].filter(Boolean).join(' · ')]
151
+ .filter(Boolean)
152
+ .join(' ');
153
+ return second ? `${heading} · ${second}` : heading;
154
+ }
155
+ //# sourceMappingURL=stepGlyph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepGlyph.js","sourceRoot":"","sources":["../src/stepGlyph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,GAAqC;IAC/C,2BAA2B;IAC3B,IAAI,EAAE,GAAG;IACT,uFAAuF;IACvF,OAAO,EAAE,GAAG;IACZ,uCAAuC;IACvC,WAAW,EAAE,GAAG;IAChB,kEAAkE;IAClE,KAAK,EAAE,GAAG;IACV,oDAAoD;IACpD,KAAK,EAAE,GAAG;IACV,yBAAyB;IACzB,QAAQ,EAAE,GAAG;IACb,qCAAqC;IACrC,SAAS,EAAE,GAAG;IACd,kCAAkC;IAClC,EAAE,EAAE,GAAG;IACP,oBAAoB;IACpB,IAAI,EAAE,GAAG;IACT,6BAA6B;IAC7B,KAAK,EAAE,GAAG;CACX,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,IAAI,gDAAgD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1E,IAAI,iCAAiC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7D;;;;;;;OAOG;IACH,IAAI,sCAAsC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAClE,IAAI,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAC5D;;;;;;OAMG;IACH,IAAI,6CAA6C,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1E,IAAI,mCAAmC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAChE,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAC/D,IAAI,kCAAkC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IACrE,IAAI,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC;IAC9D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAwB;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAOhC;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;IACxE,uFAAuF;IACvF,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IAE3C,uGAAuG;IACvG,0GAA0G;IAC1G,MAAM,MAAM,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACrF,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC"}