@galaxy-tool-util/cli 1.1.0 → 1.3.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 (71) hide show
  1. package/dist/commands/annotate-connections.d.ts +30 -0
  2. package/dist/commands/annotate-connections.d.ts.map +1 -0
  3. package/dist/commands/annotate-connections.js +42 -0
  4. package/dist/commands/annotate-connections.js.map +1 -0
  5. package/dist/commands/connection-validation.d.ts +20 -0
  6. package/dist/commands/connection-validation.d.ts.map +1 -0
  7. package/dist/commands/connection-validation.js +26 -0
  8. package/dist/commands/connection-validation.js.map +1 -0
  9. package/dist/commands/cytoscapejs/_template-bundled.d.ts +2 -0
  10. package/dist/commands/cytoscapejs/_template-bundled.d.ts.map +1 -0
  11. package/dist/commands/cytoscapejs/_template-bundled.js +182 -0
  12. package/dist/commands/cytoscapejs/_template-bundled.js.map +1 -0
  13. package/dist/commands/cytoscapejs.d.ts +12 -0
  14. package/dist/commands/cytoscapejs.d.ts.map +1 -0
  15. package/dist/commands/cytoscapejs.js +62 -0
  16. package/dist/commands/cytoscapejs.js.map +1 -0
  17. package/dist/commands/mermaid.d.ts +2 -0
  18. package/dist/commands/mermaid.d.ts.map +1 -1
  19. package/dist/commands/mermaid.js +5 -1
  20. package/dist/commands/mermaid.js.map +1 -1
  21. package/dist/commands/summarize.d.ts +31 -0
  22. package/dist/commands/summarize.d.ts.map +1 -0
  23. package/dist/commands/summarize.js +85 -0
  24. package/dist/commands/summarize.js.map +1 -0
  25. package/dist/commands/validate-workflow.d.ts +1 -0
  26. package/dist/commands/validate-workflow.d.ts.map +1 -1
  27. package/dist/commands/validate-workflow.js +38 -3
  28. package/dist/commands/validate-workflow.js.map +1 -1
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +2 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/meta/extract-spec.d.ts +13 -0
  34. package/dist/meta/extract-spec.d.ts.map +1 -0
  35. package/dist/meta/extract-spec.js +90 -0
  36. package/dist/meta/extract-spec.js.map +1 -0
  37. package/dist/meta/index.d.ts +8 -0
  38. package/dist/meta/index.d.ts.map +1 -0
  39. package/dist/meta/index.js +21 -0
  40. package/dist/meta/index.js.map +1 -0
  41. package/dist/meta/spec-types.d.ts +40 -0
  42. package/dist/meta/spec-types.d.ts.map +1 -0
  43. package/dist/meta/spec-types.js +11 -0
  44. package/dist/meta/spec-types.js.map +1 -0
  45. package/dist/meta/specs.d.ts +4 -0
  46. package/dist/meta/specs.d.ts.map +1 -0
  47. package/dist/meta/specs.js +10 -0
  48. package/dist/meta/specs.js.map +1 -0
  49. package/dist/meta/types.d.ts +55 -0
  50. package/dist/meta/types.d.ts.map +1 -0
  51. package/dist/meta/types.js +9 -0
  52. package/dist/meta/types.js.map +1 -0
  53. package/dist/meta-build.d.ts +13 -0
  54. package/dist/meta-build.d.ts.map +1 -0
  55. package/dist/meta-build.js +60 -0
  56. package/dist/meta-build.js.map +1 -0
  57. package/dist/programs/galaxy-tool-cache.d.ts +5 -1
  58. package/dist/programs/galaxy-tool-cache.d.ts.map +1 -1
  59. package/dist/programs/galaxy-tool-cache.js +14 -56
  60. package/dist/programs/galaxy-tool-cache.js.map +1 -1
  61. package/dist/programs/gxwf.d.ts +7 -1
  62. package/dist/programs/gxwf.d.ts.map +1 -1
  63. package/dist/programs/gxwf.js +36 -184
  64. package/dist/programs/gxwf.js.map +1 -1
  65. package/dist/spec/build-program.d.ts +12 -0
  66. package/dist/spec/build-program.d.ts.map +1 -0
  67. package/dist/spec/build-program.js +102 -0
  68. package/dist/spec/build-program.js.map +1 -0
  69. package/package.json +10 -4
  70. package/spec/galaxy-tool-cache.json +177 -0
  71. package/spec/gxwf.json +693 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Helper for `gxwf mermaid` / `gxwf cytoscapejs` `--annotate-connections`:
