@galaxyproject/galaxy-api-client 25.0.0-dev.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/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # Galaxy API Client
2
+
3
+ A standalone client library for the Galaxy API, built using the type definitions from the main Galaxy client.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @galaxyproject/galaxy-api-client
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Usage
14
+
15
+ ```typescript
16
+ import { createGalaxyApi } from "@galaxyproject/galaxy-api-client";
17
+
18
+ // Create an instance of the Galaxy API client with a specific base URL
19
+ const api = createGalaxyApi("https://usegalaxy.org");
20
+
21
+ // Alternatively, use the default (current origin)
22
+ // const api = createGalaxyApi();
23
+
24
+ // Example: Get a list of histories
25
+ const { data, error } = await api.GET("/api/histories");
26
+
27
+ if (error) {
28
+ console.error("Error fetching histories:", error);
29
+ } else {
30
+ console.log("Histories:", data);
31
+ }
32
+
33
+ // For backward compatibility
34
+ import { GalaxyApi } from "@galaxyproject/galaxy-api-client";
35
+ const legacyApi = GalaxyApi(); // Uses current origin
36
+ ```
37
+
38
+ ### Usage with API Keys and Custom Headers
39
+
40
+ ```typescript
41
+ import { createGalaxyApi } from "@galaxyproject/galaxy-api-client";
42
+
43
+ // Create a client with API key authentication and custom headers
44
+ const api = createGalaxyApi({
45
+ baseUrl: "https://usegalaxy.org",
46
+ apiKey: "your-api-key-here",
47
+ headers: {
48
+ Accept: "application/json",
49
+ },
50
+ fetchOptions: {
51
+ credentials: "include", // Include cookies for CORS requests
52
+ cache: "no-cache", // Don't cache responses
53
+ },
54
+ });
55
+
56
+ // Now all requests will include the API key header and custom options
57
+ const { data, error } = await api.GET("/api/histories");
58
+ ```
59
+
60
+ ## Type Safety
61
+
62
+ This package provides TypeScript types for Galaxy API endpoints and models:
63
+
64
+ ```typescript
65
+ import { createGalaxyApi, type HistorySummary, type DatasetEntry } from "@galaxyproject/galaxy-api-client";
66
+
67
+ const api = createGalaxyApi();
68
+
69
+ // Type-safe API calls
70
+ const { data: histories } = await api.GET("/api/histories");
71
+ // histories is typed as HistorySummary[] | undefined
72
+
73
+ // You can use the types for your variables
74
+ const myHistory: HistorySummary = {
75
+ id: "123",
76
+ name: "My History",
77
+ // ...other required properties
78
+ };
79
+ ```
80
+
81
+ ## Examples
82
+
83
+ See more in `src/example.ts` that demonstrate how to use the client:
84
+
85
+ ### Basic Example
86
+
87
+ ```typescript
88
+ import { createGalaxyApi } from "@galaxyproject/galaxy-api-client";
89
+
90
+ // Create a client with a specific Galaxy instance
91
+ const api = createGalaxyApi("https://usegalaxy.org");
92
+
93
+ // Example: Get a list of tools
94
+ async function getTools() {
95
+ const { data, error } = await api.GET("/api/tools");
96
+
97
+ if (error) {
98
+ console.error("Error fetching tools:", error);
99
+ return [];
100
+ }
101
+
102
+ // Log tool count
103
+ console.log(`Found ${data.length} tools`);
104
+
105
+ return data;
106
+ }
107
+ ```
108
+
109
+ ## Notes
110
+
111
+ This package uses a symlink to reference API type definitions from the main Galaxy client while providing a standalone client implementation. This approach was chosen to:
112
+
113
+ 1. Minimize duplication of type definitions
114
+ 2. Ensure type definitions stay in sync with the main codebase
115
+ 3. Allow the client to work independently of Galaxy's internal utilities
116
+
117
+ ## Development
118
+
119
+ To work on this package:
120
+
121
+ 1. Make changes to the API type definitions in the main Galaxy client
122
+ 2. The type changes will automatically be available in this package via symlinks
123
+ 3. Synchronize the version with Galaxy:
124
+
125
+ ```bash
126
+ # Update the version in package.json from Galaxy's version.py
127
+ npm run sync-version
128
+ ```
129
+
130
+ 4. Build the library for distribution:
131
+
132
+ ```bash
133
+ # Install dependencies
134
+ npm install
135
+
136
+ # Build the library
137
+ npm run build
138
+
139
+ # Watch mode for development
140
+ npm run dev
141
+ ```
142
+
143
+ ### Version Synchronization
144
+
145
+ This package maintains version parity with Galaxy to indicate API compatibility. The version number in `package.json` is derived from Galaxy's `lib/galaxy/version.py` file but formatted to comply with npm's semver requirements.
146
+
147
+ **Important:** npm does not allow republishing the same version, even for development versions. When making changes to the client API during development:
148
+
149
+ 1. Manually increment the version before publishing:
150
+
151
+ ```bash
152
+ # Example: Update from 25.0.0-dev.0 to 25.0.0-dev.1
153
+ npm version prerelease --preid=dev
154
+ ```
155
+
156
+ 2. Or edit the npm version directly in package.json:
157
+ ```json
158
+ {
159
+ "version": "25.0.0-dev.1"
160
+ }
161
+ ```
162
+
163
+ There's also a script to automate this process of syncing with galaxy version that we may want to use in other contexts, too?:
164
+
165
+ ```bash
166
+ # Using npm script
167
+ npm run sync-version
168
+ ```
169
+
170
+ The script will:
171
+
172
+ 1. Read the version from Galaxy's `version.py` file
173
+ 2. Convert it to npm-compatible semver format
174
+ 3. Update the version in `package.json` if different
175
+
176
+ Version synchronization should be performed before each release to ensure the client API version accurately reflects the Galaxy API version it supports.
177
+
178
+ ### Testing
179
+
180
+ The package includes a few vitest tests as a sanity check, but we could do a lot more here:
181
+
182
+ ```bash
183
+ # Run tests
184
+ npm test
185
+
186
+ # Run tests with watch mode (during development)
187
+ npm run test:watch
188
+ ```
189
+
190
+ The tests verify:
191
+
192
+ - Client creation with default and custom base URLs
193
+ - Basic API interaction with proper typing
194
+ - Error handling
package/dist/index.cjs ADDED
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ var createClient = require('openapi-fetch');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var createClient__default = /*#__PURE__*/_interopDefault(createClient);
8
+
9
+ // src/client.ts
10
+
11
+ // src/api-types.ts
12
+ function isHDA(entry) {
13
+ return entry !== void 0 && "history_content_type" in entry && entry.history_content_type === "dataset";
14
+ }
15
+ function isHDCA(entry) {
16
+ return entry !== void 0 && "history_content_type" in entry && entry.history_content_type === "dataset_collection";
17
+ }
18
+ function isDCE(item) {
19
+ return item && "element_type" in item;
20
+ }
21
+ function isCollectionElement(element) {
22
+ return element.element_type === "dataset_collection";
23
+ }
24
+ function isDatasetElement(element) {
25
+ return element.element_type === "hda";
26
+ }
27
+ function hasDetails(entry) {
28
+ return "peek" in entry;
29
+ }
30
+ function isInaccessible(entry) {
31
+ return "accessible" in entry && !entry.accessible;
32
+ }
33
+
34
+ // src/client.ts
35
+ function createGalaxyApi(options = {}) {
36
+ const opts = typeof options === "string" ? { baseUrl: options } : options;
37
+ const baseUrl = opts.baseUrl || window.location.origin;
38
+ const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
39
+ const headers = {
40
+ ...opts.headers || {}
41
+ };
42
+ if (opts.apiKey) {
43
+ headers["x-api-key"] = opts.apiKey;
44
+ }
45
+ return createClient__default.default({
46
+ baseUrl: normalizedBaseUrl,
47
+ headers,
48
+ // Pass any custom fetchOptions directly to createClient
49
+ ...opts.fetchOptions ? { fetchOptions: opts.fetchOptions } : {}
50
+ });
51
+ }
52
+
53
+ // src/utils/error.ts
54
+ function errorMessageAsString(error) {
55
+ if (typeof error === "string") {
56
+ return error;
57
+ }
58
+ if (error instanceof Error) {
59
+ return error.message;
60
+ }
61
+ if (error && typeof error === "object") {
62
+ if (error.status && error.error) {
63
+ return `API Error (${error.status}): ${error.error}`;
64
+ }
65
+ if (error.message) {
66
+ return error.message;
67
+ }
68
+ try {
69
+ return JSON.stringify(error);
70
+ } catch (e) {
71
+ return String(error);
72
+ }
73
+ }
74
+ return "Unknown error";
75
+ }
76
+
77
+ // src/index.ts
78
+ var SimpleError = class extends Error {
79
+ constructor(message) {
80
+ super(message);
81
+ this.name = "GalaxyApiError";
82
+ }
83
+ };
84
+ function GalaxyApi() {
85
+ return createGalaxyApi();
86
+ }
87
+ function formatErrorMessage(error) {
88
+ return errorMessageAsString(error);
89
+ }
90
+
91
+ exports.GalaxyApi = GalaxyApi;
92
+ exports.SimpleError = SimpleError;
93
+ exports.createGalaxyApi = createGalaxyApi;
94
+ exports.formatErrorMessage = formatErrorMessage;
95
+ exports.hasDetails = hasDetails;
96
+ exports.isCollectionElement = isCollectionElement;
97
+ exports.isDCE = isDCE;
98
+ exports.isDatasetElement = isDatasetElement;
99
+ exports.isHDA = isHDA;
100
+ exports.isHDCA = isHDCA;
101
+ exports.isInaccessible = isInaccessible;
102
+ //# sourceMappingURL=index.cjs.map
103
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api-types.ts","../src/client.ts","../src/utils/error.ts","../src/index.ts"],"names":["createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * This file re-exports the types we want to use from the Galaxy API.\n * It serves as a compatibility layer to avoid importing directly from the\n * symlinked files, which would require all of Galaxy's dependencies.\n */\n\n// Import types from the symlinked files\nimport { type components, type GalaxyApiPaths } from \"./api/schema\";\n\n// We only need the types, not the code that depends on Galaxy's implementation\nexport type { components, GalaxyApiPaths };\n\n// Re-export specific types\nexport type HistorySummary = components[\"schemas\"][\"HistorySummary\"];\nexport type HistoryDetailed = components[\"schemas\"][\"HistoryDetailed\"];\nexport type HDASummary = components[\"schemas\"][\"HDASummary\"];\nexport type HDADetailed = components[\"schemas\"][\"HDADetailed\"];\nexport type DCESummary = components[\"schemas\"][\"DCESummary\"];\nexport type HDCASummary = components[\"schemas\"][\"HDCASummary\"];\nexport type HDCADetailed = components[\"schemas\"][\"HDCADetailed\"];\nexport type DCObject = components[\"schemas\"][\"DCObject\"];\nexport type HDAObject = components[\"schemas\"][\"HDAObject\"];\nexport type HDAInaccessible = components[\"schemas\"][\"HDAInaccessible\"];\nexport type DatasetTextContentDetails = components[\"schemas\"][\"DatasetTextContentDetails\"];\nexport type DatasetStorageDetails = components[\"schemas\"][\"DatasetStorageDetails\"];\nexport type DatasetCollectionAttributes = components[\"schemas\"][\"DatasetCollectionAttributesResult\"];\nexport type ConcreteObjectStoreModel = components[\"schemas\"][\"ConcreteObjectStoreModel\"];\nexport type MessageException = components[\"schemas\"][\"MessageExceptionModel\"];\nexport type DatasetHash = components[\"schemas\"][\"DatasetHash\"];\nexport type DatasetSource = components[\"schemas\"][\"DatasetSource\"];\nexport type DatasetTransform = components[\"schemas\"][\"DatasetSourceTransform\"];\nexport type StoreExportPayload = components[\"schemas\"][\"StoreExportPayload\"];\nexport type ModelStoreFormat = components[\"schemas\"][\"ModelStoreFormat\"];\nexport type ObjectExportTaskResponse = components[\"schemas\"][\"ObjectExportTaskResponse\"];\nexport type ExportObjectRequestMetadata = components[\"schemas\"][\"ExportObjectRequestMetadata\"];\nexport type ExportObjectResultMetadata = components[\"schemas\"][\"ExportObjectResultMetadata\"];\nexport type AsyncTaskResultSummary = components[\"schemas\"][\"AsyncTaskResultSummary\"];\n\n// Define utility types that may be used in the client\nexport type HistorySortByLiteral = \"create_time\" | \"name\" | \"update_time\" | \"username\" | undefined;\n\nexport interface HistoryContentsStats {\n id: string;\n update_time: string;\n size: number;\n contents_active: components[\"schemas\"][\"HistoryActiveContentCounts\"];\n}\n\nexport interface HistorySummaryExtended extends HistorySummary, HistoryContentsStats {\n user_id: string | null;\n}\n\nexport interface SelectableObjectStore extends ConcreteObjectStoreModel {\n object_store_id: string;\n}\n\nexport type DatasetEntry = HDASummary | HDADetailed | HDAInaccessible;\n\nexport interface DCECollection extends DCESummary {\n element_type: \"dataset_collection\";\n object: DCObject;\n}\n\nexport interface DCEDataset extends DCESummary {\n element_type: \"hda\";\n object: HDAObject;\n}\n\nexport interface SubCollection extends DCObject {\n name: string;\n hdca_id: string;\n}\n\nexport type CollectionEntry = HDCASummary | SubCollection;\nexport type HistoryItemSummary = HDASummary | HDCASummary;\n\n// Utility functions\nexport function isHDA(entry?: HistoryItemSummary): entry is HDASummary {\n return entry !== undefined && \"history_content_type\" in entry && entry.history_content_type === \"dataset\";\n}\n\nexport function isHDCA(entry?: HistoryItemSummary | CollectionEntry): entry is HDCASummary {\n return (\n entry !== undefined && \"history_content_type\" in entry && entry.history_content_type === \"dataset_collection\"\n );\n}\n\nexport function isDCE(item: object): item is DCESummary {\n return item && \"element_type\" in item;\n}\n\nexport function isCollectionElement(element: DCESummary): element is DCECollection {\n return element.element_type === \"dataset_collection\";\n}\n\nexport function isDatasetElement(element: DCESummary): element is DCEDataset {\n return element.element_type === \"hda\";\n}\n\nexport function hasDetails(entry: DatasetEntry): entry is HDADetailed {\n return \"peek\" in entry;\n}\n\nexport function isInaccessible(entry: DatasetEntry): entry is HDAInaccessible {\n return \"accessible\" in entry && !entry.accessible;\n}\n","import createClient from \"openapi-fetch\";\nimport { type GalaxyApiPaths } from \"./api-types\";\n\n/**\n * Options for creating a Galaxy API client\n */\nexport interface GalaxyApiOptions {\n /**\n * The base URL of the Galaxy server (e.g., \"https://usegalaxy.org\")\n * @default window.location.origin\n */\n baseUrl?: string;\n\n /**\n * API key for authentication\n */\n apiKey?: string;\n\n /**\n * Custom headers to include with each request\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch options that will be passed to all requests\n */\n fetchOptions?: RequestInit;\n}\n\n/**\n * Creates a Galaxy API client with the specified options\n * @param options Configuration options for the Galaxy API client\n * @returns The Galaxy API client\n */\nexport function createGalaxyApi(options: GalaxyApiOptions | string = {}) {\n // Handle the case where baseUrl is passed as a string for backward compatibility\n const opts = typeof options === \"string\" ? { baseUrl: options } : options;\n\n // Default to window.location.origin if no baseUrl is provided\n const baseUrl = opts.baseUrl || window.location.origin;\n const normalizedBaseUrl = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n\n // Build headers object\n const headers: Record<string, string> = {\n ...(opts.headers || {}),\n };\n\n // Add API key header if provided\n if (opts.apiKey) {\n headers[\"x-api-key\"] = opts.apiKey;\n }\n\n // Create the client with all options\n return createClient<GalaxyApiPaths>({\n baseUrl: normalizedBaseUrl,\n headers,\n // Pass any custom fetchOptions directly to createClient\n ...(opts.fetchOptions ? { fetchOptions: opts.fetchOptions } : {}),\n });\n}\n\nexport type GalaxyApiClient = ReturnType<typeof createGalaxyApi>;\n","/**\n * Simple error handling utilities for Galaxy Client API\n */\n\n/**\n * Convert various error formats to a readable string message\n */\nexport function errorMessageAsString(error: any): string {\n if (typeof error === \"string\") {\n return error;\n }\n\n if (error instanceof Error) {\n return error.message;\n }\n\n if (error && typeof error === \"object\") {\n // Handle API response errors\n if (error.status && error.error) {\n return `API Error (${error.status}): ${error.error}`;\n }\n\n // Handle response objects with error message\n if (error.message) {\n return error.message;\n }\n\n // Try to stringify the error object\n try {\n return JSON.stringify(error);\n } catch (e) {\n // Fall back to object inspection\n return String(error);\n }\n }\n\n return \"Unknown error\";\n}\n","/**\n * Galaxy Client API\n * A client library for the Galaxy API\n */\n\nimport { createGalaxyApi, type GalaxyApiClient } from \"./client\";\nimport { errorMessageAsString } from \"./utils/error\";\n\n// Re-export all the types from our type compatibility layer\nexport * from \"./api-types\";\n\n// SimpleError class for error handling\nexport class SimpleError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"GalaxyApiError\";\n }\n}\n\n// Re-export the client functions\nexport { createGalaxyApi, type GalaxyApiClient };\n\n// For backward compatibility - creates a client with default settings\nexport function GalaxyApi() {\n return createGalaxyApi();\n}\n\n// Utility function to format error messages\nexport function formatErrorMessage(error: any): string {\n return errorMessageAsString(error);\n}\n"]}