@galaxy-tool-util/schema 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/index.d.ts +7 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +7 -3
  4. package/dist/index.js.map +1 -1
  5. package/dist/test-format/tests.schema.generated.d.ts +47 -0
  6. package/dist/test-format/tests.schema.generated.d.ts.map +1 -1
  7. package/dist/test-format/tests.schema.generated.js +62 -0
  8. package/dist/test-format/tests.schema.generated.js.map +1 -1
  9. package/dist/workflow/cytoscape.d.ts.map +1 -1
  10. package/dist/workflow/cytoscape.js +5 -3
  11. package/dist/workflow/cytoscape.js.map +1 -1
  12. package/dist/workflow/draft-checks.d.ts +2 -1
  13. package/dist/workflow/draft-checks.d.ts.map +1 -1
  14. package/dist/workflow/draft-checks.js +134 -64
  15. package/dist/workflow/draft-checks.js.map +1 -1
  16. package/dist/workflow/index.d.ts +4 -2
  17. package/dist/workflow/index.d.ts.map +1 -1
  18. package/dist/workflow/index.js +4 -2
  19. package/dist/workflow/index.js.map +1 -1
  20. package/dist/workflow/layout-properties.d.ts +10 -0
  21. package/dist/workflow/layout-properties.d.ts.map +1 -0
  22. package/dist/workflow/layout-properties.js +112 -0
  23. package/dist/workflow/layout-properties.js.map +1 -0
  24. package/dist/workflow/layout.d.ts +84 -0
  25. package/dist/workflow/layout.d.ts.map +1 -0
  26. package/dist/workflow/layout.js +356 -0
  27. package/dist/workflow/layout.js.map +1 -0
  28. package/dist/workflow/lint-rules.d.ts +6 -0
  29. package/dist/workflow/lint-rules.d.ts.map +1 -1
  30. package/dist/workflow/lint-rules.js +6 -0
  31. package/dist/workflow/lint-rules.js.map +1 -1
  32. package/dist/workflow/lint.d.ts +1 -1
  33. package/dist/workflow/lint.d.ts.map +1 -1
  34. package/dist/workflow/lint.js +83 -15
  35. package/dist/workflow/lint.js.map +1 -1
  36. package/dist/workflow/lint_profiles.yml +1 -0
  37. package/dist/workflow/mermaid.d.ts +1 -1
  38. package/dist/workflow/mermaid.d.ts.map +1 -1
  39. package/dist/workflow/mermaid.js +5 -3
  40. package/dist/workflow/mermaid.js.map +1 -1
  41. package/dist/workflow/normalized/expanded.d.ts +12 -0
  42. package/dist/workflow/normalized/expanded.d.ts.map +1 -1
  43. package/dist/workflow/normalized/expanded.js +50 -3
  44. package/dist/workflow/normalized/expanded.js.map +1 -1
  45. package/dist/workflow/normalized/format2.d.ts +22 -1
  46. package/dist/workflow/normalized/format2.d.ts.map +1 -1
  47. package/dist/workflow/normalized/format2.js +26 -5
  48. package/dist/workflow/normalized/format2.js.map +1 -1
  49. package/dist/workflow/normalized/index.d.ts +3 -3
  50. package/dist/workflow/normalized/index.d.ts.map +1 -1
  51. package/dist/workflow/normalized/index.js +3 -3
  52. package/dist/workflow/normalized/index.js.map +1 -1
  53. package/dist/workflow/normalized/labels.d.ts +7 -0
  54. package/dist/workflow/normalized/labels.d.ts.map +1 -1
  55. package/dist/workflow/normalized/labels.js +11 -0
  56. package/dist/workflow/normalized/labels.js.map +1 -1
  57. package/dist/workflow/normalized/toFormat2.d.ts +1 -0
  58. package/dist/workflow/normalized/toFormat2.d.ts.map +1 -1
  59. package/dist/workflow/normalized/toFormat2.js +38 -23
  60. package/dist/workflow/normalized/toFormat2.js.map +1 -1
  61. package/dist/workflow/normalized/toNative.d.ts +16 -1
  62. package/dist/workflow/normalized/toNative.d.ts.map +1 -1
  63. package/dist/workflow/normalized/toNative.js +39 -32
  64. package/dist/workflow/normalized/toNative.js.map +1 -1
  65. package/dist/workflow/semantic-validators.d.ts +9 -0
  66. package/dist/workflow/semantic-validators.d.ts.map +1 -1
  67. package/dist/workflow/semantic-validators.js +27 -14
  68. package/dist/workflow/semantic-validators.js.map +1 -1
  69. package/package.json +1 -1
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Compute and apply node positions for Galaxy workflows.
3
+ *
4
+ * Port of gxformat2/layout. Two strategies: `topological` (the cross-language
5
+ * layering from `cytoscape-layout.ts`) and `layered` (barycenter Sugiyama
6
+ * crossing reduction). Layered coordinates are not a cross-language contract;
7
+ * both strategies are validated by the structural checkers in
8
+ * `layout-properties.ts`. Cyclic workflows raise {@link LayoutCycleError}.
9
+ */
10
+ import { COL_STRIDE, ROW_STRIDE, topologicalPositions } from "./cytoscape-layout.js";
11
+ import { cytoscapeElements } from "./cytoscape.js";
12
+ import { rawStepRenderIdentity, unlabeledNodeId } from "./normalized/labels.js";
13
+ import { INPUT_STEP_TYPES } from "./normalized/toFormat2.js";
14
+ /** Sentinel value for `position:` that requests automatic layout. */
15
+ export const AUTO = "auto";
16
+ /**
17
+ * Raised when a workflow graph contains a cycle. The bake path refuses to lay
18
+ * out a cyclic graph; the cytoscape viz path keeps its diagonal fallback.
19
+ */
20
+ export class LayoutCycleError extends Error {
21
+ constructor(message) {
22
+ super(message);
23
+ this.name = "LayoutCycleError";
24
+ }
25
+ }
26
+ function isDict(value) {
27
+ return typeof value === "object" && value !== null && !Array.isArray(value);
28
+ }
29
+ function containerItems(container) {
30
+ if (Array.isArray(container))
31
+ return container;
32
+ if (isDict(container))
33
+ return Object.values(container);
34
+ return [];
35
+ }
36
+ // --- Graph + layering -------------------------------------------------------
37
+ /** Pull `[nodeIds, edges]` out of cytoscape elements, dropping dangling edges. */
38
+ export function extractGraph(elements) {
39
+ const nodeIds = elements.nodes.map((n) => n.data.id);
40
+ const idSet = new Set(nodeIds);
41
+ const edges = [];
42
+ for (const edge of elements.edges) {
43
+ const { source, target } = edge.data;
44
+ if (idSet.has(source) && idSet.has(target))
45
+ edges.push([source, target]);
46
+ }
47
+ return [nodeIds, edges];
48
+ }
49
+ /**
50
+ * Longest-path layering via Kahn topological sort with declaration-index tie
51
+ * break (same as `topologicalPositions`). Throws {@link LayoutCycleError} when
52
+ * the graph is not a DAG.
53
+ */
54
+ export function layerAssignment(nodeIds, edges) {
55
+ const indexById = new Map(nodeIds.map((id, i) => [id, i]));
56
+ const incoming = new Map(nodeIds.map((id) => [id, []]));
57
+ const dependents = new Map(nodeIds.map((id) => [id, []]));
58
+ for (const [source, target] of edges) {
59
+ incoming.get(target).push(source);
60
+ dependents.get(source).push(target);
61
+ }
62
+ const inDegree = new Map(nodeIds.map((id) => [id, incoming.get(id).length]));
63
+ const column = new Map();
64
+ const queue = nodeIds.filter((id) => inDegree.get(id) === 0);
65
+ while (queue.length > 0) {
66
+ let best = 0;
67
+ for (let i = 1; i < queue.length; i++) {
68
+ if (indexById.get(queue[i]) < indexById.get(queue[best]))
69
+ best = i;
70
+ }
71
+ const id = queue.splice(best, 1)[0];
72
+ const sources = incoming.get(id);
73
+ column.set(id, sources.length === 0 ? 0 : Math.max(...sources.map((s) => column.get(s) + 1)));
74
+ for (const dep of dependents.get(id)) {
75
+ const remaining = inDegree.get(dep) - 1;
76
+ inDegree.set(dep, remaining);
77
+ if (remaining === 0)
78
+ queue.push(dep);
79
+ }
80
+ }
81
+ if (column.size !== nodeIds.length) {
82
+ const unplaced = nodeIds.filter((id) => !column.has(id)).sort();
83
+ throw new LayoutCycleError("Workflow graph contains a cycle; cannot compute a layout. " +
84
+ `Nodes on or downstream of the cycle: ${JSON.stringify(unplaced)}`);
85
+ }
86
+ return column;
87
+ }
88
+ /** Throw {@link LayoutCycleError} if `elements` describes a cyclic graph. */
89
+ export function checkAcyclic(elements) {
90
+ const [nodeIds, edges] = extractGraph(elements);
91
+ layerAssignment(nodeIds, edges);
92
+ }
93
+ /** Barycenter sweeps to attempt; the best ordering seen is kept. */
94
+ const MAX_SWEEPS = 8;
95
+ function countCrossingsBetween(upper, lower, successors) {
96
+ const posLower = new Map(lower.map((id, i) => [id, i]));
97
+ const edges = [];
98
+ upper.forEach((u, uIdx) => {
99
+ for (const v of successors.get(u)) {
100
+ const vIdx = posLower.get(v);
101
+ if (vIdx !== undefined)
102
+ edges.push([uIdx, vIdx]);
103
+ }
104
+ });
105
+ let crossings = 0;
106
+ for (let i = 0; i < edges.length; i++) {
107
+ const [ui, vi] = edges[i];
108
+ for (let j = i + 1; j < edges.length; j++) {
109
+ const [uj, vj] = edges[j];
110
+ if ((ui < uj && vi > vj) || (ui > uj && vi < vj))
111
+ crossings += 1;
112
+ }
113
+ }
114
+ return crossings;
115
+ }
116
+ function countAllCrossings(layers, successors) {
117
+ let total = 0;
118
+ for (let col = 0; col < layers.length - 1; col++) {
119
+ total += countCrossingsBetween(layers[col], layers[col + 1], successors);
120
+ }
121
+ return total;
122
+ }
123
+ /** Stable reorder of `layer` by mean position of each node's fixed neighbors. */
124
+ function orderByBarycenter(layer, neighbors, posInFixed) {
125
+ const keyed = layer.map((id, idx) => {
126
+ const fixed = neighbors
127
+ .get(id)
128
+ .map((m) => posInFixed.get(m))
129
+ .filter((p) => p !== undefined);
130
+ const key = fixed.length > 0 ? fixed.reduce((a, b) => a + b, 0) / fixed.length : idx;
131
+ return { id, key };
132
+ });
133
+ // Array.prototype.sort is stable, so ties preserve input order.
134
+ return keyed.sort((a, b) => a.key - b.key).map((k) => k.id);
135
+ }
136
+ function sweep(layers, neighbors, down) {
137
+ const columns = [];
138
+ if (down)
139
+ for (let col = 1; col < layers.length; col++)
140
+ columns.push(col);
141
+ else
142
+ for (let col = layers.length - 2; col >= 0; col--)
143
+ columns.push(col);
144
+ for (const col of columns) {
145
+ const fixed = layers[down ? col - 1 : col + 1];
146
+ const posInFixed = new Map(fixed.map((id, i) => [id, i]));
147
+ layers[col] = orderByBarycenter(layers[col], neighbors, posInFixed);
148
+ }
149
+ }
150
+ /**
151
+ * Sugiyama-style layered layout: longest-path layering, barycenter crossing
152
+ * reduction, then order-index rows per layer. Skip-level edges are not split
153
+ * into dummy nodes, so results can be suboptimal but every edge still points
154
+ * rightward.
155
+ */
156
+ export function layeredPositions(elements) {
157
+ const [nodeIds, edges] = extractGraph(elements);
158
+ const column = layerAssignment(nodeIds, edges);
159
+ const maxCol = Math.max(-1, ...column.values());
160
+ const layers = Array.from({ length: maxCol + 1 }, () => []);
161
+ for (const id of nodeIds)
162
+ layers[column.get(id)].push(id);
163
+ const predecessors = new Map(nodeIds.map((id) => [id, []]));
164
+ const successors = new Map(nodeIds.map((id) => [id, []]));
165
+ for (const [source, target] of edges) {
166
+ successors.get(source).push(target);
167
+ predecessors.get(target).push(source);
168
+ }
169
+ let bestLayers = layers.map((l) => [...l]);
170
+ let bestCrossings = countAllCrossings(bestLayers, successors);
171
+ for (let i = 0; i < MAX_SWEEPS && bestCrossings > 0; i++) {
172
+ const goingDown = i % 2 === 0;
173
+ sweep(layers, goingDown ? predecessors : successors, goingDown);
174
+ const crossings = countAllCrossings(layers, successors);
175
+ if (crossings < bestCrossings) {
176
+ bestCrossings = crossings;
177
+ bestLayers = layers.map((l) => [...l]);
178
+ }
179
+ }
180
+ const positions = new Map();
181
+ bestLayers.forEach((layer, col) => {
182
+ layer.forEach((id, row) => positions.set(id, { x: col * COL_STRIDE, y: row * ROW_STRIDE }));
183
+ });
184
+ return positions;
185
+ }
186
+ // --- Document helpers (shared with layout-properties.ts) ---------------------
187
+ export function isNativeDocument(workflow) {
188
+ return workflow.a_galaxy_workflow === "true";
189
+ }
190
+ /** A `$graph` multi-workflow document (many workflows, one file). */
191
+ export function isGraphDocument(workflow) {
192
+ return isDict(workflow) && "$graph" in workflow && !("class" in workflow);
193
+ }
194
+ function isEmbeddedWorkflow(value) {
195
+ return isDict(value) && (value.class === "GalaxyWorkflow" || value.a_galaxy_workflow === "true");
196
+ }
197
+ /**
198
+ * Yield in-file subworkflows embedded in `workflow`'s steps (native inline
199
+ * `subworkflow`, Format2 embedded `run`). String references are not followed.
200
+ */
201
+ export function* iterSubworkflows(workflow) {
202
+ const native = isNativeDocument(workflow);
203
+ for (const step of containerItems(workflow.steps)) {
204
+ if (!isDict(step))
205
+ continue;
206
+ const candidate = native ? step.subworkflow : step.run;
207
+ if (isEmbeddedWorkflow(candidate))
208
+ yield candidate;
209
+ }
210
+ }
211
+ /**
212
+ * Id cytoscape assigns to a Format2 node: inputs by id, steps by render
213
+ * identity. `key` is the dict-container key, or null for list form.
214
+ */
215
+ export function format2NodeId(item, key, isInput) {
216
+ if (isInput) {
217
+ if (key !== null)
218
+ return key;
219
+ return isDict(item) && typeof item.id === "string" ? item.id : null;
220
+ }
221
+ if (key !== null)
222
+ return rawStepRenderIdentity(item, key);
223
+ if (!isDict(item))
224
+ return null;
225
+ const id = item.label || item.id;
226
+ return id ?? null;
227
+ }
228
+ /** Id normalization assigns to a native step (label, else unlabeled sentinel). */
229
+ export function nativeNodeId(key, step) {
230
+ return unlabeledNodeId(step.label, step.id ?? key, INPUT_STEP_TYPES.has(step.type));
231
+ }
232
+ function stripPositions(workflow) {
233
+ const cleaned = JSON.parse(JSON.stringify(workflow));
234
+ const containerKeys = isNativeDocument(cleaned) ? ["steps"] : ["inputs", "steps"];
235
+ for (const containerKey of containerKeys) {
236
+ for (const item of containerItems(cleaned[containerKey])) {
237
+ if (isDict(item))
238
+ delete item.position;
239
+ }
240
+ }
241
+ return cleaned;
242
+ }
243
+ function shouldWrite(existing, overwrite) {
244
+ if (existing == null || existing === AUTO)
245
+ return true;
246
+ return overwrite;
247
+ }
248
+ // --- Public API ---------------------------------------------------------------
249
+ /**
250
+ * Compute node positions keyed by node id (Format2 input ids / step render
251
+ * identities — the ids the cytoscape builder emits).
252
+ */
253
+ /**
254
+ * Preset cytoscape elements for one layout unit. `graphEntries` are the
255
+ * sibling entries when `workflow` is part of a `$graph` document.
256
+ */
257
+ export function layoutElements(workflow, graphEntries = []) {
258
+ // Strip positions first: strategies ignore them and `auto` isn't a valid position.
259
+ let source = isDict(workflow) ? stripPositions(workflow) : workflow;
260
+ if (graphEntries.length > 0 && isDict(source)) {
261
+ // Normalize the entry as `main` alongside its siblings so `#id` run
262
+ // references resolve.
263
+ const siblings = graphEntries.filter((e) => e !== workflow && e.id !== "main");
264
+ source = { $graph: [{ ...source, id: "main" }, ...siblings] };
265
+ }
266
+ return cytoscapeElements(source, { layout: "preset", draftOverlay: null });
267
+ }
268
+ export function layoutPositions(workflow, strategy = "topological", graphEntries = []) {
269
+ if (strategy !== "topological" && strategy !== "layered") {
270
+ throw new Error(`Unknown layout strategy "${strategy}". Valid values: topological, layered.`);
271
+ }
272
+ const elements = layoutElements(workflow, graphEntries);
273
+ let positions;
274
+ if (strategy === "topological") {
275
+ // topologicalPositions silently falls back on cycles; refuse up front.
276
+ checkAcyclic(elements);
277
+ positions = topologicalPositions(elements);
278
+ }
279
+ else {
280
+ positions = layeredPositions(elements);
281
+ }
282
+ const result = new Map();
283
+ for (const [id, p] of positions)
284
+ result.set(id, { left: p.x, top: p.y });
285
+ return result;
286
+ }
287
+ function applyToContainer(container, positions, overwrite, isInput) {
288
+ if (isDict(container)) {
289
+ for (const key of Object.keys(container)) {
290
+ const pos = positions.get(format2NodeId(container[key], key, isInput) ?? "");
291
+ if (pos === undefined)
292
+ continue;
293
+ // Promote Format2 shorthand (e.g. `x: data`) to mapping form.
294
+ const value = isDict(container[key]) ? container[key] : { type: container[key] };
295
+ if (shouldWrite(value.position, overwrite))
296
+ value.position = { ...pos };
297
+ container[key] = value;
298
+ }
299
+ }
300
+ else if (Array.isArray(container)) {
301
+ for (const item of container) {
302
+ if (!isDict(item))
303
+ continue;
304
+ const pos = positions.get(format2NodeId(item, null, isInput) ?? "");
305
+ if (pos !== undefined && shouldWrite(item.position, overwrite))
306
+ item.position = { ...pos };
307
+ }
308
+ }
309
+ return container;
310
+ }
311
+ function applyNative(workflow, positions, overwrite) {
312
+ if (!isDict(workflow.steps))
313
+ return;
314
+ for (const [key, step] of Object.entries(workflow.steps)) {
315
+ if (!isDict(step))
316
+ continue;
317
+ const pos = positions.get(nativeNodeId(key, step));
318
+ if (pos !== undefined && shouldWrite(step.position, overwrite))
319
+ step.position = { ...pos };
320
+ }
321
+ }
322
+ /**
323
+ * Merge computed positions into a Format2 or native workflow dict, mutating it
324
+ * in place and returning it. Explicit positions are kept unless `overwrite`;
325
+ * `position: auto` is always replaced. With `recursive` (default), embedded
326
+ * subworkflows and every `$graph` entry get their own coordinate space.
327
+ */
328
+ export function applyLayout(workflow, opts = {}) {
329
+ if (isGraphDocument(workflow)) {
330
+ const entries = containerItems(workflow.$graph).filter(isDict);
331
+ for (const entry of entries)
332
+ applyLayoutUnit(entry, opts, entries);
333
+ return workflow;
334
+ }
335
+ return applyLayoutUnit(workflow, opts, []);
336
+ }
337
+ function applyLayoutUnit(workflow, opts, graphEntries) {
338
+ const { strategy = "topological", overwrite = false, recursive = true } = opts;
339
+ const positions = layoutPositions(workflow, strategy, graphEntries);
340
+ if (isNativeDocument(workflow)) {
341
+ applyNative(workflow, positions, overwrite);
342
+ }
343
+ else {
344
+ for (const containerKey of ["inputs", "steps"]) {
345
+ if (workflow[containerKey] == null)
346
+ continue;
347
+ workflow[containerKey] = applyToContainer(workflow[containerKey], positions, overwrite, containerKey === "inputs");
348
+ }
349
+ }
350
+ if (recursive) {
351
+ for (const sub of iterSubworkflows(workflow))
352
+ applyLayout(sub, opts);
353
+ }
354
+ return workflow;
355
+ }
356
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/workflow/layout.ts"],"names":[],"mappings":"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"}
@@ -12,4 +12,10 @@ export declare class NativeStepKeyNotInteger extends Linter {
12
12
  static applies_to: readonly ["native"];
13
13
  static profile: string;
14
14
  }