3
+ * runs the connection validator against a workflow and returns the
4
+ * `EdgeAnnotation` lookup the emitters consume.
5
+ */
6
+ import { type EdgeAnnotation } from "@galaxy-tool-util/connection-validation";
7
+ import type { ToolCache } from "@galaxy-tool-util/core";
8
+ import type { ParsedTool } from "@galaxy-tool-util/schema";
9
+ export interface ResolveEdgeAnnotationsOptions {
10
+ cacheDir?: string;
11
+ }
12
+ export declare function resolveEdgeAnnotations(data: Record<string, unknown>, opts?: ResolveEdgeAnnotationsOptions): Promise<Map<string, EdgeAnnotation>>;
13
+ export declare function resolveEdgeAnnotationsWithCache(data: Record<string, unknown>, cache: ToolCache): Promise<Map<string, EdgeAnnotation>>;
14
+ export interface ResolvedToolSpec {
15
+ tool_id: string;
16
+ tool_version: string;
17
+ parsed: ParsedTool;
18
+ }
19
+ /**
20
+ * Variant of `resolveEdgeAnnotationsWithCache` that also returns the
21
+ * `ParsedTool` specs the validator consumed, keyed by `toolId@toolVersion`.
22
+ * The hybrid `gxwf-web` edge-annotations response uses this so co-resident
23
+ * browsers can write the specs into IndexedDB and warm the client-side
24
+ * `useToolInfoService` for free.
25
+ */
26
+ export declare function resolveEdgeAnnotationsAndSpecsWithCache(data: Record<string, unknown>, cache: ToolCache): Promise<{
27
+ annotations: Map<string, EdgeAnnotation>;
28
+ specs: Map<string, ResolvedToolSpec>;
29
+ }>;
30
+ //# sourceMappingURL=annotate-connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotate-connections.d.ts","sourceRoot":"","sources":["../../src/commands/annotate-connections.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,GAAE,6BAAkC,GACvC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAItC;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAKtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,uCAAuC,CAC3D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,GACf,OAAO,CAAC;IACT,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CACtC,CAAC,CAYD"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Helper for `gxwf mermaid` / `gxwf cytoscapejs` `--annotate-connections`:
3
+ * runs the connection validator against a workflow and returns the
4
+ * `EdgeAnnotation` lookup the emitters consume.
5
+ */
6
+ import { buildEdgeAnnotations, buildGetToolInfo as _buildGetToolInfo, buildWorkflowGraph, validateConnectionGraph, } from "@galaxy-tool-util/connection-validation";
7
+ import { makeNodeToolCache } from "@galaxy-tool-util/core/node";
8
+ import { buildGetToolInfo } from "./connection-validation.js";
9
+ import { isResolveError, loadCachedTool } from "./resolve-tool.js";
10
+ export async function resolveEdgeAnnotations(data, opts = {}) {
11
+ const cache = makeNodeToolCache({ cacheDir: opts.cacheDir });
12
+ await cache.index.load();
13
+ return resolveEdgeAnnotationsWithCache(data, cache);
14
+ }
15
+ export async function resolveEdgeAnnotationsWithCache(data, cache) {
16
+ const getToolInfo = await buildGetToolInfo(data, cache);
17
+ const graph = buildWorkflowGraph(data, getToolInfo);
18
+ const [report] = validateConnectionGraph(graph);
19
+ return buildEdgeAnnotations(report);
20
+ }
21
+ /**
22
+ * Variant of `resolveEdgeAnnotationsWithCache` that also returns the
23
+ * `ParsedTool` specs the validator consumed, keyed by `toolId@toolVersion`.
24
+ * The hybrid `gxwf-web` edge-annotations response uses this so co-resident
25
+ * browsers can write the specs into IndexedDB and warm the client-side
26
+ * `useToolInfoService` for free.
27
+ */
28
+ export async function resolveEdgeAnnotationsAndSpecsWithCache(data, cache) {
29
+ const specs = new Map();
30
+ const getToolInfo = await _buildGetToolInfo(data, async (id, version) => {
31
+ const r = await loadCachedTool(cache, id, version);
32
+ if (isResolveError(r))
33
+ return null;
34
+ const ver = r.tool.version ?? version ?? "";
35
+ specs.set(`${id}@${ver}`, { tool_id: id, tool_version: ver, parsed: r.tool });
36
+ return r.tool;
37
+ });
38
+ const graph = buildWorkflowGraph(data, getToolInfo);
39
+ const [report] = validateConnectionGraph(graph);
40
+ return { annotations: buildEdgeAnnotations(report), specs };
41
+ }
42
+ //# sourceMappingURL=annotate-connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotate-connections.js","sourceRoot":"","sources":["../../src/commands/annotate-connections.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,oBAAoB,EACpB,gBAAgB,IAAI,iBAAiB,EACrC,kBAAkB,EAClB,uBAAuB,GAExB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAA6B,EAC7B,OAAsC,EAAE;IAExC,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7D,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACzB,OAAO,+BAA+B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,IAA6B,EAC7B,KAAgB;IAEhB,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uCAAuC,CAC3D,IAA6B,EAC7B,KAAgB;IAKhB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAClD,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;QACtE,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,cAAc,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,EAAE,CAAC;QAC5C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9E,OAAO,CAAC,CAAC,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,EAAE,WAAW,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * CLI integration for connection validation.
3
+ *
4
+ * Walks a workflow dict to collect every tool reference (recursing into
5
+ * subworkflows), preloads each tool from the cache, and runs
6
+ * `validateConnectionsReport`. The connection validator wants a sync
7
+ * `GetToolInfo` lookup, so async cache fetches happen up front.
8
+ *
9
+ * The walker + preloader live in `@galaxy-tool-util/connection-validation`
10
+ * (`collectToolRefs`, `buildGetToolInfo`); this module is a thin wrapper that
11
+ * adapts the CLI's on-disk `ToolCache` to the lifted helper's `AsyncToolFetcher`.
12
+ */
13
+ import { collectToolRefs, type GetToolInfo } from "@galaxy-tool-util/connection-validation";
14
+ import type { ToolCache } from "@galaxy-tool-util/core";
15
+ import type { ConnectionValidationReport } from "@galaxy-tool-util/schema";
16
+ export { collectToolRefs };
17
+ export type { ToolRef } from "@galaxy-tool-util/connection-validation";
18
+ export declare function buildConnectionReport(data: Record<string, unknown>, cache: ToolCache): Promise<ConnectionValidationReport>;
19
+ export declare function buildGetToolInfo(data: Record<string, unknown>, cache: ToolCache): Promise<GetToolInfo>;
20
+ //# sourceMappingURL=connection-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-validation.d.ts","sourceRoot":"","sources":["../../src/commands/connection-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAEL,eAAe,EAEf,KAAK,WAAW,EACjB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAI3E,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,YAAY,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAEvE,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,0BAA0B,CAAC,CAGrC;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,WAAW,CAAC,CAKtB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * CLI integration for connection validation.
3
+ *
4
+ * Walks a workflow dict to collect every tool reference (recursing into
5
+ * subworkflows), preloads each tool from the cache, and runs
6
+ * `validateConnectionsReport`. The connection validator wants a sync
7
+ * `GetToolInfo` lookup, so async cache fetches happen up front.
8
+ *
9
+ * The walker + preloader live in `@galaxy-tool-util/connection-validation`
10
+ * (`collectToolRefs`, `buildGetToolInfo`); this module is a thin wrapper that
11
+ * adapts the CLI's on-disk `ToolCache` to the lifted helper's `AsyncToolFetcher`.
12
+ */
13
+ import { buildGetToolInfo as _buildGetToolInfo, collectToolRefs, validateConnectionsReport, } from "@galaxy-tool-util/connection-validation";
14
+ import { isResolveError, loadCachedTool } from "./resolve-tool.js";
15
+ export { collectToolRefs };
16
+ export async function buildConnectionReport(data, cache) {
17
+ const getToolInfo = await buildGetToolInfo(data, cache);
18
+ return validateConnectionsReport(data, getToolInfo);
19
+ }
20
+ export async function buildGetToolInfo(data, cache) {
21
+ return _buildGetToolInfo(data, async (id, version) => {
22
+ const r = await loadCachedTool(cache, id, version);
23
+ return isResolveError(r) ? null : r.tool;
24
+ });
25
+ }
26
+ //# sourceMappingURL=connection-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-validation.js","sourceRoot":"","sources":["../../src/commands/connection-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,gBAAgB,IAAI,iBAAiB,EACrC,eAAe,EACf,yBAAyB,GAE1B,MAAM,yCAAyC,CAAC;AAIjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,CAAC;AAG3B,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAA6B,EAC7B,KAAgB;IAEhB,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,yBAAyB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA6B,EAC7B,KAAgB;IAEhB,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;QACnD,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const CYTOSCAPE_HTML_TEMPLATE = "<!doctype html>\n\n<html>\n\n<head>\n <title>Galaxy Workflow</title>\n <script src=\"https://unpkg.com/cytoscape@3.33.2/dist/cytoscape.min.js\"></script>\n <script src=\"https://unpkg.com/dagre@0.8.5/dist/dagre.min.js\"></script>\n <script src=\"https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js\"></script>\n <script src=\"https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js\"></script>\n <script src=\"https://unpkg.com/cytoscape-popper@2.0.0/cytoscape-popper.js\"></script>\n <script src=\"https://unpkg.com/tippy.js@6.3.7/dist/tippy.umd.min.js\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/tippy.js@6.3.7/dist/tippy.css\" />\n <script>\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n var requestedLayout = $layout;\n var dagreReady = (typeof cytoscapeDagre !== 'undefined');\n if (dagreReady && cytoscape.use) {\n try { cytoscape.use(cytoscapeDagre); } catch (e) { /* already registered */ }\n }\n var layoutConfig = (function(name) {\n if (name === 'dagre') {\n return dagreReady\n ? { name: 'dagre', rankDir: 'LR', nodeSep: 40, rankSep: 80 }\n : { name: 'preset' };\n }\n if (name === 'breadthfirst') return { name: 'breadthfirst', directed: true, spacingFactor: 1.2 };\n if (name === 'grid') return { name: 'grid' };\n if (name === 'cose') return { name: 'cose' };\n if (name === 'random') return { name: 'random' };\n if (name === 'topological') return { name: 'preset' };\n return { name: 'preset' };\n })(requestedLayout);\n var cy = cytoscape({\n container: document.getElementById('cy'),\n elements: $elements,\n layout: layoutConfig,\n // so we can see the ids\n style: [\n {\n selector: 'node',\n style: {\n 'label': 'data(label)'\n }\n },\n {\n selector: 'edge',\n style: {\n 'curve-style': 'bezier',\n 'target-arrow-shape': 'vee',\n 'arrow-scale': 2\n }\n },\n {\n selector: \".input\",\n style: {\n shape: 'diamond',\n 'background-color': '#d0bb46'\n }\n },\n {\n selector: \".runnable\",\n style: {\n shape: 'round-rectangle',\n 'background-color': '#2c3143'\n }\n },\n {\n selector: 'edge.mapover_1',\n style: { width: 4, 'line-color': '#5a8' }\n },\n {\n selector: 'edge.mapover_2',\n style: { width: 6, 'line-color': '#5a8' }\n },\n {\n selector: 'edge.mapover_3',\n style: { width: 8, 'line-color': '#5a8' }\n },\n {\n selector: 'edge.reduction',\n style: {\n 'line-style': 'dashed',\n 'line-color': '#a55',\n 'target-arrow-shape': 'tee',\n 'target-arrow-color': '#a55'\n }\n }\n ]\n });\n\n function makePopper(ele) {\n let ref = ele.popperRef(); // used only for positioning\n let dummyDomEle = document.createElement('div');\n\n ele.tippy = tippy(dummyDomEle, { // tippy options:\n getReferenceClientRect: ref.getBoundingClientRect.bind(ref),\n content: function() {\n let content = document.createElement('div');\n\n let innerHTML = '';\n if(ele.isNode()) {\n let stepType = ele.data(\"step_type\");\n innerHTML += \"<p><i>Step Type:</i> \" + stepType + \"</p>\";\n let toolId = ele.data(\"tool_id\");\n if (toolId) {\n innerHTML += \"<p><i>ToolID:</i> \" + toolId + \"</p>\";\n }\n let repoLink = ele.data(\"repo_link\");\n if (repoLink) {\n innerHTML += \"<a href=\" + repoLink + '\">Visit Tool Shed Repository</a>';\n }\n let doc = ele.data('doc');\n if (doc) {\n innerHTML += \"<p>\" + doc + \"</p>\";\n }\n } else {\n let output = ele.data(\"output\");\n let input = ele.data(\"input\");\n if(output) {\n innerHTML += \"Output named \" + output + \" connects to \" + input;\n } else {\n innerHTML += \"Connected to input \" + input;\n }\n let mapDepth = ele.data(\"map_depth\");\n if (mapDepth) {\n let mapping = ele.data(\"mapping\");\n innerHTML += \"<p><i>Map depth:</i> \" + mapDepth + (mapping ? \" (\" + mapping + \")\" : \"\") + \"</p>\";\n }\n if (ele.data(\"reduction\")) {\n innerHTML += \"<p><i>Reduction:</i> list \u2192 multi-data</p>\";\n }\n }\n content.innerHTML = innerHTML;\n\n return content;\n },\n delay: [0,1000],\n interactive: true,\n placement: 'bottom',\n trigger: 'manual', // probably want manual mode\n appendTo: document.body\n });\n }\n\n cy.ready(function() {\n cy.elements().forEach(function(ele) {\n makePopper(ele);\n });\n });\n\n cy.elements().unbind('mouseover');\n cy.elements().bind('mouseover', function(event) { event.target.tippy.show(); });\n\n cy.elements().unbind('mouseout');\n cy.elements().bind('mouseout', function(event) { event.target.tippy.hide(); });\n // document.querySelector('#cypng').setAttribute('src', cy.png());\n});\n\n </script>\n</head>\n\n<style>\n #cy {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0px;\n left: 0px;\n }\n a {\n color: #d0bb46\n }\n</style>\n\n<body>\n <div id=\"cy\"></div>\n</body>\n</html>\n";
2
+ //# sourceMappingURL=_template-bundled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_template-bundled.d.ts","sourceRoot":"","sources":["../../../src/commands/cytoscapejs/_template-bundled.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,uBAAuB,s/LAmLnC,CAAC"}
@@ -0,0 +1,182 @@
1
+ // AUTO-GENERATED by scripts/bundle-templates.mjs — do not edit.
2
+ export const CYTOSCAPE_HTML_TEMPLATE = `<!doctype html>
3
+
4
+ <html>
5
+
6
+ <head>
7
+ <title>Galaxy Workflow</title>
8
+ <script src="https://unpkg.com/cytoscape@3.33.2/dist/cytoscape.min.js"></script>
9
+ <script src="https://unpkg.com/dagre@0.8.5/dist/dagre.min.js"></script>
10
+ <script src="https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js"></script>
11
+ <script src="https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script>
12
+ <script src="https://unpkg.com/cytoscape-popper@2.0.0/cytoscape-popper.js"></script>
13
+ <script src="https://unpkg.com/tippy.js@6.3.7/dist/tippy.umd.min.js"></script>
14
+ <link rel="stylesheet" href="https://unpkg.com/tippy.js@6.3.7/dist/tippy.css" />
15
+ <script>
16
+ document.addEventListener("DOMContentLoaded", function() {
17
+ var requestedLayout = $layout;
18
+ var dagreReady = (typeof cytoscapeDagre !== 'undefined');
19
+ if (dagreReady && cytoscape.use) {
20
+ try { cytoscape.use(cytoscapeDagre); } catch (e) { /* already registered */ }
21
+ }
22
+ var layoutConfig = (function(name) {
23
+ if (name === 'dagre') {
24
+ return dagreReady
25
+ ? { name: 'dagre', rankDir: 'LR', nodeSep: 40, rankSep: 80 }
26
+ : { name: 'preset' };
27
+ }
28
+ if (name === 'breadthfirst') return { name: 'breadthfirst', directed: true, spacingFactor: 1.2 };
29
+ if (name === 'grid') return { name: 'grid' };
30
+ if (name === 'cose') return { name: 'cose' };
31
+ if (name === 'random') return { name: 'random' };
32
+ if (name === 'topological') return { name: 'preset' };
33
+ return { name: 'preset' };
34
+ })(requestedLayout);
35
+ var cy = cytoscape({
36
+ container: document.getElementById('cy'),
37
+ elements: $elements,
38
+ layout: layoutConfig,
39
+ // so we can see the ids
40
+ style: [
41
+ {
42
+ selector: 'node',
43
+ style: {
44
+ 'label': 'data(label)'
45
+ }
46
+ },
47
+ {
48
+ selector: 'edge',
49
+ style: {
50
+ 'curve-style': 'bezier',
51
+ 'target-arrow-shape': 'vee',
52
+ 'arrow-scale': 2
53
+ }
54
+ },
55
+ {
56
+ selector: ".input",
57
+ style: {
58
+ shape: 'diamond',
59
+ 'background-color': '#d0bb46'
60
+ }
61
+ },
62
+ {
63
+ selector: ".runnable",
64
+ style: {
65
+ shape: 'round-rectangle',
66
+ 'background-color': '#2c3143'
67
+ }
68
+ },
69
+ {
70
+ selector: 'edge.mapover_1',
71
+ style: { width: 4, 'line-color': '#5a8' }
72
+ },
73
+ {
74
+ selector: 'edge.mapover_2',
75
+ style: { width: 6, 'line-color': '#5a8' }
76
+ },
77
+ {
78
+ selector: 'edge.mapover_3',
79
+ style: { width: 8, 'line-color': '#5a8' }
80
+ },
81
+ {
82
+ selector: 'edge.reduction',
83
+ style: {
84
+ 'line-style': 'dashed',
85
+ 'line-color': '#a55',
86
+ 'target-arrow-shape': 'tee',
87
+ 'target-arrow-color': '#a55'
88
+ }
89
+ }
90
+ ]
91
+ });
92
+
93
+ function makePopper(ele) {
94
+ let ref = ele.popperRef(); // used only for positioning
95
+ let dummyDomEle = document.createElement('div');
96
+
97
+ ele.tippy = tippy(dummyDomEle, { // tippy options:
98
+ getReferenceClientRect: ref.getBoundingClientRect.bind(ref),
99
+ content: function() {
100
+ let content = document.createElement('div');
101
+
102
+ let innerHTML = '';
103
+ if(ele.isNode()) {
104
+ let stepType = ele.data("step_type");
105
+ innerHTML += "<p><i>Step Type:</i> " + stepType + "</p>";
106
+ let toolId = ele.data("tool_id");
107
+ if (toolId) {
108
+ innerHTML += "<p><i>ToolID:</i> " + toolId + "</p>";
109
+ }
110
+ let repoLink = ele.data("repo_link");
111
+ if (repoLink) {
112
+ innerHTML += "<a href=" + repoLink + '">Visit Tool Shed Repository</a>';
113
+ }
114
+ let doc = ele.data('doc');
115
+ if (doc) {
116
+ innerHTML += "<p>" + doc + "</p>";
117
+ }
118
+ } else {
119
+ let output = ele.data("output");
120
+ let input = ele.data("input");
121
+ if(output) {
122
+ innerHTML += "Output named " + output + " connects to " + input;
123
+ } else {
124
+ innerHTML += "Connected to input " + input;
125
+ }
126
+ let mapDepth = ele.data("map_depth");
127
+ if (mapDepth) {
128
+ let mapping = ele.data("mapping");
129
+ innerHTML += "<p><i>Map depth:</i> " + mapDepth + (mapping ? " (" + mapping + ")" : "") + "</p>";
130
+ }
131
+ if (ele.data("reduction")) {
132
+ innerHTML += "<p><i>Reduction:</i> list → multi-data</p>";
133
+ }
134
+ }
135
+ content.innerHTML = innerHTML;
136
+
137
+ return content;
138
+ },
139
+ delay: [0,1000],
140
+ interactive: true,
141
+ placement: 'bottom',
142
+ trigger: 'manual', // probably want manual mode
143
+ appendTo: document.body
144
+ });
145
+ }
146
+
147
+ cy.ready(function() {
148
+ cy.elements().forEach(function(ele) {
149
+ makePopper(ele);
150
+ });
151
+ });
152
+
153
+ cy.elements().unbind('mouseover');
154
+ cy.elements().bind('mouseover', function(event) { event.target.tippy.show(); });
155
+
156
+ cy.elements().unbind('mouseout');
157
+ cy.elements().bind('mouseout', function(event) { event.target.tippy.hide(); });
158
+ // document.querySelector('#cypng').setAttribute('src', cy.png());
159
+ });
160
+
161
+ </script>
162
+ </head>
163
+
164
+ <style>
165
+ #cy {
166
+ width: 100%;
167
+ height: 100%;
168
+ position: absolute;
169
+ top: 0px;
170
+ left: 0px;
171
+ }
172
+ a {
173
+ color: #d0bb46
174
+ }
175
+ </style>
176
+
177
+ <body>
178
+ <div id="cy"></div>
179
+ </body>
180
+ </html>
181
+ `;
182
+ //# sourceMappingURL=_template-bundled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_template-bundled.js","sourceRoot":"","sources":["../../../src/commands/cytoscapejs/_template-bundled.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmLtC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CytoscapeElements, LayoutName } from "@galaxy-tool-util/schema";
2
+ export interface CytoscapeJsCommandOptions {
3
+ output?: string;
4
+ html?: boolean;
5
+ json?: boolean;
6
+ annotateConnections?: boolean;
7
+ cacheDir?: string;
8
+ layout?: string;
9
+ }
10
+ export declare function renderHtml(elements: CytoscapeElements, layout?: LayoutName): string;
11
+ export declare function runCytoscapeJs(filePath: string, opts: CytoscapeJsCommandOptions): Promise<void>;
12
+ //# sourceMappingURL=cytoscapejs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cytoscapejs.d.ts","sourceRoot":"","sources":["../../src/commands/cytoscapejs.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAO9E,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,GAAE,UAAqB,GAAG,MAAM,CAQ7F;AAmBD,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `gxwf cytoscapejs` — render a Galaxy workflow as Cytoscape.js elements,
3
+ * either as JSON (default / `.json` output) or as a standalone HTML viewer
4
+ * (`.html` output).
5
+ *
6
+ * Port of gxformat2's `gxwf-viz` CLI; diverges from Python by defaulting to
7
+ * stdout JSON when no output path is given.
8
+ */
9
+ import { cytoscapeElements, elementsToList, isLayoutName } from "@galaxy-tool-util/schema";
10
+ import { writeFile } from "node:fs/promises";
11
+ import { resolveEdgeAnnotations } from "./annotate-connections.js";
12
+ import { CYTOSCAPE_HTML_TEMPLATE } from "./cytoscapejs/_template-bundled.js";
13
+ import { readWorkflowFile } from "./workflow-io.js";
14
+ export function renderHtml(elements, layout = "preset") {
15
+ const elementsJson = JSON.stringify(elementsToList(elements));
16
+ // Python uses string.Template.safe_substitute(...). Tokens are $elements
17
+ // and $layout (a quoted string the template embeds inside `layout: { name: ... }`).
18
+ return CYTOSCAPE_HTML_TEMPLATE.replaceAll("$elements", elementsJson).replaceAll("$layout", JSON.stringify(layout));
19
+ }
20
+ function chooseFormat(opts) {
21
+ if (opts.html)
22
+ return "html";
23
+ if (opts.json)
24
+ return "json";
25
+ if (opts.output?.endsWith(".html"))
26
+ return "html";
27
+ return "json";
28
+ }
29
+ function resolveLayout(raw) {
30
+ if (raw == null)
31
+ return "preset";
32
+ if (!isLayoutName(raw)) {
33
+ throw new Error(`Unknown --layout "${raw}". Valid values: preset, topological, dagre, breadthfirst, grid, cose, random.`);
34
+ }
35
+ return raw;
36
+ }
37
+ export async function runCytoscapeJs(filePath, opts) {
38
+ const data = await readWorkflowFile(filePath);
39
+ if (!data)
40
+ return;
41
+ const layout = resolveLayout(opts.layout);
42
+ const edgeAnnotations = opts.annotateConnections
43
+ ? await resolveEdgeAnnotations(data, { cacheDir: opts.cacheDir })
44
+ : undefined;
45
+ const elements = cytoscapeElements(data, { edgeAnnotations, layout });
46
+ const format = chooseFormat(opts);
47
+ // JSON shape: bare list when layout=preset (Python parity), wrapped
48
+ // {elements, layout} when caller opted in to a non-default layout. The
49
+ // wrapper carries the hint so downstream consumers (e.g. gxwf-ui) can honor
50
+ // it without sniffing.
51
+ const jsonPayload = layout === "preset"
52
+ ? elementsToList(elements)
53
+ : { elements: elementsToList(elements), layout: { name: layout } };
54
+ const content = format === "html" ? renderHtml(elements, layout) : JSON.stringify(jsonPayload, null, 2);
55
+ if (!opts.output) {
56
+ process.stdout.write(content + "\n");
57
+ return;
58
+ }
59
+ await writeFile(opts.output, content + "\n", "utf-8");
60
+ console.error(`Cytoscape ${format.toUpperCase()} written to ${opts.output}`);
61
+ }
62
+ //# sourceMappingURL=cytoscapejs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cytoscapejs.js","sourceRoot":"","sources":["../../src/commands/cytoscapejs.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  export interface MermaidCommandOptions {
2
2
  output?: string;
