@galaxy-tool-util/cli 0.2.0 → 1.0.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.
- package/dist/bin/gxwf.js +51 -19
- package/dist/bin/gxwf.js.map +1 -1
- package/dist/commands/add.js +2 -2
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/clean-tree.d.ts +3 -17
- package/dist/commands/clean-tree.d.ts.map +1 -1
- package/dist/commands/clean-tree.js +30 -29
- package/dist/commands/clean-tree.js.map +1 -1
- package/dist/commands/clean.d.ts +3 -0
- package/dist/commands/clean.d.ts.map +1 -1
- package/dist/commands/clean.js +12 -2
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/clear.js +4 -4
- package/dist/commands/clear.js.map +1 -1
- package/dist/commands/convert-tree.d.ts +2 -1
- package/dist/commands/convert-tree.d.ts.map +1 -1
- package/dist/commands/convert-tree.js +23 -7
- package/dist/commands/convert-tree.js.map +1 -1
- package/dist/commands/convert.d.ts +2 -1
- package/dist/commands/convert.d.ts.map +1 -1
- package/dist/commands/convert.js +36 -4
- package/dist/commands/convert.js.map +1 -1
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +5 -4
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/lint-tree.d.ts +3 -19
- package/dist/commands/lint-tree.d.ts.map +1 -1
- package/dist/commands/lint-tree.js +46 -58
- package/dist/commands/lint-tree.js.map +1 -1
- package/dist/commands/lint.d.ts +8 -4
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +61 -13
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/list.js +3 -3
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/mermaid.d.ts +6 -0
- package/dist/commands/mermaid.d.ts.map +1 -0
- package/dist/commands/mermaid.js +22 -0
- package/dist/commands/mermaid.js.map +1 -0
- package/dist/commands/populate-workflow.js +2 -2
- package/dist/commands/populate-workflow.js.map +1 -1
- package/dist/commands/render-results.d.ts +3 -3
- package/dist/commands/render-results.d.ts.map +1 -1
- package/dist/commands/render-results.js +8 -4
- package/dist/commands/render-results.js.map +1 -1
- package/dist/commands/report-output.d.ts +34 -0
- package/dist/commands/report-output.d.ts.map +1 -0
- package/dist/commands/report-output.js +70 -0
- package/dist/commands/report-output.js.map +1 -0
- package/dist/commands/resolve-tool.d.ts +2 -1
- package/dist/commands/resolve-tool.d.ts.map +1 -1
- package/dist/commands/resolve-tool.js +1 -1
- package/dist/commands/resolve-tool.js.map +1 -1
- package/dist/commands/roundtrip-tree.d.ts +3 -1
- package/dist/commands/roundtrip-tree.d.ts.map +1 -1
- package/dist/commands/roundtrip-tree.js +67 -5
- package/dist/commands/roundtrip-tree.js.map +1 -1
- package/dist/commands/roundtrip.d.ts +2 -1
- package/dist/commands/roundtrip.d.ts.map +1 -1
- package/dist/commands/roundtrip.js +30 -8
- package/dist/commands/roundtrip.js.map +1 -1
- package/dist/commands/schema.js +2 -2
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/strict-options.d.ts +22 -0
- package/dist/commands/strict-options.d.ts.map +1 -0
- package/dist/commands/strict-options.js +18 -0
- package/dist/commands/strict-options.js.map +1 -0
- package/dist/commands/validate-tests-tree.d.ts +36 -0
- package/dist/commands/validate-tests-tree.d.ts.map +1 -0
- package/dist/commands/validate-tests-tree.js +191 -0
- package/dist/commands/validate-tests-tree.js.map +1 -0
- package/dist/commands/validate-tests.d.ts +21 -0
- package/dist/commands/validate-tests.d.ts.map +1 -0
- package/dist/commands/validate-tests.js +83 -0
- package/dist/commands/validate-tests.js.map +1 -0
- package/dist/commands/validate-tree.d.ts +3 -20
- package/dist/commands/validate-tree.d.ts.map +1 -1
- package/dist/commands/validate-tree.js +53 -47
- package/dist/commands/validate-tree.js.map +1 -1
- package/dist/commands/validate-workflow-json-schema.d.ts +8 -2
- package/dist/commands/validate-workflow-json-schema.d.ts.map +1 -1
- package/dist/commands/validate-workflow-json-schema.js +104 -58
- package/dist/commands/validate-workflow-json-schema.js.map +1 -1
- package/dist/commands/validate-workflow.d.ts +17 -10
- package/dist/commands/validate-workflow.d.ts.map +1 -1
- package/dist/commands/validate-workflow.js +185 -59
- package/dist/commands/validate-workflow.js.map +1 -1
- package/dist/commands/workflow-io.d.ts +2 -11
- package/dist/commands/workflow-io.d.ts.map +1 -1
- package/dist/commands/workflow-io.js +7 -16
- package/dist/commands/workflow-io.js.map +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/workflow/_templates-bundled.d.ts +2 -0
- package/dist/workflow/_templates-bundled.d.ts.map +1 -0
- package/dist/workflow/_templates-bundled.js +324 -0
- package/dist/workflow/_templates-bundled.js.map +1 -0
- package/dist/workflow/report-templates.d.ts +13 -0
- package/dist/workflow/report-templates.d.ts.map +1 -0
- package/dist/workflow/report-templates.js +91 -0
- package/dist/workflow/report-templates.js.map +1 -0
- package/package.json +7 -5
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/bundle-templates.mjs — do not edit.
|
|
2
|
+
export const BUNDLED_TEMPLATES = {
|
|
3
|
+
"_macros.md.j2": `{#-
|
|
4
|
+
Shared macros for workflow_state report templates.
|
|
5
|
+
|
|
6
|
+
IMPORTANT: every construct used here must also be valid in Nunjucks so
|
|
7
|
+
the TypeScript mirror can render identical markdown. That means: only
|
|
8
|
+
\`for\`, \`if\`, \`set\`, \`macro\`, \`import\`, \`include\`, and the shared-subset
|
|
9
|
+
filters (\`length\`, \`default\`, \`upper\`, \`lower\`, \`replace\`, \`join\`,
|
|
10
|
+
\`sort\`, \`selectattr\`). No custom filters, no globals.
|
|
11
|
+
-#}
|
|
12
|
+
|
|
13
|
+
{#-
|
|
14
|
+
status_badge(label)
|
|
15
|
+
Renders the summary-line badge shared across every report header.
|
|
16
|
+
-#}
|
|
17
|
+
{% macro status_badge(label) -%}
|
|
18
|
+
**Status:** {{ label }}
|
|
19
|
+
{%- endmacro %}
|
|
20
|
+
|
|
21
|
+
{#-
|
|
22
|
+
kv_summary(summary)
|
|
23
|
+
Render a dict-of-counts as \`\`key: value, key: value\`\` (insertion order
|
|
24
|
+
is preserved by Pydantic \`\`model_dump\`\`, so upstream models control
|
|
25
|
+
ordering). Used under the status badge in every report header.
|
|
26
|
+
-#}
|
|
27
|
+
{% macro kv_summary(summary) -%}
|
|
28
|
+
{% for key, value in summary.items() -%}
|
|
29
|
+
{{ key }}: {{ value }}{% if not loop.last %}, {% endif %}
|
|
30
|
+
{%- endfor %}
|
|
31
|
+
{%- endmacro %}
|
|
32
|
+
|
|
33
|
+
{#-
|
|
34
|
+
workflow_state_cells(r)
|
|
35
|
+
Renders the 5 trailing cells of a workflow table row — handling the
|
|
36
|
+
error / skipped / ok three-branch logic that every current
|
|
37
|
+
\`\`format_*_markdown\`\` reimplements. \`\`r\`\` is the json-dumped
|
|
38
|
+
workflow result dict.
|
|
39
|
+
|
|
40
|
+
Expected columns (Total | OK | Fail | Skip | Details). Callers provide
|
|
41
|
+
the leading \`\`| name\`\` cell themselves so they can choose how to label
|
|
42
|
+
it (basename, relative_path, etc.).
|
|
43
|
+
-#}
|
|
44
|
+
{% macro workflow_state_cells(r) -%}
|
|
45
|
+
{% if r.skipped_reason -%}
|
|
46
|
+
- | - | - | - | SKIPPED: {{ r.skipped_reason }}
|
|
47
|
+
{%- elif r.error -%}
|
|
48
|
+
- | - | - | - | ERROR: {{ r.error }}
|
|
49
|
+
{%- else -%}
|
|
50
|
+
{% set s = r.summary %}
|
|
51
|
+
{{ (r.results | length) }} | {{ s.ok }} | {{ s.fail }} | {{ s.skip }} |
|
|
52
|
+
{%- endif %}
|
|
53
|
+
{%- endmacro %}
|
|
54
|
+
|
|
55
|
+
{#-
|
|
56
|
+
failure_bullet(f)
|
|
57
|
+
Renders a single \`\`all_failures\`\` entry as a markdown bullet. The input
|
|
58
|
+
dict has keys \`\`workflow\`\`, \`\`step\`\`, \`\`tool_id\`\`, \`\`message\`\`.
|
|
59
|
+
-#}
|
|
60
|
+
{% macro failure_bullet(f) -%}
|
|
61
|
+
- **{{ f.workflow }}** Step {{ f.step }} ({{ f.tool_id }}): {{ f.message }}
|
|
62
|
+
{%- endmacro %}
|
|
63
|
+
`,
|
|
64
|
+
"clean_tree.md.j2": `{#-
|
|
65
|
+
Tree-level report for \`\`gxwf-state-clean\`\`.
|
|
66
|
+
|
|
67
|
+
Three sections: affected-workflows table, clean-workflows banner, and
|
|
68
|
+
per-workflow detail bullets. Uses \`\`selectattr("removed_keys")\`\` and
|
|
69
|
+
\`\`selectattr("total_removed")\`\` for filtering, \`\`loop.first\`\` to gate
|
|
70
|
+
the Per-Workflow Details header, and the \`\`steps_affected\`\` +
|
|
71
|
+
\`\`display_label\`\` computed fields landed in step 1.
|
|
72
|
+
|
|
73
|
+
Context:
|
|
74
|
+
report — TreeCleanReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
75
|
+
meta — ignored here; kept for uniform signature
|
|
76
|
+
-#}
|
|
77
|
+
# Stale State Cleaning Report
|
|
78
|
+
|
|
79
|
+
Root: \`{{ report.root }}\`
|
|
80
|
+
Workflows: {{ report.workflows | length }} | {{ report.summary.total_keys }} stale key(s) across {{ report.summary.affected }} workflow(s)
|
|
81
|
+
|
|
82
|
+
{% if report.summary.affected > 0 or report.summary.errors > 0 %}
|
|
83
|
+
## Affected Workflows
|
|
84
|
+
|
|
85
|
+
| Workflow | Steps Affected | Keys Removed | Details |
|
|
86
|
+
| --- | --- | --- | --- |
|
|
87
|
+
{% for r in report.workflows %}
|
|
88
|
+
{% if r.error %}
|
|
89
|
+
| {{ r.path }} | - | - | ERROR: {{ r.error }} |
|
|
90
|
+
{% elif r.total_removed > 0 %}
|
|
91
|
+
| {{ r.path }} | {{ r.steps_affected }} | {{ r.total_removed }} | {% for sr in r.results | selectattr("removed_keys") %}Step {{ sr.step }} ({{ sr.tool_id }}): {{ sr.removed_keys | join(", ") }}{% if not loop.last %}; {% endif %}{% endfor %} |
|
|
92
|
+
{% endif %}
|
|
93
|
+
{% endfor %}
|
|
94
|
+
|
|
95
|
+
{% endif %}
|
|
96
|
+
{% if report.summary.clean > 0 %}
|
|
97
|
+
## Clean Workflows ({{ report.summary.clean }})
|
|
98
|
+
|
|
99
|
+
All other workflows have no stale keys.
|
|
100
|
+
|
|
101
|
+
{% endif %}
|
|
102
|
+
{% for r in report.workflows | selectattr("total_removed") %}
|
|
103
|
+
{% if loop.first %}
|
|
104
|
+
## Per-Workflow Details
|
|
105
|
+
|
|
106
|
+
{% endif %}
|
|
107
|
+
### {{ r.path }}
|
|
108
|
+
{% for sr in r.results | selectattr("removed_keys") %}
|
|
109
|
+
- Step {{ sr.step }} ({{ sr.display_label }}): Removed \`{{ sr.removed_keys | join("\`, \`") }}\`
|
|
110
|
+
{% endfor %}
|
|
111
|
+
|
|
112
|
+
{% endfor %}
|
|
113
|
+
`,
|
|
114
|
+
"connection_section.md.j2": `{#-
|
|
115
|
+
Connection validation section.
|
|
116
|
+
|
|
117
|
+
Ported verbatim from \`\`validate.format_connection_markdown\`\`. Standalone
|
|
118
|
+
renderer today; also an include target for \`\`validate_tree.md.j2\`\` when a
|
|
119
|
+
workflow carries a \`\`connection_report\`\`.
|
|
120
|
+
|
|
121
|
+
Context:
|
|
122
|
+
report — ConnectionValidationReport as json-dumped dict
|
|
123
|
+
-#}
|
|
124
|
+
{% set s = report.summary %}
|
|
125
|
+
{% set valid_label = "VALID" if report.valid else "INVALID" %}
|
|
126
|
+
## Connection Validation
|
|
127
|
+
|
|
128
|
+
**Status:** {{ valid_label }}
|
|
129
|
+
**Connections:** {{ s.ok | default(0) }} OK, {{ s.invalid | default(0) }} INVALID, {{ s.skip | default(0) }} SKIP
|
|
130
|
+
{% if report.has_details %}
|
|
131
|
+
|
|
132
|
+
| Source | Target | Status | Mapping | Errors |
|
|
133
|
+
| --- | --- | --- | --- | --- |
|
|
134
|
+
{% for sr in report.step_results %}
|
|
135
|
+
{% for cr in sr.connections %}
|
|
136
|
+
{% set mapping_cell = cr.mapping if cr.mapping else "-" %}
|
|
137
|
+
{% set errors_cell = cr.errors | join("; ") if cr.errors else "-" %}
|
|
138
|
+
| {{ cr.source_step }}/{{ cr.source_output }} | {{ cr.target_step }}/{{ cr.target_input }} | {{ cr.status }} | {{ mapping_cell }} | {{ errors_cell }} |
|
|
139
|
+
{% endfor %}
|
|
140
|
+
{% for err in sr.errors %}
|
|
141
|
+
{% set step_label = (sr.step ~ " (" ~ sr.tool_id ~ ")") if sr.tool_id else sr.step %}
|
|
142
|
+
| - | {{ step_label }} | error | - | {{ err }} |
|
|
143
|
+
{% endfor %}
|
|
144
|
+
{% endfor %}
|
|
145
|
+
{% endif %}
|
|
146
|
+
`,
|
|
147
|
+
"export_tree.md.j2": `{#-
|
|
148
|
+
Tree-level report for \`\`gxwf-to-format2-stateful\`\`.
|
|
149
|
+
|
|
150
|
+
Pure port of \`\`export_format2._format_tree_markdown\`\`. Content improvements
|
|
151
|
+
(category grouping, per-tool fallback aggregation, skipped appendix) are
|
|
152
|
+
deferred to follow-up commits — per the plan, per-tool fallback aggregation
|
|
153
|
+
needs step-level \`\`tool_id\`\` plumbing that is out of scope here.
|
|
154
|
+
|
|
155
|
+
Context:
|
|
156
|
+
report — ExportTreeReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
157
|
+
meta — ignored here; kept for uniform signature
|
|
158
|
+
-#}
|
|
159
|
+
# Export Report: {{ report.root }}
|
|
160
|
+
|
|
161
|
+
{% for r in report.workflows %}
|
|
162
|
+
{% if r.error %}
|
|
163
|
+
- **{{ r.path }}**: ERROR ({{ r.error }})
|
|
164
|
+
{% elif r.skipped_reason %}
|
|
165
|
+
- **{{ r.path }}**: SKIPPED ({{ r.skipped_reason }})
|
|
166
|
+
{% elif r.ok %}
|
|
167
|
+
- **{{ r.path }}**: OK ({{ r.steps_converted }} steps)
|
|
168
|
+
{% else %}
|
|
169
|
+
- **{{ r.path }}**: PARTIAL ({{ r.steps_fallback }} fallbacks)
|
|
170
|
+
{% endif %}
|
|
171
|
+
{% endfor %}
|
|
172
|
+
|
|
173
|
+
**Summary**: {{ report.summary.ok }} OK, {{ report.summary.fail }} errors, {{ report.summary.skipped }} skipped
|
|
174
|
+
`,
|
|
175
|
+
"lint_tree.md.j2": `{#-
|
|
176
|
+
Tree-level report for \`\`gxwf-lint-stateful\`\`.
|
|
177
|
+
|
|
178
|
+
Pure port of \`\`lint_stateful._format_lint_tree_markdown\`\` — single wide
|
|
179
|
+
table with one row per workflow. Uses the \`\`step_counts\`\` computed field
|
|
180
|
+
on \`\`LintWorkflowResult\`\` instead of re-looping \`\`results\`\`.
|
|
181
|
+
|
|
182
|
+
Content improvements deferred — surfacing lint messages and exit-code
|
|
183
|
+
meaning needs model + pipeline changes called out in the plan's
|
|
184
|
+
Step 1 "out of scope" list.
|
|
185
|
+
|
|
186
|
+
Context:
|
|
187
|
+
report — LintTreeReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
188
|
+
meta — ignored here; kept for uniform signature
|
|
189
|
+
-#}
|
|
190
|
+
# Lint Report
|
|
191
|
+
|
|
192
|
+
Root: \`{{ report.root }}\`
|
|
193
|
+
Workflows: {{ report.workflows | length }} | Lint: {{ report.summary.lint_errors }} errors, {{ report.summary.lint_warnings }} warnings | State: {{ report.summary.state_ok }} OK, {{ report.summary.state_fail }} FAIL, {{ report.summary.state_skip }} SKIP
|
|
194
|
+
|
|
195
|
+
| Workflow | Lint Errors | Lint Warnings | State OK | State Fail | State Skip |
|
|
196
|
+
| --- | --- | --- | --- | --- | --- |
|
|
197
|
+
{% for r in report.workflows %}
|
|
198
|
+
{% if r.error %}
|
|
199
|
+
| {{ r.path }} | - | - | - | - | ERROR: {{ r.error }} |
|
|
200
|
+
{% elif r.skipped_reason %}
|
|
201
|
+
| {{ r.path }} | - | - | - | - | SKIPPED |
|
|
202
|
+
{% else %}
|
|
203
|
+
| {{ r.path }} | {{ r.lint_errors }} | {{ r.lint_warnings }} | {{ r.step_counts.ok }} | {{ r.step_counts.fail }} | {{ r.step_counts.skip }} |
|
|
204
|
+
{% endif %}
|
|
205
|
+
{% endfor %}
|
|
206
|
+
`,
|
|
207
|
+
"roundtrip_tree.md.j2": `{#-
|
|
208
|
+
Tree-level report for \`\`gxwf-roundtrip-validate-tree\`\`.
|
|
209
|
+
|
|
210
|
+
Pure port of \`\`roundtrip.format_roundtrip_markdown\`\`. Flat bullet list
|
|
211
|
+
per workflow with sub-bullets for conversion failures and error diffs.
|
|
212
|
+
|
|
213
|
+
Context:
|
|
214
|
+
report — RoundTripTreeReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
215
|
+
meta — ignored here; kept for uniform signature
|
|
216
|
+
-#}
|
|
217
|
+
{% set s = report.summary %}
|
|
218
|
+
# Roundtrip Validation: {{ report.root }}
|
|
219
|
+
|
|
220
|
+
**{{ report.total }} workflows:** {{ s.clean }} clean, {{ s.benign_only }} benign, {{ s.fail }} fail, {{ s.error }} error, {{ s.skipped }} skipped
|
|
221
|
+
|
|
222
|
+
{% for r in report.workflows %}
|
|
223
|
+
{% set benign = r.benign_diffs | length %}
|
|
224
|
+
{% set error_count = r.error_diffs | length %}
|
|
225
|
+
{% set detail = "" %}
|
|
226
|
+
{% if benign %}{% set detail = detail ~ " (" ~ benign ~ " benign)" %}{% endif %}
|
|
227
|
+
{% if error_count %}{% set detail = detail ~ " (" ~ error_count ~ " errors)" %}{% endif %}
|
|
228
|
+
- **{{ r.workflow_path }}**: {{ r.status | upper }}{{ detail }}
|
|
229
|
+
{% for line in r.conversion_failure_lines %}
|
|
230
|
+
- {{ line }}
|
|
231
|
+
{% endfor %}
|
|
232
|
+
{% for d in r.error_diffs %}
|
|
233
|
+
- {{ d.step_path }}: {{ d.description }}
|
|
234
|
+
{% endfor %}
|
|
235
|
+
{% endfor %}
|
|
236
|
+
`,
|
|
237
|
+
"to_native_tree.md.j2": `{#-
|
|
238
|
+
Tree-level report for \`\`gxwf-to-native-stateful\`\`.
|
|
239
|
+
|
|
240
|
+
Pure port of \`\`to_native_stateful._format_tree_markdown\`\`. Structure is
|
|
241
|
+
identical to \`\`export_tree.md.j2\`\` — same four branches, only the H1 and
|
|
242
|
+
the OK-branch count field (\`\`steps_encoded\`\` vs \`\`steps_converted\`\`)
|
|
243
|
+
differ. Content improvements deferred, same rationale as export.
|
|
244
|
+
|
|
245
|
+
Context:
|
|
246
|
+
report — ToNativeTreeReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
247
|
+
meta — ignored here; kept for uniform signature
|
|
248
|
+
-#}
|
|
249
|
+
# Conversion Report: {{ report.root }}
|
|
250
|
+
|
|
251
|
+
{% for r in report.workflows %}
|
|
252
|
+
{% if r.error %}
|
|
253
|
+
- **{{ r.path }}**: ERROR ({{ r.error }})
|
|
254
|
+
{% elif r.skipped_reason %}
|
|
255
|
+
- **{{ r.path }}**: SKIPPED ({{ r.skipped_reason }})
|
|
256
|
+
{% elif r.ok %}
|
|
257
|
+
- **{{ r.path }}**: OK ({{ r.steps_encoded }} steps)
|
|
258
|
+
{% else %}
|
|
259
|
+
- **{{ r.path }}**: PARTIAL ({{ r.steps_fallback }} fallbacks)
|
|
260
|
+
{% endif %}
|
|
261
|
+
{% endfor %}
|
|
262
|
+
|
|
263
|
+
**Summary**: {{ report.summary.ok }} OK, {{ report.summary.fail }} errors, {{ report.summary.skipped }} skipped
|
|
264
|
+
`,
|
|
265
|
+
"validate_tree.md.j2": `{#-
|
|
266
|
+
Tree-level report for \`\`gxwf-state-validate\`\`.
|
|
267
|
+
|
|
268
|
+
Pure port of \`\`validate.format_tree_markdown\`\`. Per-category tables with
|
|
269
|
+
a Details column showing failure counts, a Failure Details appendix using
|
|
270
|
+
\`\`report.all_failures\`\`, and per-workflow connection sections via
|
|
271
|
+
\`\`{% include "connection_section.md.j2" %}\`\`.
|
|
272
|
+
|
|
273
|
+
The \`\`workflow_state_cells\`\` macro is NOT used here because the validate
|
|
274
|
+
table has a 6th "Details" column whose content varies (failure count for
|
|
275
|
+
normal rows, SKIPPED/ERROR for exceptional rows) — inlining the 3-branch
|
|
276
|
+
logic keeps the template straightforward.
|
|
277
|
+
|
|
278
|
+
Context:
|
|
279
|
+
report — TreeValidationReport as json-dumped dict (\`\`results\`\` → \`\`workflows\`\`)
|
|
280
|
+
meta — ignored here; kept for uniform signature
|
|
281
|
+
-#}
|
|
282
|
+
{% import "_macros.md.j2" as m %}
|
|
283
|
+
{% set s = report.summary %}
|
|
284
|
+
# Workflow Validation Report
|
|
285
|
+
|
|
286
|
+
Root: \`{{ report.root }}\`
|
|
287
|
+
Workflows: {{ report.workflows | length }} | Steps: {{ s.ok }} OK, {{ s.fail }} FAIL, {{ s.skip }} SKIP, {{ s.error }} ERROR{% if s.skipped %} | {{ s.skipped }} workflow(s) skipped{% endif %}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
{% for cat in report.categories %}
|
|
291
|
+
## {{ cat.name }} ({{ cat.results | length }} workflows)
|
|
292
|
+
|
|
293
|
+
| Workflow | Steps | OK | Fail | Skip | Details |
|
|
294
|
+
| --- | --- | --- | --- | --- | --- |
|
|
295
|
+
{% for r in cat.results %}
|
|
296
|
+
{% if r.skipped_reason %}
|
|
297
|
+
| {{ r.name }} | - | - | - | - | SKIPPED: {{ r.skipped_reason }} |
|
|
298
|
+
{% elif r.error %}
|
|
299
|
+
| {{ r.name }} | - | - | - | - | ERROR: {{ r.error }} |
|
|
300
|
+
{% else %}
|
|
301
|
+
{% set fail_count = r.failures | length %}
|
|
302
|
+
| {{ r.name }} | {{ r.results | length }} | {{ r.summary.ok }} | {{ r.summary.fail }} | {{ r.summary.skip }} | {% if fail_count %}{{ fail_count }} failure(s){% endif %} |
|
|
303
|
+
{% endif %}
|
|
304
|
+
{% endfor %}
|
|
305
|
+
|
|
306
|
+
{% endfor %}
|
|
307
|
+
{% if report.all_failures %}
|
|
308
|
+
## Failure Details
|
|
309
|
+
|
|
310
|
+
{% for f in report.all_failures %}
|
|
311
|
+
{{ m.failure_bullet(f) }}
|
|
312
|
+
{% endfor %}
|
|
313
|
+
|
|
314
|
+
{% endif %}
|
|
315
|
+
{% for r in report.workflows | selectattr("connection_report") %}
|
|
316
|
+
## Connections: {{ r.path }}
|
|
317
|
+
|
|
318
|
+
{% set report = r.connection_report %}
|
|
319
|
+
{% include "connection_section.md.j2" %}
|
|
320
|
+
|
|
321
|
+
{% endfor %}
|
|
322
|
+
`,
|
|
323
|
+
};
|
|
324
|
+
//# sourceMappingURL=_templates-bundled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_templates-bundled.js","sourceRoot":"","sources":["../../src/workflow/_templates-bundled.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4DlB;IACC,kBAAkB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDrB;IACC,0BAA0B,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC7B;IACC,mBAAmB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BtB;IACC,iBAAiB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BpB;IACC,sBAAsB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BzB;IACC,sBAAsB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BzB;IACC,qBAAqB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDxB;CACA,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ReportMeta {
|
|
2
|
+
generated_at?: string;
|
|
3
|
+
tool_util_version?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Render a Markdown report template by name.
|
|
7
|
+
*
|
|
8
|
+
* @param templateName - e.g. `"validate_tree.md.j2"`
|
|
9
|
+
* @param report - the tree report object (plain JSON-serialisable value)
|
|
10
|
+
* @param meta - optional metadata (generated_at, tool_util_version)
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderReport(templateName: string, report: unknown, meta?: ReportMeta): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=report-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-templates.d.ts","sourceRoot":"","sources":["../../src/workflow/report-templates.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,UAAU;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA+DD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,OAAO,EACf,IAAI,CAAC,EAAE,UAAU,GAChB,OAAO,CAAC,MAAM,CAAC,CAQjB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nunjucks renderer for workflow_state tree-level Markdown reports.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Python's `_report_templates.py`. Templates are the synced `.md.j2`
|
|
5
|
+
* files under `templates/reports/`. The Nunjucks environment aliases
|
|
6
|
+
* `_macros.md.j2` to the bundled macro file so body templates remain unchanged.
|
|
7
|
+
*
|
|
8
|
+
* Nunjucks/Jinja2 compatibility note:
|
|
9
|
+
* The synced `_macros.md.j2` uses `summary.items()` in `kv_summary`. This is
|
|
10
|
+
* valid Jinja2 but NOT Nunjucks — use plain `for k, v in obj` in Nunjucks.
|
|
11
|
+
* `kv_summary` is currently unused by all body templates, so this is latent.
|
|
12
|
+
* If a future sync adds a template that calls `kv_summary`, the `.items()` call
|
|
13
|
+
* will fail at render time. Fix in `_macros.md.j2` (TS-side) by using plain
|
|
14
|
+
* iteration; for the Python-side file the issue upstream with Python first.
|
|
15
|
+
*/
|
|
16
|
+
import nunjucks from "nunjucks";
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
import { join, dirname } from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
// ── Template loader ──────────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Custom Nunjucks loader that resolves templates from an in-memory map
|
|
23
|
+
* (bundled mode) with a filesystem fallback (dev/test mode).
|
|
24
|
+
*/
|
|
25
|
+
class ReportTemplateLoader extends nunjucks.Loader {
|
|
26
|
+
async = false;
|
|
27
|
+
bundled;
|
|
28
|
+
fsDir;
|
|
29
|
+
constructor(bundled, fsDir) {
|
|
30
|
+
super();
|
|
31
|
+
this.bundled = bundled;
|
|
32
|
+
this.fsDir = fsDir;
|
|
33
|
+
}
|
|
34
|
+
getSource(name) {
|
|
35
|
+
if (this.bundled[name] !== undefined) {
|
|
36
|
+
return { src: this.bundled[name], path: name, noCache: false };
|
|
37
|
+
}
|
|
38
|
+
// Filesystem fallback (dev/test without a prior build)
|
|
39
|
+
const fsPath = join(this.fsDir, name);
|
|
40
|
+
const src = readFileSync(fsPath, "utf-8");
|
|
41
|
+
return { src, path: fsPath, noCache: true };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// ── Lazy singleton environment ───────────────────────────────────────
|
|
45
|
+
let _mdEnv;
|
|
46
|
+
/** Path to `templates/reports/` resolved relative to this source file. */
|
|
47
|
+
function getTemplatesDir() {
|
|
48
|
+
return join(dirname(fileURLToPath(import.meta.url)), "templates/reports");
|
|
49
|
+
}
|
|
50
|
+
async function loadBundled() {
|
|
51
|
+
try {
|
|
52
|
+
// Dynamic import so the module is optional (not present before `pnpm build`)
|
|
53
|
+
const mod = await import("./_templates-bundled.js");
|
|
54
|
+
return mod.BUNDLED_TEMPLATES;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function getMdEnv() {
|
|
61
|
+
if (_mdEnv)
|
|
62
|
+
return _mdEnv;
|
|
63
|
+
const bundled = await loadBundled();
|
|
64
|
+
const loader = new ReportTemplateLoader(bundled, getTemplatesDir());
|
|
65
|
+
_mdEnv = new nunjucks.Environment(loader, {
|
|
66
|
+
autoescape: false,
|
|
67
|
+
trimBlocks: true,
|
|
68
|
+
lstripBlocks: true,
|
|
69
|
+
});
|
|
70
|
+
return _mdEnv;
|
|
71
|
+
}
|
|
72
|
+
// ── Public API ───────────────────────────────────────────────────────
|
|
73
|
+
/**
|
|
74
|
+
* Render a Markdown report template by name.
|
|
75
|
+
*
|
|
76
|
+
* @param templateName - e.g. `"validate_tree.md.j2"`
|
|
77
|
+
* @param report - the tree report object (plain JSON-serialisable value)
|
|
78
|
+
* @param meta - optional metadata (generated_at, tool_util_version)
|
|
79
|
+
*/
|
|
80
|
+
export async function renderReport(templateName, report, meta) {
|
|
81
|
+
const env = await getMdEnv();
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
env.render(templateName, { report, meta }, (err, result) => {
|
|
84
|
+
if (err)
|
|
85
|
+
reject(err);
|
|
86
|
+
else
|
|
87
|
+
resolve(result ?? "");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=report-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-templates.js","sourceRoot":"","sources":["../../src/workflow/report-templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAOzC,wEAAwE;AAExE;;;GAGG;AACH,MAAM,oBAAqB,SAAQ,QAAQ,CAAC,MAAM;IAChD,KAAK,GAAG,KAAc,CAAC;IACf,OAAO,CAAyB;IAChC,KAAK,CAAS;IAEtB,YAAY,OAA+B,EAAE,KAAa;QACxD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACjE,CAAC;QACD,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC9C,CAAC;CACF;AAED,wEAAwE;AAExE,IAAI,MAAwC,CAAC;AAE7C,0EAA0E;AAC1E,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC5E,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,IAAI,CAAC;QACH,6EAA6E;QAC7E,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACpD,OAAO,GAAG,CAAC,iBAA2C,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ;IACrB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IACpE,MAAM,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE;QACxC,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wEAAwE;AAExE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,YAAoB,EACpB,MAAe,EACf,IAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC7B,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACzD,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAChB,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@galaxy-tool-util/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "galaxy-tool-cache CLI — cache and inspect Galaxy tool metadata",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,15 +32,17 @@
|
|
|
32
32
|
"ajv": "^8.18.0",
|
|
33
33
|
"commander": "^14.0.0",
|
|
34
34
|
"effect": "^3.21.0",
|
|
35
|
+
"nunjucks": "^3.2.4",
|
|
35
36
|
"yaml": "^2.8.3",
|
|
36
|
-
"@galaxy-tool-util/core": "0.
|
|
37
|
-
"@galaxy-tool-util/schema": "0.
|
|
37
|
+
"@galaxy-tool-util/core": "1.0.0",
|
|
38
|
+
"@galaxy-tool-util/schema": "1.0.0"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^25.5.0"
|
|
41
|
+
"@types/node": "^25.5.0",
|
|
42
|
+
"@types/nunjucks": "^3.2.6"
|
|
41
43
|
},
|
|
42
44
|
"scripts": {
|
|
43
|
-
"build": "tsc",
|
|
45
|
+
"build": "node scripts/bundle-templates.mjs && tsc",
|
|
44
46
|
"typecheck": "tsc --noEmit",
|
|
45
47
|
"test": "tsc --noEmit && vitest run",
|
|
46
48
|
"test:watch": "vitest",
|