15
+ /** Step labels (including inputs) must be unique within a workflow; Galaxy refuses duplicates at import. */
16
+ export declare class StepLabelNotUnique extends Linter {
17
+ static severity: "error";
18
+ static applies_to: readonly ["format2", "native"];
19
+ static profile: string;
20
+ }
15
21
  //# sourceMappingURL=lint-rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lint-rules.d.ts","sourceRoot":"","sources":["../../src/workflow/lint-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,4EAA4E;AAC5E,qBAAa,uBAAwB,SAAQ,MAAM;IACjD,MAAM,CAAC,QAAQ,EAAG,OAAO,CAAU;IACnC,MAAM,CAAC,UAAU,sBAAuB;IACxC,MAAM,CAAC,OAAO,SAAgB;CAC/B"}
1
+ {"version":3,"file":"lint-rules.d.ts","sourceRoot":"","sources":["../../src/workflow/lint-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,4EAA4E;AAC5E,qBAAa,uBAAwB,SAAQ,MAAM;IACjD,MAAM,CAAC,QAAQ,EAAG,OAAO,CAAU;IACnC,MAAM,CAAC,UAAU,sBAAuB;IACxC,MAAM,CAAC,OAAO,SAAgB;CAC/B;AAED,4GAA4G;AAC5G,qBAAa,kBAAmB,SAAQ,MAAM;IAC5C,MAAM,CAAC,QAAQ,EAAG,OAAO,CAAU;IACnC,MAAM,CAAC,UAAU,iCAAkC;IACnD,MAAM,CAAC,OAAO,SAAgB;CAC/B"}
@@ -12,4 +12,10 @@ export class NativeStepKeyNotInteger extends Linter {
12
12
  static applies_to = ["native"];
13
13
  static profile = "structural";
14
14
  }
15
+ /** Step labels (including inputs) must be unique within a workflow; Galaxy refuses duplicates at import. */
16
+ export class StepLabelNotUnique extends Linter {
17
+ static severity = "error";
18
+ static applies_to = ["format2", "native"];
19
+ static profile = "structural";
20
+ }
15
21
  //# sourceMappingURL=lint-rules.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lint-rules.js","sourceRoot":"","sources":["../../src/workflow/lint-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,4EAA4E;AAC5E,MAAM,OAAO,uBAAwB,SAAQ,MAAM;IACjD,MAAM,CAAC,QAAQ,GAAG,OAAgB,CAAC;IACnC,MAAM,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAU,CAAC;IACxC,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC"}
1
+ {"version":3,"file":"lint-rules.js","sourceRoot":"","sources":["../../src/workflow/lint-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,4EAA4E;AAC5E,MAAM,OAAO,uBAAwB,SAAQ,MAAM;IACjD,MAAM,CAAC,QAAQ,GAAG,OAAgB,CAAC;IACnC,MAAM,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAU,CAAC;IACxC,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC;;AAGhC,4GAA4G;AAC5G,MAAM,OAAO,kBAAmB,SAAQ,MAAM;IAC5C,MAAM,CAAC,QAAQ,GAAG,OAAgB,CAAC;IACnC,MAAM,CAAC,UAAU,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAU,CAAC;IACnD,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC"}
@@ -29,7 +29,7 @@ export declare function lintWorkflow(workflowDict: Record<string, unknown>): Lin
29
29
  export declare function lintBestPracticesFormat2(workflowDict: Record<string, unknown>): LintResult;
30
30
  /**
31
31
  * Lint best practices for a native Galaxy workflow.
32
- * Runs shared format2 best practices plus native-specific checks.
32
+ * Runs top-level checks on the format2 view and step checks on native steps.
33
33
  */
34
34
  export declare function lintBestPracticesNative(workflowDict: Record<string, unknown>): LintResult;
35
35
  //# sourceMappingURL=lint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/workflow/lint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG5D,OAAO,EACL,WAAW,EACX,WAAW,EACX,MAAM,EACN,WAAW,EACX,UAAU,EACV,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAqNtB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAU5E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAU7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAG9E;AA6HD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAY1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAyBzF"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/workflow/lint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAI5D,OAAO,EACL,WAAW,EACX,WAAW,EACX,MAAM,EACN,WAAW,EACX,UAAU,EACV,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AA4QtB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAU5E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAU7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAG9E;AA+ID;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAe1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAuBzF"}
@@ -9,7 +9,8 @@ import { normalizedNative } from "./normalized/native.js";
9
9
  import { ensureFormat2 } from "./normalized/ensure.js";
10
10
  import { detectFormat } from "./detect-format.js";
11
11
  import { LintContext } from "./linting.js";
12
- import { NativeStepKeyNotInteger } from "./lint-rules.js";
12
+ import { nativeInputLabel, nativeStepLabel } from "./normalized/toNative.js";
13
+ import { NativeStepKeyNotInteger, StepLabelNotUnique } from "./lint-rules.js";
13
14
  export { LintContext, LintMessage, Linter, LEVEL_ERROR, LEVEL_WARN, } from "./linting.js";
14
15
  function toLintResult(ctx) {
15
16
  return {
@@ -41,6 +42,34 @@ function validateReport(ctx, report) {
41
42
  }
42
43
  // Note: Galaxy markdown validation (```galaxy directives) not yet ported
43
44
  }
45
+ function nativeStepContext(ctx, stepKey) {
46
+ return ctx.child("steps").child(stepKey);
47
+ }
48
+ /**
49
+ * Error on step labels shared by more than one step, as Galaxy rejects these at import.
50
+ *
51
+ * `labeledSteps` holds `[label, description, labelContext]` for each step of one
52
+ * workflow level (subworkflows have their own label namespace); `labelContext`
53
+ * locates the label, or `undefined` to report at `ctx`. Empty labels are
54
+ * ignored, matching Galaxy.
55
+ */
56
+ function lintDuplicateStepLabels(ctx, labeledSteps) {
57
+ const stepsByLabel = new Map();
58
+ for (const [label, description, labelContext] of labeledSteps) {
59
+ if (!label)
60
+ continue;
61
+ const steps = stepsByLabel.get(label);
62
+ if (steps)
63
+ steps.push([description, labelContext]);
64
+ else
65
+ stepsByLabel.set(label, [[description, labelContext]]);
66
+ }
67
+ for (const [label, steps] of stepsByLabel) {
68
+ if (steps.length < 2)
69
+ continue;
70
+ (steps[1][1] ?? ctx).error(`Duplicated step label '${label}' (${steps.map(([d]) => d).join(", ")})`, { linter: StepLabelNotUnique });
71
+ }
72
+ }
44
73
  // ---------------------------------------------------------------------------
45
74
  // Native workflow linting
46
75
  // ---------------------------------------------------------------------------
@@ -66,11 +95,16 @@ function lintNativeWorkflow(ctx, nnw, rawDict) {
66
95
  }
67
96
  let foundOutputs = false;
68
97
  let foundOutputWithoutLabel = false;
98
+ lintDuplicateStepLabels(ctx, Object.entries(nnw.steps).map(([key, step]) => [
99
+ step.label,
100
+ `step ${key}`,
101
+ nativeStepContext(ctx, key).child("label"),
102
+ ]));
69
103
  for (const [orderIndex, step] of Object.entries(nnw.steps)) {
104
+ const stepContext = nativeStepContext(ctx, orderIndex);
70
105
  if (!/^\d+$/.test(orderIndex)) {
71
- ctx.error(`expected step_key to be integer not [${orderIndex}]`, {
106
+ stepContext.error(`expected step_key to be integer not [${orderIndex}]`, {
72
107
  linter: NativeStepKeyNotInteger,
73
- json_pointer: `/steps/${orderIndex}`,
74
108
  });
75
109
  }
76
110
  for (const wo of step.workflow_outputs) {
@@ -85,7 +119,7 @@ function lintNativeWorkflow(ctx, nnw, rawDict) {
85
119
  ctx.error("subworkflow is missing steps or steps are empty");
86
120
  }
87
121
  else {
88
- lintNativeWorkflow(ctx, step.subworkflow);
122
+ lintNativeWorkflow(stepContext.child("subworkflow"), step.subworkflow);
89
123
  }
90
124
  }
91
125
  lintStepErrors(ctx, step.errors);
@@ -166,6 +200,19 @@ function lintFormat2Workflow(ctx, nf2, rawDict) {
166
200
  ctx.error("expected to find key [class] but absent");
167
201
  }
168
202
  }
203
+ // Check the labels conversion will assign to the native steps.
204
+ lintDuplicateStepLabels(ctx, [
205
+ ...nf2.inputs.map((inp, i) => [
206
+ nativeInputLabel(inp, i),
207
+ `input ${inp.id || i}`,
208
+ undefined,
209
+ ]),
210
+ ...nf2.steps.map((step) => [
211
+ nativeStepLabel(step),
212
+ `step ${step.id}`,
213
+ undefined,
214
+ ]),
215
+ ]);
169
216
  for (const step of nf2.steps) {
170
217
  lintStepErrors(ctx, step.errors);
171
218
  lintToolIfPresent(ctx, step.tool_id);
@@ -276,6 +323,10 @@ function lintStepBestPractices(ctx, step) {
276
323
  ctx.warn(`Workflow step ${stepId} specifies an untyped parameter in the post-job actions.`);
277
324
  }
278
325
  }
326
+ /**
327
+ * Native step best-practice checks on native fields, so messages reference
328
+ * native ids / labels rather than format2 sentinels like `_unlabeled_step_1`.
329
+ */
279
330
  function lintNativeStepBestPractices(ctx, step) {
280
331
  const stepId = step.label || step.annotation || String(step.id);
281
332
  // disconnected inputs
@@ -286,14 +337,34 @@ function lintNativeStepBestPractices(ctx, step) {
286
337
  }
287
338
  }
288
339
  }
340
+ // missing metadata
341
+ if (!step.annotation) {
342
+ ctx.warn(`Workflow step ${stepId} has no annotation.`);
343
+ }
344
+ if (!step.label) {
345
+ ctx.warn(`Workflow step ${stepId} has no label.`);
346
+ }
347
+ // untyped params in tool_state
348
+ let toolState = step.tool_state;
349
+ if (typeof toolState === "string") {
350
+ try {
351
+ toolState = JSON.parse(toolState);
352
+ }
353
+ catch {
354
+ toolState = {};
355
+ }
356
+ }
357
+ if (toolState && typeof toolState === "object" && checkJsonForUntypedParams(toolState)) {
358
+ ctx.warn(`Workflow step ${stepId} specifies an untyped parameter as an input.`);
359
+ }
289
360
  // untyped params in post_job_actions
290
361
  if (step.post_job_actions && Object.keys(step.post_job_actions).length > 0) {
291
362
  if (checkJsonForUntypedParams(step.post_job_actions)) {
292
- ctx.warn(`Workflow step with ID ${step.id} specifies an untyped parameter in the post-job actions.`);
363
+ ctx.warn(`Workflow step ${stepId} specifies an untyped parameter in the post-job actions.`);
293
364
  }
294
365
  }
295
366
  }
296
- function lintBestPractices(ctx, nf2, rawDict) {
367
+ function lintWorkflowTopLevel(ctx, nf2, rawDict) {
297
368
  // annotation/doc
298
369
  if (!nf2.doc || !nf2.doc.trim()) {
299
370
  ctx.warn("Workflow is not annotated.");
@@ -322,10 +393,6 @@ function lintBestPractices(ctx, nf2, rawDict) {
322
393
  if (!nf2.license) {
323
394
  ctx.warn("Workflow does not specify a license.");
324
395
  }
325
- // step-level
326
- for (const step of nf2.steps) {
327
- lintStepBestPractices(ctx, step);
328
- }
329
396
  }
330
397
  /**
331
398
  * Lint best practices for a Format2 Galaxy workflow.
@@ -342,17 +409,19 @@ export function lintBestPracticesFormat2(workflowDict) {
342
409
  nf2 = null;
343
410
  }
344
411
  if (nf2) {
345
- lintBestPractices(ctx, nf2, workflowDict);
412
+ lintWorkflowTopLevel(ctx, nf2, workflowDict);
413
+ for (const step of nf2.steps) {
414
+ lintStepBestPractices(ctx, step);
415
+ }
346
416
  }
347
417
  return toLintResult(ctx);
348
418
  }
349
419
  /**
350
420
  * Lint best practices for a native Galaxy workflow.
351
- * Runs shared format2 best practices plus native-specific checks.
421
+ * Runs top-level checks on the format2 view and step checks on native steps.
352
422
  */
353
423
  export function lintBestPracticesNative(workflowDict) {
354
424
  const ctx = new LintContext();
355
- // Shared best practices on format2 view
356
425
  let nf2;
357
426
  try {
358
427
  nf2 = ensureFormat2(workflowDict);
@@ -361,9 +430,8 @@ export function lintBestPracticesNative(workflowDict) {
361
430
  nf2 = null;
362
431
  }
363
432
  if (nf2) {
364
- lintBestPractices(ctx, nf2, workflowDict);
433
+ lintWorkflowTopLevel(ctx, nf2, workflowDict);
365
434
  }
366
- // Native-specific checks
367
435
  let nnw;
368
436
  try {
369
437
  nnw = normalizedNative(workflowDict);