@galaxy-tool-util/core 0.1.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 (42) hide show
  1. package/README.md +13 -0
  2. package/dist/cache/cache-index.d.ts +36 -0
  3. package/dist/cache/cache-index.d.ts.map +1 -0
  4. package/dist/cache/cache-index.js +87 -0
  5. package/dist/cache/cache-index.js.map +1 -0
  6. package/dist/cache/cache-key.d.ts +6 -0
  7. package/dist/cache/cache-key.d.ts.map +1 -0
  8. package/dist/cache/cache-key.js +10 -0
  9. package/dist/cache/cache-key.js.map +1 -0
  10. package/dist/cache/index.d.ts +7 -0
  11. package/dist/cache/index.d.ts.map +1 -0
  12. package/dist/cache/index.js +5 -0
  13. package/dist/cache/index.js.map +1 -0
  14. package/dist/cache/tool-cache.d.ts +48 -0
  15. package/dist/cache/tool-cache.d.ts.map +1 -0
  16. package/dist/cache/tool-cache.js +119 -0
  17. package/dist/cache/tool-cache.js.map +1 -0
  18. package/dist/cache/tool-id.d.ts +26 -0
  19. package/dist/cache/tool-id.d.ts.map +1 -0
  20. package/dist/cache/tool-id.js +34 -0
  21. package/dist/cache/tool-id.js.map +1 -0
  22. package/dist/client/index.d.ts +2 -0
  23. package/dist/client/index.d.ts.map +1 -0
  24. package/dist/client/index.js +2 -0
  25. package/dist/client/index.js.map +1 -0
  26. package/dist/client/toolshed.d.ts +31 -0
  27. package/dist/client/toolshed.d.ts.map +1 -0
  28. package/dist/client/toolshed.js +60 -0
  29. package/dist/client/toolshed.js.map +1 -0
  30. package/dist/index.d.ts +28 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +26 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/models/parsed-tool.d.ts +46 -0
  35. package/dist/models/parsed-tool.d.ts.map +1 -0
  36. package/dist/models/parsed-tool.js +41 -0
  37. package/dist/models/parsed-tool.js.map +1 -0
  38. package/dist/tool-info.d.ts +30 -0
  39. package/dist/tool-info.d.ts.map +1 -0
  40. package/dist/tool-info.js +78 -0
  41. package/dist/tool-info.js.map +1 -0
  42. package/package.json +39 -0
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # @galaxy-tool-util/core
2
+
3
+ Galaxy tool cache, ToolShed client, and ParsedTool models.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @galaxy-tool-util/core
9
+ ```
10
+
11
+ ## License
12
+
13
+ MIT
@@ -0,0 +1,36 @@
1
+ /** Metadata for a single cached tool entry. */
2
+ export interface CacheIndexEntry {
3
+ tool_id: string;
4
+ tool_version: string;
5
+ /** How the tool was fetched: "api" (ToolShed), "galaxy", or "local". */
6
+ source: string;
7
+ source_url: string;
8
+ /** ISO 8601 timestamp of when the tool was cached. */
9
+ cached_at: string;
10
+ }
11
+ /** Serialized cache index structure (persisted as index.json). */
12
+ export interface CacheIndexData {
13
+ entries: Record<string, CacheIndexEntry>;
14
+ }
15
+ /**
16
+ * Manages the cache index file (index.json) that tracks metadata about cached tools.
17
+ * Supports lazy loading, add/remove, and listing operations.
18
+ */
19
+ export declare class CacheIndex {
20
+ readonly cacheDir: string;
21
+ private indexPath;
22
+ private entries;
23
+ constructor(cacheDir: string);
24
+ private getEntries;
25
+ private loadSync;
26
+ load(): Promise<void>;
27
+ save(): Promise<void>;
28
+ add(key: string, toolId: string, toolVersion: string, source: string, sourceUrl?: string): Promise<void>;
29
+ remove(key: string): Promise<void>;
30
+ has(key: string): boolean;
31
+ listAll(): Array<CacheIndexEntry & {
32
+ cache_key: string;
33
+ }>;
34
+ clear(): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=cache-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-index.d.ts","sourceRoot":"","sources":["../../src/cache/cache-index.ts"],"names":[],"mappings":"AAIA,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,UAAU;IAIT,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAHrC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAgD;gBAE1C,QAAQ,EAAE,MAAM;IAIrC,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,QAAQ;IAcV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAerB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,GAAG,CACP,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAW,GACrB,OAAO,CAAC,IAAI,CAAC;IAWV,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,OAAO,IAAI,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAOnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -0,0 +1,87 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ /**
5
+ * Manages the cache index file (index.json) that tracks metadata about cached tools.
6
+ * Supports lazy loading, add/remove, and listing operations.
7
+ */
8
+ export class CacheIndex {
9
+ cacheDir;
10
+ indexPath;
11
+ entries = null;
12
+ constructor(cacheDir) {
13
+ this.cacheDir = cacheDir;
14
+ this.indexPath = join(cacheDir, "index.json");
15
+ }
16
+ getEntries() {
17
+ if (this.entries === null) {
18
+ this.entries = this.loadSync();
19
+ }
20
+ return this.entries;
21
+ }
22
+ loadSync() {
23
+ if (!existsSync(this.indexPath)) {
24
+ return {};
25
+ }
26
+ try {
27
+ const raw = readFileSync(this.indexPath, "utf-8");
28
+ const data = JSON.parse(raw);
29
+ return data.entries ?? {};
30
+ }
31
+ catch (err) {
32
+ console.debug(`Failed to load cache index (sync): ${err}`);
33
+ return {};
34
+ }
35
+ }
36
+ async load() {
37
+ if (!existsSync(this.indexPath)) {
38
+ this.entries = {};
39
+ return;
40
+ }
41
+ try {
42
+ const raw = await readFile(this.indexPath, "utf-8");
43
+ const data = JSON.parse(raw);
44
+ this.entries = data.entries ?? {};
45
+ }
46
+ catch (err) {
47
+ console.debug(`Failed to load cache index: ${err}`);
48
+ this.entries = {};
49
+ }
50
+ }
51
+ async save() {
52
+ await mkdir(this.cacheDir, { recursive: true });
53
+ const data = { entries: this.getEntries() };
54
+ await writeFile(this.indexPath, JSON.stringify(data, null, 2));
55
+ }
56
+ async add(key, toolId, toolVersion, source, sourceUrl = "") {
57
+ this.getEntries()[key] = {
58
+ tool_id: toolId,
59
+ tool_version: toolVersion,
60
+ source,
61
+ source_url: sourceUrl,
62
+ cached_at: new Date().toISOString(),
63
+ };
64
+ await this.save();
65
+ }
66
+ async remove(key) {
67
+ const entries = this.getEntries();
68
+ if (key in entries) {
69
+ delete entries[key];
70
+ await this.save();
71
+ }
72
+ }
73
+ has(key) {
74
+ return key in this.getEntries();
75
+ }
76
+ listAll() {
77
+ return Object.entries(this.getEntries()).map(([key, entry]) => ({
78
+ cache_key: key,
79
+ ...entry,
80
+ }));
81
+ }
82
+ async clear() {
83
+ this.entries = {};
84
+ await this.save();
85
+ }
86
+ }
87
+ //# sourceMappingURL=cache-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-index.js","sourceRoot":"","sources":["../../src/cache/cache-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Compute a deterministic cache key (SHA-256 hex) for a tool.
3
+ * The key is derived from the ToolShed URL, TRS tool ID, and version.
4
+ */
5
+ export declare function cacheKey(toolshedUrl: string, trsToolId: string, toolVersion: string): string;
6
+ //# sourceMappingURL=cache-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-key.d.ts","sourceRoot":"","sources":["../../src/cache/cache-key.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAG5F"}
@@ -0,0 +1,10 @@
1
+ import { createHash } from "node:crypto";
2
+ /**
3
+ * Compute a deterministic cache key (SHA-256 hex) for a tool.
4
+ * The key is derived from the ToolShed URL, TRS tool ID, and version.
5
+ */
6
+ export function cacheKey(toolshedUrl, trsToolId, toolVersion) {
7
+ const raw = `${toolshedUrl}/${trsToolId}/${toolVersion}`;
8
+ return createHash("sha256").update(raw).digest("hex");
9
+ }
10
+ //# sourceMappingURL=cache-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-key.js","sourceRoot":"","sources":["../../src/cache/cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,WAAmB,EAAE,SAAiB,EAAE,WAAmB;IAClF,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;IACzD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { parseToolshedToolId, toolIdFromTrs } from "./tool-id.js";
2
+ export type { ToolCoordinates } from "./tool-id.js";
3
+ export { cacheKey } from "./cache-key.js";
4
+ export { CacheIndex } from "./cache-index.js";
5
+ export type { CacheIndexEntry, CacheIndexData } from "./cache-index.js";
6
+ export { ToolCache, getCacheDir, DEFAULT_CACHE_DIR, CACHE_DIR_ENV_VAR, DEFAULT_TOOLSHED_URL, TOOLSHED_URL_ENV_VAR, } from "./tool-cache.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EACL,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { parseToolshedToolId, toolIdFromTrs } from "./tool-id.js";
2
+ export { cacheKey } from "./cache-key.js";
3
+ export { CacheIndex } from "./cache-index.js";
4
+ export { ToolCache, getCacheDir, DEFAULT_CACHE_DIR, CACHE_DIR_ENV_VAR, DEFAULT_TOOLSHED_URL, TOOLSHED_URL_ENV_VAR, } from "./tool-cache.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { ParsedTool } from "../models/parsed-tool.js";
2
+ import { CacheIndex } from "./cache-index.js";
3
+ /** Default cache directory: `~/.galaxy/tool_info_cache`. */
4
+ export declare const DEFAULT_CACHE_DIR: string;
5
+ /** Environment variable to override the cache directory. */
6
+ export declare const CACHE_DIR_ENV_VAR = "GALAXY_TOOL_CACHE_DIR";
7
+ /** Default Galaxy ToolShed URL. */
8
+ export declare const DEFAULT_TOOLSHED_URL = "https://toolshed.g2.bx.psu.edu";
9
+ /** Environment variable to override the default ToolShed URL. */
10
+ export declare const TOOLSHED_URL_ENV_VAR = "GALAXY_TOOLSHED_URL";
11
+ /** Resolve cache directory: explicit override > env var > default. */
12
+ export declare function getCacheDir(override?: string): string;
13
+ interface ResolvedCoordinates {
14
+ toolshedUrl: string;
15
+ trsToolId: string;
16
+ version: string | null;
17
+ readableId: string;
18
+ }
19
+ /**
20
+ * Two-layer cache (memory + filesystem) for parsed Galaxy tool metadata.
21
+ * Resolves tool IDs to cache keys, loads/saves tool JSON, and manages the cache index.
22
+ */
23
+ export declare class ToolCache {
24
+ readonly cacheDir: string;
25
+ readonly defaultToolshedUrl: string;
26
+ readonly index: CacheIndex;
27
+ private memoryCache;
28
+ constructor(opts?: {
29
+ cacheDir?: string;
30
+ defaultToolshedUrl?: string;
31
+ });
32
+ resolveToolCoordinates(toolId: string, toolVersion?: string | null): ResolvedCoordinates;
33
+ private cachePath;
34
+ hasCached(toolId: string, toolVersion?: string | null): boolean;
35
+ loadCached(key: string): Promise<ParsedTool | null>;
36
+ saveTool(key: string, parsedTool: ParsedTool, toolId: string, toolVersion: string, source: string, sourceUrl?: string): Promise<void>;
37
+ listCached(): Array<{
38
+ cache_key: string;
39
+ tool_id: string;
40
+ tool_version: string;
41
+ source: string;
42
+ source_url: string;
43
+ cached_at: string;
44
+ }>;
45
+ clearCache(toolIdPrefix?: string): Promise<void>;
46
+ }
47
+ export {};
48
+ //# sourceMappingURL=tool-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-cache.d.ts","sourceRoot":"","sources":["../../src/cache/tool-cache.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAI9C,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,QAAgD,CAAC;AAC/E,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AACzD,mCAAmC;AACnC,eAAO,MAAM,oBAAoB,mCAAmC,CAAC;AACrE,iEAAiE;AACjE,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAE1D,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,UAAU,mBAAmB;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,OAAO,CAAC,WAAW,CAAiC;gBAExC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAAE;IAOrE,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,mBAAmB;IAkBxF,OAAO,CAAC,SAAS;IAIjB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAOzD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAqBnD,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAW,GACrB,OAAO,CAAC,IAAI,CAAC;IAQhB,UAAU,IAAI,KAAK,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAII,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAmBvD"}
@@ -0,0 +1,119 @@
1
+ import { readFile, writeFile, mkdir, unlink } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import * as S from "effect/Schema";
6
+ import { ParsedTool } from "../models/parsed-tool.js";
7
+ import { CacheIndex } from "./cache-index.js";
8
+ import { cacheKey } from "./cache-key.js";
9
+ import { parseToolshedToolId, toolIdFromTrs } from "./tool-id.js";
10
+ /** Default cache directory: `~/.galaxy/tool_info_cache`. */
11
+ export const DEFAULT_CACHE_DIR = join(homedir(), ".galaxy", "tool_info_cache");
12
+ /** Environment variable to override the cache directory. */
13
+ export const CACHE_DIR_ENV_VAR = "GALAXY_TOOL_CACHE_DIR";
14
+ /** Default Galaxy ToolShed URL. */
15
+ export const DEFAULT_TOOLSHED_URL = "https://toolshed.g2.bx.psu.edu";
16
+ /** Environment variable to override the default ToolShed URL. */
17
+ export const TOOLSHED_URL_ENV_VAR = "GALAXY_TOOLSHED_URL";
18
+ /** Resolve cache directory: explicit override > env var > default. */
19
+ export function getCacheDir(override) {
20
+ return override ?? process.env[CACHE_DIR_ENV_VAR] ?? DEFAULT_CACHE_DIR;
21
+ }
22
+ /**
23
+ * Two-layer cache (memory + filesystem) for parsed Galaxy tool metadata.
24
+ * Resolves tool IDs to cache keys, loads/saves tool JSON, and manages the cache index.
25
+ */
26
+ export class ToolCache {
27
+ cacheDir;
28
+ defaultToolshedUrl;
29
+ index;
30
+ memoryCache = new Map();
31
+ constructor(opts) {
32
+ this.cacheDir = getCacheDir(opts?.cacheDir);
33
+ this.defaultToolshedUrl =
34
+ opts?.defaultToolshedUrl ?? process.env[TOOLSHED_URL_ENV_VAR] ?? DEFAULT_TOOLSHED_URL;
35
+ this.index = new CacheIndex(this.cacheDir);
36
+ }
37
+ resolveToolCoordinates(toolId, toolVersion) {
38
+ const parsed = parseToolshedToolId(toolId);
39
+ if (parsed !== null) {
40
+ return {
41
+ toolshedUrl: parsed.toolshedUrl,
42
+ trsToolId: parsed.trsToolId,
43
+ version: toolVersion ?? parsed.toolVersion,
44
+ readableId: toolIdFromTrs(parsed.toolshedUrl, parsed.trsToolId),
45
+ };
46
+ }
47
+ return {
48
+ toolshedUrl: this.defaultToolshedUrl,
49
+ trsToolId: toolId,
50
+ version: toolVersion ?? null,
51
+ readableId: toolIdFromTrs(this.defaultToolshedUrl, toolId),
52
+ };
53
+ }
54
+ cachePath(key) {
55
+ return join(this.cacheDir, `${key}.json`);
56
+ }
57
+ hasCached(toolId, toolVersion) {
58
+ const coords = this.resolveToolCoordinates(toolId, toolVersion);
59
+ if (coords.version === null)
60
+ return false;
61
+ const key = cacheKey(coords.toolshedUrl, coords.trsToolId, coords.version);
62
+ return this.memoryCache.has(key) || existsSync(this.cachePath(key));
63
+ }
64
+ async loadCached(key) {
65
+ if (this.memoryCache.has(key)) {
66
+ return this.memoryCache.get(key);
67
+ }
68
+ const path = this.cachePath(key);
69
+ if (!existsSync(path))
70
+ return null;
71
+ try {
72
+ const raw = await readFile(path, "utf-8");
73
+ const data = JSON.parse(raw);
74
+ const parsedTool = S.decodeUnknownSync(ParsedTool)(data);
75
+ if (!this.index.has(key)) {
76
+ await this.index.add(key, data.id ?? "unknown", data.version ?? "unknown", "unknown");
77
+ }
78
+ this.memoryCache.set(key, parsedTool);
79
+ return parsedTool;
80
+ }
81
+ catch (err) {
82
+ console.debug(`Failed to load cached tool ${key}: ${err}`);
83
+ return null;
84
+ }
85
+ }
86
+ async saveTool(key, parsedTool, toolId, toolVersion, source, sourceUrl = "") {
87
+ await mkdir(this.cacheDir, { recursive: true });
88
+ const path = this.cachePath(key);
89
+ await writeFile(path, JSON.stringify(parsedTool, null, 2));
90
+ await this.index.add(key, toolId, toolVersion, source, sourceUrl);
91
+ this.memoryCache.set(key, parsedTool);
92
+ }
93
+ listCached() {
94
+ return this.index.listAll();
95
+ }
96
+ async clearCache(toolIdPrefix) {
97
+ if (toolIdPrefix === undefined) {
98
+ for (const entry of this.index.listAll()) {
99
+ const path = this.cachePath(entry.cache_key);
100
+ if (existsSync(path))
101
+ await unlink(path);
102
+ }
103
+ await this.index.clear();
104
+ this.memoryCache.clear();
105
+ }
106
+ else {
107
+ const prefix = toolIdPrefix.replace(/\*$/, "");
108
+ const toRemove = this.index.listAll().filter((e) => e.tool_id.startsWith(prefix));
109
+ for (const entry of toRemove) {
110
+ const path = this.cachePath(entry.cache_key);
111
+ if (existsSync(path))
112
+ await unlink(path);
113
+ await this.index.remove(entry.cache_key);
114
+ this.memoryCache.delete(entry.cache_key);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ //# sourceMappingURL=tool-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-cache.js","sourceRoot":"","sources":["../../src/cache/tool-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Parse and manipulate Galaxy toolshed tool IDs.
3
+ *
4
+ * Input format: toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version
5
+ * Or with scheme: https://toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version
6
+ */
7
+ /** Parsed components of a ToolShed tool ID. */
8
+ export interface ToolCoordinates {
9
+ /** ToolShed base URL (with https:// scheme). */
10
+ toolshedUrl: string;
11
+ /** TRS-style tool ID: `owner~repo~tool_name`. */
12
+ trsToolId: string;
13
+ /** Tool version, or null if not present in the ID. */
14
+ toolVersion: string | null;
15
+ }
16
+ /**
17
+ * Parse a full ToolShed tool ID into its components.
18
+ * Accepts both scheme-prefixed and bare formats:
19
+ * - `toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version`
20
+ * - `https://toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version`
21
+ * @returns Parsed coordinates, or null if the ID doesn't match the ToolShed format.
22
+ */
23
+ export declare function parseToolshedToolId(toolId: string): ToolCoordinates | null;
24
+ /** Reconstruct a human-readable tool ID from a ToolShed URL and TRS tool ID. */
25
+ export declare function toolIdFromTrs(toolshedUrl: string, trsToolId: string): string;
26
+ //# sourceMappingURL=tool-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-id.d.ts","sourceRoot":"","sources":["../../src/cache/tool-id.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAa1E;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI5E"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Parse and manipulate Galaxy toolshed tool IDs.
3
+ *
4
+ * Input format: toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version
5
+ * Or with scheme: https://toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version
6
+ */
7
+ /**
8
+ * Parse a full ToolShed tool ID into its components.
9
+ * Accepts both scheme-prefixed and bare formats:
10
+ * - `toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version`
11
+ * - `https://toolshed.g2.bx.psu.edu/repos/owner/repo/tool_name/version`
12
+ * @returns Parsed coordinates, or null if the ID doesn't match the ToolShed format.
13
+ */
14
+ export function parseToolshedToolId(toolId) {
15
+ if (!toolId.includes("/repos/")) {
16
+ return null;
17
+ }
18
+ const [toolshedBase, rest] = toolId.split("/repos/", 2);
19
+ const segments = rest.split("/");
20
+ if (segments.length < 3) {
21
+ return null;
22
+ }
23
+ const trsToolId = `${segments[0]}~${segments[1]}~${segments[2]}`;
24
+ const toolVersion = segments.length > 3 ? segments[3] : null;
25
+ const toolshedUrl = toolshedBase.startsWith("http") ? toolshedBase : `https://${toolshedBase}`;
26
+ return { toolshedUrl, trsToolId, toolVersion };
27
+ }
28
+ /** Reconstruct a human-readable tool ID from a ToolShed URL and TRS tool ID. */
29
+ export function toolIdFromTrs(toolshedUrl, trsToolId) {
30
+ const parts = trsToolId.split("~");
31
+ const base = toolshedUrl.replace("https://", "").replace("http://", "");
32
+ return `${base}/repos/${parts.join("/")}`;
33
+ }
34
+ //# sourceMappingURL=tool-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-id.js","sourceRoot":"","sources":["../../src/cache/tool-id.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,MAAM,WAAW,GAAG,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,YAAY,EAAE,CAAC;IAC/F,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AACjD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,SAAiB;IAClE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACxE,OAAO,GAAG,IAAI,UAAU,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { fetchFromToolShed, fetchFromGalaxy, ToolFetchError } from "./toolshed.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { fetchFromToolShed, fetchFromGalaxy, ToolFetchError } from "./toolshed.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { ParsedTool } from "../models/parsed-tool.js";
2
+ /** Error thrown when fetching a tool from a remote source fails. */
3
+ export declare class ToolFetchError extends Error {
4
+ /** The URL that was requested. */
5
+ readonly url: string;
6
+ /** HTTP status code, if the request reached the server. */
7
+ readonly statusCode?: number | undefined;
8
+ readonly _tag = "ToolFetchError";
9
+ constructor(message: string,
10
+ /** The URL that was requested. */
11
+ url: string,
12
+ /** HTTP status code, if the request reached the server. */
13
+ statusCode?: number | undefined);
14
+ }
15
+ /**
16
+ * Fetch parsed tool metadata from a ToolShed instance via its TRS API.
17
+ * @param toolshedUrl - Base URL of the ToolShed (e.g. `https://toolshed.g2.bx.psu.edu`)
18
+ * @param trsToolId - TRS-style tool ID (e.g. `owner~repo~tool_name`)
19
+ * @param toolVersion - Exact tool version string
20
+ * @param fetcher - Custom fetch implementation (defaults to globalThis.fetch)
21
+ */
22
+ export declare function fetchFromToolShed(toolshedUrl: string, trsToolId: string, toolVersion: string, fetcher?: typeof fetch): Promise<ParsedTool>;
23
+ /**
24
+ * Fetch parsed tool metadata from a Galaxy instance via its API.
25
+ * @param galaxyUrl - Base URL of the Galaxy instance (e.g. `https://usegalaxy.org`)
26
+ * @param toolId - Full tool ID (e.g. `toolshed.g2.bx.psu.edu/repos/devteam/fastqc/fastqc`)
27
+ * @param toolVersion - Tool version (optional, fetches latest if omitted)
28
+ * @param fetcher - Custom fetch implementation (defaults to globalThis.fetch)
29
+ */
30
+ export declare function fetchFromGalaxy(galaxyUrl: string, toolId: string, toolVersion?: string | null, fetcher?: typeof fetch): Promise<ParsedTool>;
31
+ //# sourceMappingURL=toolshed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolshed.d.ts","sourceRoot":"","sources":["../../src/client/toolshed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,oEAAoE;AACpE,qBAAa,cAAe,SAAQ,KAAK;IAIrC,kCAAkC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM;IAN9B,QAAQ,CAAC,IAAI,oBAAoB;gBAE/B,OAAO,EAAE,MAAM;IACf,kCAAkC;IACzB,GAAG,EAAE,MAAM;IACpB,2DAA2D;IAClD,UAAU,CAAC,EAAE,MAAM,YAAA;CAI/B;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAO,KAAwB,GACvC,OAAO,CAAC,UAAU,CAAC,CAgBrB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,OAAO,GAAE,OAAO,KAAwB,GACvC,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
@@ -0,0 +1,60 @@
1
+ import * as S from "effect/Schema";
2
+ import { ParsedTool } from "../models/parsed-tool.js";
3
+ /** Error thrown when fetching a tool from a remote source fails. */
4
+ export class ToolFetchError extends Error {
5
+ url;
6
+ statusCode;
7
+ _tag = "ToolFetchError";
8
+ constructor(message,
9
+ /** The URL that was requested. */
10
+ url,
11
+ /** HTTP status code, if the request reached the server. */
12
+ statusCode) {
13
+ super(message);
14
+ this.url = url;
15
+ this.statusCode = statusCode;
16
+ }
17
+ }
18
+ /**
19
+ * Fetch parsed tool metadata from a ToolShed instance via its TRS API.
20
+ * @param toolshedUrl - Base URL of the ToolShed (e.g. `https://toolshed.g2.bx.psu.edu`)
21
+ * @param trsToolId - TRS-style tool ID (e.g. `owner~repo~tool_name`)
22
+ * @param toolVersion - Exact tool version string
23
+ * @param fetcher - Custom fetch implementation (defaults to globalThis.fetch)
24
+ */
25
+ export async function fetchFromToolShed(toolshedUrl, trsToolId, toolVersion, fetcher = globalThis.fetch) {
26
+ const url = `${toolshedUrl}/api/tools/${trsToolId}/versions/${toolVersion}`;
27
+ const response = await fetcher(url, {
28
+ headers: { Accept: "application/json" },
29
+ signal: AbortSignal.timeout(30_000),
30
+ });
31
+ if (!response.ok) {
32
+ const body = await response.text().catch(() => "");
33
+ throw new ToolFetchError(`Failed to fetch from ${url}: ${response.status} ${body.slice(0, 200)}`, url, response.status);
34
+ }
35
+ const json = await response.json();
36
+ return S.decodeUnknownSync(ParsedTool)(json);
37
+ }
38
+ /**
39
+ * Fetch parsed tool metadata from a Galaxy instance via its API.
40
+ * @param galaxyUrl - Base URL of the Galaxy instance (e.g. `https://usegalaxy.org`)
41
+ * @param toolId - Full tool ID (e.g. `toolshed.g2.bx.psu.edu/repos/devteam/fastqc/fastqc`)
42
+ * @param toolVersion - Tool version (optional, fetches latest if omitted)
43
+ * @param fetcher - Custom fetch implementation (defaults to globalThis.fetch)
44
+ */
45
+ export async function fetchFromGalaxy(galaxyUrl, toolId, toolVersion, fetcher = globalThis.fetch) {
46
+ const encodedId = encodeURIComponent(toolId);
47
+ const params = toolVersion ? `?tool_version=${encodeURIComponent(toolVersion)}` : "";
48
+ const url = `${galaxyUrl}/api/tools/${encodedId}/parsed${params}`;
49
+ const response = await fetcher(url, {
50
+ headers: { Accept: "application/json" },
51
+ signal: AbortSignal.timeout(30_000),
52
+ });
53
+ if (!response.ok) {
54
+ const body = await response.text().catch(() => "");
55
+ throw new ToolFetchError(`Failed to fetch from Galaxy ${url}: ${response.status} ${body.slice(0, 200)}`, url, response.status);
56
+ }
57
+ const json = await response.json();
58
+ return S.decodeUnknownSync(ParsedTool)(json);
59
+ }
60
+ //# sourceMappingURL=toolshed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolshed.js","sourceRoot":"","sources":["../../src/client/toolshed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,oEAAoE;AACpE,MAAM,OAAO,cAAe,SAAQ,KAAK;IAK5B;IAEA;IANF,IAAI,GAAG,gBAAgB,CAAC;IACjC,YACE,OAAe;IACf,kCAAkC;IACzB,GAAW;IACpB,2DAA2D;IAClD,UAAmB;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QAJN,QAAG,GAAH,GAAG,CAAQ;QAEX,eAAU,GAAV,UAAU,CAAS;IAG9B,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,SAAiB,EACjB,WAAmB,EACnB,UAAwB,UAAU,CAAC,KAAK;IAExC,MAAM,GAAG,GAAG,GAAG,WAAW,cAAc,SAAS,aAAa,WAAW,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAClC,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,cAAc,CACtB,wBAAwB,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EACvE,GAAG,EACH,QAAQ,CAAC,MAAM,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,MAAc,EACd,WAA2B,EAC3B,UAAwB,UAAU,CAAC,KAAK;IAExC,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,iBAAiB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,MAAM,GAAG,GAAG,GAAG,SAAS,cAAc,SAAS,UAAU,MAAM,EAAE,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAClC,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,cAAc,CACtB,+BAA+B,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAC9E,GAAG,EACH,QAAQ,CAAC,MAAM,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @module @galaxy-tool-util/core
3
+ *
4
+ * Galaxy tool cache, ToolShed/Galaxy API client, and ParsedTool model.
5
+ * Handles fetching tool metadata from remote sources and caching locally.
6
+ */
7
+ /** Effect Schema for parsed tool metadata (id, version, name, inputs, outputs, etc.). */
8
+ export { ParsedTool, HelpContent, XrefDict, Citation } from "./models/parsed-tool.js";
9
+ export {
10
+ /** Parse a full ToolShed tool ID into ToolCoordinates (toolshedUrl, trsToolId, version). */
11
+ parseToolshedToolId,
12
+ /** Reconstruct a full tool ID from ToolShed URL and TRS tool ID. */
13
+ toolIdFromTrs,
14
+ /** Compute a deterministic SHA-256 cache key from ToolShed URL + TRS ID + version. */
15
+ cacheKey,
16
+ /** Cache metadata index — tracks tool IDs, versions, sources, and timestamps. */
17
+ CacheIndex,
18
+ /** Two-layer cache (memory + filesystem) for parsed tool metadata. */
19
+ ToolCache,
20
+ /** Resolve cache directory from explicit override, env var, or default. */
21
+ getCacheDir, DEFAULT_CACHE_DIR, CACHE_DIR_ENV_VAR, DEFAULT_TOOLSHED_URL, TOOLSHED_URL_ENV_VAR, } from "./cache/index.js";
22
+ export type { ToolCoordinates, CacheIndexEntry, CacheIndexData } from "./cache/index.js";
23
+ /** Fetch parsed tool metadata from a ToolShed instance via TRS API. */
24
+ export { fetchFromToolShed, fetchFromGalaxy, ToolFetchError } from "./client/index.js";
25
+ /** High-level service: fetch tools from multiple sources with automatic caching. */
26
+ export { ToolInfoService } from "./tool-info.js";
27
+ export type { ToolInfoOptions, ToolSource } from "./tool-info.js";
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yFAAyF;AACzF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO;AACL,4FAA4F;AAC5F,mBAAmB;AACnB,oEAAoE;AACpE,aAAa;AACb,sFAAsF;AACtF,QAAQ;AACR,iFAAiF;AACjF,UAAU;AACV,sEAAsE;AACtE,SAAS;AACT,2EAA2E;AAC3E,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzF,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvF,oFAAoF;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @module @galaxy-tool-util/core
3
+ *
4
+ * Galaxy tool cache, ToolShed/Galaxy API client, and ParsedTool model.
5
+ * Handles fetching tool metadata from remote sources and caching locally.
6
+ */
7
+ /** Effect Schema for parsed tool metadata (id, version, name, inputs, outputs, etc.). */
8
+ export { ParsedTool, HelpContent, XrefDict, Citation } from "./models/parsed-tool.js";
9
+ export {
10
+ /** Parse a full ToolShed tool ID into ToolCoordinates (toolshedUrl, trsToolId, version). */
11
+ parseToolshedToolId,
12
+ /** Reconstruct a full tool ID from ToolShed URL and TRS tool ID. */
13
+ toolIdFromTrs,
14
+ /** Compute a deterministic SHA-256 cache key from ToolShed URL + TRS ID + version. */
15
+ cacheKey,
16
+ /** Cache metadata index — tracks tool IDs, versions, sources, and timestamps. */
17
+ CacheIndex,
18
+ /** Two-layer cache (memory + filesystem) for parsed tool metadata. */
19
+ ToolCache,
20
+ /** Resolve cache directory from explicit override, env var, or default. */
21
+ getCacheDir, DEFAULT_CACHE_DIR, CACHE_DIR_ENV_VAR, DEFAULT_TOOLSHED_URL, TOOLSHED_URL_ENV_VAR, } from "./cache/index.js";
22
+ /** Fetch parsed tool metadata from a ToolShed instance via TRS API. */
23
+ export { fetchFromToolShed, fetchFromGalaxy, ToolFetchError } from "./client/index.js";
24
+ /** High-level service: fetch tools from multiple sources with automatic caching. */
25
+ export { ToolInfoService } from "./tool-info.js";
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yFAAyF;AACzF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO;AACL,4FAA4F;AAC5F,mBAAmB;AACnB,oEAAoE;AACpE,aAAa;AACb,sFAAsF;AACtF,QAAQ;AACR,iFAAiF;AACjF,UAAU;AACV,sEAAsE;AACtE,SAAS;AACT,2EAA2E;AAC3E,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvF,oFAAoF;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,46 @@
1
+ import * as S from "effect/Schema";
2
+ /** Tool help content with format (rst, markdown, etc.) and rendered content. */
3
+ export declare const HelpContent: S.Struct<{
4
+ format: typeof S.String;
5
+ content: typeof S.String;
6
+ }>;
7
+ /** External reference (e.g. bio.tools ID, bioconductor package). */
8
+ export declare const XrefDict: S.Struct<{
9
+ value: typeof S.String;
10
+ type: typeof S.String;
11
+ }>;
12
+ /** Tool citation entry (bibtex, doi, etc.). */
13
+ export declare const Citation: S.Struct<{
14
+ type: typeof S.String;
15
+ content: typeof S.String;
16
+ }>;
17
+ /**
18
+ * Effect Schema for parsed Galaxy tool metadata as returned by the ToolShed TRS API
19
+ * or Galaxy's /api/tools/:id/parsed endpoint.
20
+ */
21
+ export declare const ParsedTool: S.Struct<{
22
+ id: typeof S.String;
23
+ version: S.NullOr<typeof S.String>;
24
+ name: typeof S.String;
25
+ description: S.transform<S.NullOr<typeof S.String>, S.NullOr<typeof S.String>>;
26
+ inputs: S.Array$<typeof S.Unknown>;
27
+ outputs: S.Array$<typeof S.Unknown>;
28
+ citations: S.Array$<S.Struct<{
29
+ type: typeof S.String;
30
+ content: typeof S.String;
31
+ }>>;
32
+ license: S.NullOr<typeof S.String>;
33
+ profile: S.NullOr<typeof S.String>;
34
+ edam_operations: S.Array$<typeof S.String>;
35
+ edam_topics: S.Array$<typeof S.String>;
36
+ xrefs: S.Array$<S.Struct<{
37
+ value: typeof S.String;
38
+ type: typeof S.String;
39
+ }>>;
40
+ help: S.optional<S.Union<[S.Struct<{
41
+ format: typeof S.String;
42
+ content: typeof S.String;
43
+ }>, typeof S.Null]>>;
44
+ }>;
45
+ export type ParsedTool = S.Schema.Type<typeof ParsedTool>;
46
+ //# sourceMappingURL=parsed-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsed-tool.d.ts","sourceRoot":"","sources":["../../src/models/parsed-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,eAAe,CAAC;AAEnC,gFAAgF;AAChF,eAAO,MAAM,WAAW;;;EAGtB,CAAC;AAEH,oEAAoE;AACpE,eAAO,MAAM,QAAQ;;;EAGnB,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,QAAQ;;;EAGnB,CAAC;AAQH;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;EAcrB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,UAAU,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import * as S from "effect/Schema";
2
+ /** Tool help content with format (rst, markdown, etc.) and rendered content. */
3
+ export const HelpContent = S.Struct({
4
+ format: S.String,
5
+ content: S.String,
6
+ });
7
+ /** External reference (e.g. bio.tools ID, bioconductor package). */
8
+ export const XrefDict = S.Struct({
9
+ value: S.String,
10
+ type: S.String,
11
+ });
12
+ /** Tool citation entry (bibtex, doi, etc.). */
13
+ export const Citation = S.Struct({
14
+ type: S.String,
15
+ content: S.String,
16
+ });
17
+ /** Normalize empty string to null for description field. */
18
+ const NullableDescription = S.transform(S.NullOr(S.String), S.NullOr(S.String), {
19
+ decode: (val) => (val === "" ? null : val),
20
+ encode: (val) => val,
21
+ });
22
+ /**
23
+ * Effect Schema for parsed Galaxy tool metadata as returned by the ToolShed TRS API
24
+ * or Galaxy's /api/tools/:id/parsed endpoint.
25
+ */
26
+ export const ParsedTool = S.Struct({
27
+ id: S.String,
28
+ version: S.NullOr(S.String),
29
+ name: S.String,
30
+ description: NullableDescription,
31
+ inputs: S.Array(S.Unknown),
32
+ outputs: S.Array(S.Unknown),
33
+ citations: S.Array(Citation),
34
+ license: S.NullOr(S.String),
35
+ profile: S.NullOr(S.String),
36
+ edam_operations: S.Array(S.String),
37
+ edam_topics: S.Array(S.String),
38
+ xrefs: S.Array(XrefDict),
39
+ help: S.optional(S.Union(HelpContent, S.Null)),
40
+ });
41
+ //# sourceMappingURL=parsed-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsed-tool.js","sourceRoot":"","sources":["../../src/models/parsed-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,eAAe,CAAC;AAEnC,gFAAgF;AAChF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM;CAClB,CAAC,CAAC;AAEH,oEAAoE;AACpE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM;IACf,IAAI,EAAE,CAAC,CAAC,MAAM;CACf,CAAC,CAAC;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM;IACd,OAAO,EAAE,CAAC,CAAC,MAAM;CAClB,CAAC,CAAC;AAEH,4DAA4D;AAC5D,MAAM,mBAAmB,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE;IAC9E,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1C,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;CACrB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM;IACZ,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM;IACd,WAAW,EAAE,mBAAmB;IAChC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3B,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAClC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACxB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;CAC/C,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { ParsedTool } from "./models/parsed-tool.js";
2
+ import { ToolCache } from "./cache/tool-cache.js";
3
+ /** A remote source for fetching tool metadata. */
4
+ export interface ToolSource {
5
+ type: "toolshed" | "galaxy";
6
+ url: string;
7
+ }
8
+ /** Options for constructing a {@link ToolInfoService}. */
9
+ export interface ToolInfoOptions {
10
+ cacheDir?: string;
11
+ defaultToolshedUrl?: string;
12
+ /** Multiple sources tried in order. If provided, overrides defaultToolshedUrl/galaxyUrl. */
13
+ sources?: ToolSource[];
14
+ /** @deprecated Use sources instead. Kept for simple single-source usage. */
15
+ galaxyUrl?: string;
16
+ fetcher?: typeof fetch;
17
+ }
18
+ /**
19
+ * High-level service for fetching Galaxy tool metadata with automatic caching.
20
+ * Tries configured sources in order and caches on first successful fetch.
21
+ */
22
+ export declare class ToolInfoService {
23
+ readonly cache: ToolCache;
24
+ private readonly sources;
25
+ private readonly fetcher;
26
+ constructor(opts?: ToolInfoOptions);
27
+ getToolInfo(toolId: string, toolVersion?: string | null): Promise<ParsedTool | null>;
28
+ addTool(toolId: string, toolVersion: string, parsedTool: ParsedTool, source?: string, sourceUrl?: string): Promise<string>;
29
+ }
30
+ //# sourceMappingURL=tool-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-info.d.ts","sourceRoot":"","sources":["../src/tool-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0DAA0D;AAC1D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAE3B,IAAI,CAAC,EAAE,eAAe;IAuB5B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAqDpF,OAAO,CACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,UAAU,EACtB,MAAM,GAAE,MAAgB,EACxB,SAAS,GAAE,MAAW,GACrB,OAAO,CAAC,MAAM,CAAC;CAOnB"}
@@ -0,0 +1,78 @@
1
+ import { ToolCache } from "./cache/tool-cache.js";
2
+ import { cacheKey } from "./cache/cache-key.js";
3
+ import { fetchFromToolShed, fetchFromGalaxy } from "./client/toolshed.js";
4
+ /**
5
+ * High-level service for fetching Galaxy tool metadata with automatic caching.
6
+ * Tries configured sources in order and caches on first successful fetch.
7
+ */
8
+ export class ToolInfoService {
9
+ cache;
10
+ sources;
11
+ fetcher;
12
+ constructor(opts) {
13
+ this.cache = new ToolCache({
14
+ cacheDir: opts?.cacheDir,
15
+ defaultToolshedUrl: opts?.defaultToolshedUrl,
16
+ });
17
+ this.fetcher = opts?.fetcher ?? globalThis.fetch;
18
+ if (opts?.sources && opts.sources.length > 0) {
19
+ this.sources = opts.sources;
20
+ }
21
+ else {
22
+ // Build sources from legacy options
23
+ this.sources = [
24
+ {
25
+ type: "toolshed",
26
+ url: opts?.defaultToolshedUrl ?? this.cache.defaultToolshedUrl,
27
+ },
28
+ ];
29
+ if (opts?.galaxyUrl) {
30
+ this.sources.push({ type: "galaxy", url: opts.galaxyUrl });
31
+ }
32
+ }
33
+ }
34
+ async getToolInfo(toolId, toolVersion) {
35
+ const coords = this.cache.resolveToolCoordinates(toolId, toolVersion);
36
+ if (coords.version === null) {
37
+ throw new Error(`No version available for tool: ${toolId}`);
38
+ }
39
+ const key = cacheKey(coords.toolshedUrl, coords.trsToolId, coords.version);
40
+ // Check filesystem cache (ToolCache checks memory first internally)
41
+ const cached = await this.cache.loadCached(key);
42
+ if (cached !== null)
43
+ return cached;
44
+ // Try each source in order
45
+ for (const source of this.sources) {
46
+ try {
47
+ let parsedTool;
48
+ let sourceLabel;
49
+ let sourceUrl;
50
+ if (source.type === "toolshed") {
51
+ parsedTool = await fetchFromToolShed(source.url, coords.trsToolId, coords.version, this.fetcher);
52
+ sourceLabel = "api";
53
+ sourceUrl = `${source.url}/api/tools/${coords.trsToolId}/versions/${coords.version}`;
54
+ }
55
+ else {
56
+ parsedTool = await fetchFromGalaxy(source.url, toolId, toolVersion, this.fetcher);
57
+ sourceLabel = "galaxy";
58
+ sourceUrl = `${source.url}/api/tools/${encodeURIComponent(toolId)}/parsed`;
59
+ }
60
+ await this.cache.saveTool(key, parsedTool, coords.readableId, coords.version, sourceLabel, sourceUrl);
61
+ return parsedTool;
62
+ }
63
+ catch (err) {
64
+ const msg = err instanceof Error ? err.message : String(err);
65
+ console.debug(`${source.type} fetch failed (${source.url}) for ${coords.trsToolId}: ${msg}`);
66
+ }
67
+ }
68
+ return null;
69
+ }
70
+ async addTool(toolId, toolVersion, parsedTool, source = "local", sourceUrl = "") {
71
+ const coords = this.cache.resolveToolCoordinates(toolId, toolVersion);
72
+ const version = coords.version ?? toolVersion;
73
+ const key = cacheKey(coords.toolshedUrl, coords.trsToolId, version);
74
+ await this.cache.saveTool(key, parsedTool, coords.readableId, version, source, sourceUrl);
75
+ return key;
76
+ }
77
+ }
78
+ //# sourceMappingURL=tool-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-info.js","sourceRoot":"","sources":["../src/tool-info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAmB1E;;;GAGG;AACH,MAAM,OAAO,eAAe;IACjB,KAAK,CAAY;IACT,OAAO,CAAe;IACtB,OAAO,CAAe;IAEvC,YAAY,IAAsB;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC;YACzB,QAAQ,EAAE,IAAI,EAAE,QAAQ;YACxB,kBAAkB,EAAE,IAAI,EAAE,kBAAkB;SAC7C,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC;QAEjD,IAAI,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,oCAAoC;YACpC,IAAI,CAAC,OAAO,GAAG;gBACb;oBACE,IAAI,EAAE,UAAU;oBAChB,GAAG,EAAE,IAAI,EAAE,kBAAkB,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB;iBAC/D;aACF,CAAC;YACF,IAAI,IAAI,EAAE,SAAS,EAAE,CAAC;gBACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,WAA2B;QAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtE,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAE3E,oEAAoE;QACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAEnC,2BAA2B;QAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,IAAI,UAAsB,CAAC;gBAC3B,IAAI,WAAmB,CAAC;gBACxB,IAAI,SAAiB,CAAC;gBAEtB,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBAC/B,UAAU,GAAG,MAAM,iBAAiB,CAClC,MAAM,CAAC,GAAG,EACV,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,OAAO,EACd,IAAI,CAAC,OAAO,CACb,CAAC;oBACF,WAAW,GAAG,KAAK,CAAC;oBACpB,SAAS,GAAG,GAAG,MAAM,CAAC,GAAG,cAAc,MAAM,CAAC,SAAS,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvF,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;oBAClF,WAAW,GAAG,QAAQ,CAAC;oBACvB,SAAS,GAAG,GAAG,MAAM,CAAC,GAAG,cAAc,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC7E,CAAC;gBAED,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CACvB,GAAG,EACH,UAAU,EACV,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,OAAO,EACd,WAAW,EACX,SAAS,CACV,CAAC;gBACF,OAAO,UAAU,CAAC;YACpB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO,CAAC,KAAK,CACX,GAAG,MAAM,CAAC,IAAI,kBAAkB,MAAM,CAAC,GAAG,SAAS,MAAM,CAAC,SAAS,KAAK,GAAG,EAAE,CAC9E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CACX,MAAc,EACd,WAAmB,EACnB,UAAsB,EACtB,SAAiB,OAAO,EACxB,YAAoB,EAAE;QAEtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,WAAW,CAAC;QAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAC1F,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@galaxy-tool-util/core",
3
+ "version": "0.1.0",
4
+ "description": "Galaxy tool cache, ToolShed client, and ParsedTool models",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ }
11
+ },
12
+ "files": ["dist", "README.md", "LICENSE"],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/jmchilton/galaxy-tool-util-ts",
16
+ "directory": "packages/core"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public",
20
+ "provenance": true
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "typecheck": "tsc --noEmit",
25
+ "test": "tsc --noEmit && vitest run",
26
+ "test:watch": "vitest",
27
+ "lint": "eslint src/ test/",
28
+ "format": "prettier --check 'src/**/*.ts' 'test/**/*.ts'",
29
+ "format-fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'"
30
+ },
31
+ "license": "MIT",
32
+ "devDependencies": {
33
+ "@types/node": "^25.5.0",
34
+ "yaml": "^2.8.3"
35
+ },
36
+ "dependencies": {
37
+ "effect": "^3.21.0"
38
+ }
39
+ }