3
3
  comments?: boolean;
4
+ annotateConnections?: boolean;
5
+ cacheDir?: string;
4
6
  }
5
7
  export declare function runMermaid(filePath: string, opts: MermaidCommandOptions): Promise<void>;
6
8
  //# sourceMappingURL=mermaid.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../src/commands/mermaid.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB7F"}
1
+ {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../src/commands/mermaid.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB7F"}
@@ -4,11 +4,15 @@
4
4
  import { workflowToMermaid } from "@galaxy-tool-util/schema";
5
5
  import { writeFile } from "node:fs/promises";
6
6
  import { readWorkflowFile } from "./workflow-io.js";
7
+ import { resolveEdgeAnnotations } from "./annotate-connections.js";
7
8
  export async function runMermaid(filePath, opts) {
8
9
  const data = await readWorkflowFile(filePath);
9
10
  if (!data)
10
11
  return;
11
- const diagram = workflowToMermaid(data, { comments: opts.comments });
12
+ const edgeAnnotations = opts.annotateConnections
13
+ ? await resolveEdgeAnnotations(data, { cacheDir: opts.cacheDir })
14
+ : undefined;
15
+ const diagram = workflowToMermaid(data, { comments: opts.comments, edgeAnnotations });
12
16
  if (!opts.output) {
13
17
  process.stdout.write(diagram + "\n");
14
18
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../../src/commands/mermaid.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAOpD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,IAA2B;IAC5E,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAErE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACzC,CAAC,CAAC,kBAAkB,OAAO,YAAY;QACvC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,OAAO,CAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../../src/commands/mermaid.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AASnE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,IAA2B;IAC5E,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,MAAM,eAAe,GAAG,IAAI,CAAC,mBAAmB;QAC9C,CAAC,CAAC,MAAM,sBAAsB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjE,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC;IAEtF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACzC,CAAC,CAAC,kBAAkB,OAAO,YAAY;QACvC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,OAAO,CAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type ParsedTool } from "@galaxy-tool-util/schema";
2
+ export interface SummarizeOptions {
3
+ version?: string;
4
+ output?: string;
5
+ cacheDir?: string;
6
+ }
7
+ export interface GalaxyToolSummaryManifest {
8
+ schema_version: 1;
9
+ tool_id: string;
10
+ tool_version: string | null;
11
+ cache_key: string;
12
+ source: {
13
+ kind: "toolshed" | "galaxy" | "local" | "orphan" | "unknown";
14
+ label: string;
15
+ url: string;
16
+ cached_at: string | null;
17
+ };
18
+ artifacts: {
19
+ parsed_tool_path: string;
20
+ raw_tool_source_path: string | null;
21
+ };
22
+ parsed_tool: ParsedTool;
23
+ input_schemas: {
24
+ workflow_step: unknown | null;
25
+ workflow_step_linked: unknown | null;
26
+ };
27
+ warnings: string[];
28
+ }
29
+ export declare function buildToolSummaryManifest(toolId: string, opts: SummarizeOptions): Promise<GalaxyToolSummaryManifest | null>;
30
+ export declare function runSummarize(toolId: string, opts: SummarizeOptions): Promise<void>;
31
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../../src/commands/summarize.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,UAAU,EAGhB,MAAM,0BAA0B,CAAC;AAIlC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QACN,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;QAC7D,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,SAAS,EAAE;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;KACrC,CAAC;IACF,WAAW,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE;QACb,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;QAC9B,oBAAoB,EAAE,OAAO,GAAG,IAAI,CAAC;KACtC,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA+BD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAwC3C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUxF"}
@@ -0,0 +1,85 @@
1
+ import { join } from "node:path";
2
+ import { writeFile } from "node:fs/promises";
3
+ import { getCacheDir, makeNodeToolCache } from "@galaxy-tool-util/core/node";
4
+ import { createFieldModel, } from "@galaxy-tool-util/schema";
5
+ import * as JSONSchema from "effect/JSONSchema";
6
+ import { isResolveError, loadCachedTool } from "./resolve-tool.js";
7
+ function sourceKind(label) {
8
+ if (label === "api")
9
+ return "toolshed";
10
+ if (label === "galaxy" || label === "local" || label === "orphan")
11
+ return label;
12
+ return "unknown";
13
+ }
14
+ function inputSchemaFor(tool, rep, warnings) {
15
+ const bundle = {
16
+ parameters: tool.inputs,
17
+ };
18
+ const effectSchema = createFieldModel(bundle, rep);
19
+ if (effectSchema === undefined) {
20
+ warnings.push(`${rep} input schema could not be generated for this tool`);
21
+ return null;
22
+ }
23
+ try {
24
+ return JSONSchema.make(effectSchema);
25
+ }
26
+ catch (err) {
27
+ warnings.push(`${rep} input schema generation failed: ${err instanceof Error ? err.message : String(err)}`);
28
+ return null;
29
+ }
30
+ }
31
+ export async function buildToolSummaryManifest(toolId, opts) {
32
+ const cacheDir = getCacheDir(opts.cacheDir);
33
+ const cache = makeNodeToolCache({ cacheDir });
34
+ await cache.index.load();
35
+ const result = await loadCachedTool(cache, toolId, opts.version);
36
+ if (isResolveError(result)) {
37
+ if (result.kind === "no_version") {
38
+ console.error(`No version specified for tool: ${toolId}`);
39
+ }
40
+ else {
41
+ console.error(`Tool not found in cache: ${toolId}. Run 'galaxy-tool-cache add' first.`);
42
+ }
43
+ process.exitCode = 1;
44
+ return null;
45
+ }
46
+ const indexEntry = (await cache.index.listAll()).find((entry) => entry.cache_key === result.key);
47
+ const warnings = [];
48
+ const manifest = {
49
+ schema_version: 1,
50
+ tool_id: result.tool.id,
51
+ tool_version: result.tool.version,
52
+ cache_key: result.key,
53
+ source: {
54
+ kind: sourceKind(indexEntry?.source),
55
+ label: indexEntry?.source ?? "unknown",
56
+ url: indexEntry?.source_url ?? "",
57
+ cached_at: indexEntry?.cached_at ?? null,
58
+ },
59
+ artifacts: {
60
+ parsed_tool_path: join(cacheDir, `${result.key}.json`),
61
+ raw_tool_source_path: null,
62
+ },
63
+ parsed_tool: result.tool,
64
+ input_schemas: {
65
+ workflow_step: inputSchemaFor(result.tool, "workflow_step", warnings),
66
+ workflow_step_linked: inputSchemaFor(result.tool, "workflow_step_linked", warnings),
67
+ },
68
+ warnings,
69
+ };
70
+ return manifest;
71
+ }
72
+ export async function runSummarize(toolId, opts) {
73
+ const manifest = await buildToolSummaryManifest(toolId, opts);
74
+ if (manifest === null)
75
+ return;
76
+ const output = `${JSON.stringify(manifest, null, 2)}\n`;
77
+ if (opts.output) {
78
+ await writeFile(opts.output, output);
79
+ console.log(`Summary written to ${opts.output}`);
80
+ }
81
+ else {
82
+ process.stdout.write(output);
83
+ }
84
+ }
85
+ //# sourceMappingURL=summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.js","sourceRoot":"","sources":["../../src/commands/summarize.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ export interface ValidateWorkflowOptions extends StrictOptions {
11
11
  toolSchemaDir?: string;
12
12
  json?: boolean;
13
13
  reportHtml?: string | boolean;
14
+ connections?: boolean;
14
15
  }
15
16
  /** Run Effect Schema decode on raw workflow data and return structural decode failures. */
16
17
  export declare function decodeStructureErrors(data: Record<string, unknown>, format: WorkflowFormat): string[];
@@ -1 +1 @@
1
- {"version":3,"file":"validate-workflow.d.ts","sourceRoot":"","sources":["../../src/commands/validate-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAmBL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG/E,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEtD,MAAM,WAAW,uBAAwB,SAAQ,aAAa;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAOD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,cAAc,GACrB,MAAM,EAAE,CAaV;AAED,YAAY,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG7F,OAAO,KAAK,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE7F,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgIf;AAID,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,SAAK,EACX,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAGjC;AA4GD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,SAAK,EACX,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAGjC;AAmJD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,cAAc,EACtB,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB"}
1
+ {"version":3,"file":"validate-workflow.d.ts","sourceRoot":"","sources":["../../src/commands/validate-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAmBL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAK/E,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEtD,MAAM,WAAW,uBAAwB,SAAQ,aAAa;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAOD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,cAAc,GACrB,MAAM,EAAE,CAaV;AAED,YAAY,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG7F,OAAO,KAAK,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE7F,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA4If;AAwBD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,SAAK,EACX,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAGjC;AA4GD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,SAAK,EACX,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAGjC;AAmJD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,cAAc,EACtB,aAAa,CAAC,EAAE,gBAAgB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB"}