@galaxy-tool-util/cli 1.1.0 → 1.2.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/commands/annotate-connections.d.ts +30 -0
- package/dist/commands/annotate-connections.d.ts.map +1 -0
- package/dist/commands/annotate-connections.js +42 -0
- package/dist/commands/annotate-connections.js.map +1 -0
- package/dist/commands/connection-validation.d.ts +20 -0
- package/dist/commands/connection-validation.d.ts.map +1 -0
- package/dist/commands/connection-validation.js +26 -0
- package/dist/commands/connection-validation.js.map +1 -0
- package/dist/commands/cytoscapejs/_template-bundled.d.ts +2 -0
- package/dist/commands/cytoscapejs/_template-bundled.d.ts.map +1 -0
- package/dist/commands/cytoscapejs/_template-bundled.js +182 -0
- package/dist/commands/cytoscapejs/_template-bundled.js.map +1 -0
- package/dist/commands/cytoscapejs.d.ts +12 -0
- package/dist/commands/cytoscapejs.d.ts.map +1 -0
- package/dist/commands/cytoscapejs.js +62 -0
- package/dist/commands/cytoscapejs.js.map +1 -0
- package/dist/commands/mermaid.d.ts +2 -0
- package/dist/commands/mermaid.d.ts.map +1 -1
- package/dist/commands/mermaid.js +5 -1
- package/dist/commands/mermaid.js.map +1 -1
- package/dist/commands/validate-workflow.d.ts +1 -0
- package/dist/commands/validate-workflow.d.ts.map +1 -1
- package/dist/commands/validate-workflow.js +38 -3
- package/dist/commands/validate-workflow.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/meta/extract-spec.d.ts +13 -0
- package/dist/meta/extract-spec.d.ts.map +1 -0
- package/dist/meta/extract-spec.js +90 -0
- package/dist/meta/extract-spec.js.map +1 -0
- package/dist/meta/index.d.ts +8 -0
- package/dist/meta/index.d.ts.map +1 -0
- package/dist/meta/index.js +21 -0
- package/dist/meta/index.js.map +1 -0
- package/dist/meta/spec-types.d.ts +40 -0
- package/dist/meta/spec-types.d.ts.map +1 -0
- package/dist/meta/spec-types.js +11 -0
- package/dist/meta/spec-types.js.map +1 -0
- package/dist/meta/specs.d.ts +4 -0
- package/dist/meta/specs.d.ts.map +1 -0
- package/dist/meta/specs.js +10 -0
- package/dist/meta/specs.js.map +1 -0
- package/dist/meta/types.d.ts +55 -0
- package/dist/meta/types.d.ts.map +1 -0
- package/dist/meta/types.js +9 -0
- package/dist/meta/types.js.map +1 -0
- package/dist/meta-build.d.ts +13 -0
- package/dist/meta-build.d.ts.map +1 -0
- package/dist/meta-build.js +60 -0
- package/dist/meta-build.js.map +1 -0
- package/dist/programs/galaxy-tool-cache.d.ts +5 -1
- package/dist/programs/galaxy-tool-cache.d.ts.map +1 -1
- package/dist/programs/galaxy-tool-cache.js +12 -56
- package/dist/programs/galaxy-tool-cache.js.map +1 -1
- package/dist/programs/gxwf.d.ts +7 -1
- package/dist/programs/gxwf.d.ts.map +1 -1
- package/dist/programs/gxwf.js +36 -184
- package/dist/programs/gxwf.js.map +1 -1
- package/dist/spec/build-program.d.ts +12 -0
- package/dist/spec/build-program.d.ts.map +1 -0
- package/dist/spec/build-program.js +102 -0
- package/dist/spec/build-program.js.map +1 -0
- package/package.json +10 -4
- package/spec/galaxy-tool-cache.json +152 -0
- 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":"
|
|
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"}
|
package/dist/commands/mermaid.js
CHANGED
|
@@ -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
|
|
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;
|
|
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"}
|
|
@@ -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;
|
|
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"}
|
|
@@ -9,6 +9,7 @@ import { renderStepResults } from "./render-results.js";
|
|
|
9
9
|
import { readWorkflowFile, resolveFormat } from "./workflow-io.js";
|
|
10
10
|
import { resolveStrictOptions } from "./strict-options.js";
|
|
11
11
|
import { writeReportHtml } from "./report-output.js";
|
|
12
|
+
import { buildConnectionReport } from "./connection-validation.js";
|
|
12
13
|
function formatIssues(error) {
|
|
13
14
|
const issues = ParseResult.ArrayFormatter.formatErrorSync(error);
|
|
14
15
|
return issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
@@ -115,32 +116,66 @@ export async function runValidateWorkflow(filePath, opts) {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
const stateOk = !results.some((r) => r.status === "fail");
|
|
119
|
+
let connectionReport = null;
|
|
120
|
+
if (opts.connections) {
|
|
121
|
+
connectionReport = await buildConnectionReport(data, cache);
|
|
122
|
+
}
|
|
123
|
+
const connectionsOk = connectionReport === null || connectionReport.valid;
|
|
118
124
|
if (opts.json || opts.reportHtml) {
|
|
119
125
|
const report = buildSingleValidationReport(filePath, results, {
|
|
120
126
|
structure_errors: structureErrors,
|
|
121
127
|
encoding_errors: encodingErrors,
|
|
122
128
|
});
|
|
129
|
+
if (connectionReport !== null) {
|
|
130
|
+
report.connection_report = connectionReport;
|
|
131
|
+
}
|
|
123
132
|
if (opts.json) {
|
|
124
133
|
console.log(JSON.stringify(report, null, 2));
|
|
125
134
|
}
|
|
126
135
|
await writeReportHtml("validate", report, opts.reportHtml);
|
|
127
|
-
process.exitCode = structOk && stateOk ? 0 : 1;
|
|
136
|
+
process.exitCode = structOk && stateOk && connectionsOk ? 0 : 1;
|
|
128
137
|
return;
|
|
129
138
|
}
|
|
130
139
|
if (results.length === 0) {
|
|
131
140
|
console.log("No tool steps to validate state for.");
|
|
132
|
-
|
|
141
|
+
if (connectionReport !== null)
|
|
142
|
+
printConnectionReport(connectionReport);
|
|
143
|
+
process.exitCode = structOk && connectionsOk ? 0 : 1;
|
|
133
144
|
return;
|
|
134
145
|
}
|
|
135
146
|
const { validated, skipped } = renderStepResults(results);
|
|
136
147
|
console.log(`\nTool state: ${validated} validated, ${skipped} skipped`);
|
|
148
|
+
if (connectionReport !== null)
|
|
149
|
+
printConnectionReport(connectionReport);
|
|
137
150
|
// --- strict state: promote skips to failures ---
|
|
138
151
|
if (strict.strictState && results.some((r) => r.status !== "ok" && r.status !== "fail")) {
|
|
139
152
|
console.error("Strict state: skipped steps not allowed");
|
|
140
153
|
process.exitCode = 2;
|
|
141
154
|
return;
|
|
142
155
|
}
|
|
143
|
-
process.exitCode = structOk && stateOk ? 0 : 1;
|
|
156
|
+
process.exitCode = structOk && stateOk && connectionsOk ? 0 : 1;
|
|
157
|
+
}
|
|
158
|
+
function printConnectionReport(report) {
|
|
159
|
+
const { ok = 0, invalid = 0, skip = 0 } = report.summary;
|
|
160
|
+
console.log(`\nConnections: ${report.valid ? "OK" : "INVALID"} — ${ok} ok, ${invalid} invalid, ${skip} skip`);
|
|
161
|
+
if (!report.has_details)
|
|
162
|
+
return;
|
|
163
|
+
for (const sr of report.step_results) {
|
|
164
|
+
if (sr.errors.length === 0 && sr.connections.every((c) => c.status === "ok"))
|
|
165
|
+
continue;
|
|
166
|
+
const label = sr.tool_id ? `${sr.step} (${sr.tool_id})` : sr.step;
|
|
167
|
+
console.log(` step ${label}${sr.map_over ? ` [map_over=${sr.map_over}]` : ""}`);
|
|
168
|
+
for (const e of sr.errors)
|
|
169
|
+
console.log(` error: ${e}`);
|
|
170
|
+
for (const cr of sr.connections) {
|
|
171
|
+
if (cr.status === "ok")
|
|
172
|
+
continue;
|
|
173
|
+
const arrow = `${cr.source_step}/${cr.source_output} -> ${cr.target_input}`;
|
|
174
|
+
console.log(` ${cr.status}: ${arrow}`);
|
|
175
|
+
for (const e of cr.errors)
|
|
176
|
+
console.log(` ${e}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
144
179
|
}
|
|
145
180
|
// --- Native validation ---
|
|
146
181
|
export async function validateNativeSteps(data, cache, prefix = "", expansionOpts) {
|