flowscale 1.0.10 → 1.0.12

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 CHANGED
@@ -1,19 +1,323 @@
1
1
  # Flowscale Node.js SDK
2
2
 
3
- A Node.js SDK for interacting with the Flowscale platform without directly managing API requests. This library simplifies invoking workflows, retrieving outputs, and checking run statuses.
3
+ A comprehensive Node.js SDK designed to simplify interaction with the Flowscale platform. This library abstracts away the complexities of API calls, enabling you to effortlessly invoke workflows, retrieve outputs, manage workflow runs, and monitor system health.
4
+
5
+ ---
4
6
 
5
7
  ## Installation
6
8
 
9
+ Install the Flowscale SDK by `npm`, `yarn`, `pnpm` or `bun`:
10
+
7
11
  ```bash
8
12
  npm install flowscale
9
13
 
14
+ yarn add flowscale
15
+
16
+ pnpm install flowscale
17
+
18
+ bun install flowscale
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Quick Start
24
+
25
+ ### Importing the SDK
26
+
27
+ To get started, import the Flowscale SDK into your project:
28
+
29
+ ```javascript
30
+ import { FlowscaleAPI } from 'flowscale';
31
+
32
+ // Initialize the SDK
33
+ const apiKey = process.env.FLOWSCALE_API_KEY;
34
+ const apiUrl = process.env.FLOWSCALE_API_URL;
35
+
36
+ if (!apiKey || !apiUrl) {
37
+ console.error('FLOWSCALE_API_KEY or FLOWSCALE_API_URL not set in .env');
38
+ process.exit(1);
39
+ }
40
+
41
+ const flowscale = new FlowscaleAPI(apiKey, apiUrl);
42
+ ```
43
+
44
+ **Environment Variables:** Add the following to your `.env` file:
45
+
46
+ ```plaintext
47
+ FLOWSCALE_API_KEY=your-api-key
48
+ FLOWSCALE_API_URL=https://api.flowscale.ai
49
+ ```
50
+
51
+ ---
52
+
53
+ ## SDK Methods
54
+
55
+ Below is a detailed guide to the SDK methods, including descriptions, usage, and response formats.
56
+
57
+ ### 1. `checkHealth()`
58
+
59
+ **Description:**
60
+ Check the health status of the Flowscale platform, including the status of containers and services.
61
+
62
+ **Usage:**
63
+ ```javascript
64
+ const health = await flowscale.checkHealth();
65
+ console.log('API Health:', health);
66
+ ```
67
+
68
+ **Response Example:**
69
+ ```json
70
+ {
71
+ "status": "success",
72
+ "data": [
73
+ {
74
+ "container": "container #1",
75
+ "status": "idle"
76
+ },
77
+ {
78
+ "container": "container #2",
79
+ "status": "running"
80
+ }
81
+ ]
82
+ }
83
+ ```
84
+
85
+ ---
86
+
87
+ ### 2. `getQueue()`
88
+
89
+ **Description:**
90
+ Retrieve the current status of the workflow queue, including running and pending jobs.
91
+
92
+ **Usage:**
93
+ ```javascript
94
+ const queue = await flowscale.getQueue();
95
+ console.log('Queue Details:', queue);
96
+ ```
97
+
98
+ **Response Example:**
99
+ ```json
100
+ {
101
+ "status": "success",
102
+ "data": [
103
+ {
104
+ "container": "container #1",
105
+ "queue": {
106
+ "queue_running": [
107
+ [
108
+ 0,
109
+ "2a0babc4-acce-4521-9576-00fa0e6ecc91"
110
+ ]
111
+ ],
112
+ "queue_pending": [
113
+ [
114
+ 1,
115
+ "5d60718a-7e89-4c64-b32d-0d1366b44e2a"
116
+ ]
117
+ ]
118
+ }
119
+ }
120
+ ]
121
+ }
122
+ ```
123
+
124
+ ---
125
+
126
+ ### 3. `executeWorkflow(workflowId, data, groupId?)`
127
+
128
+ **Description:**
129
+ Trigger a workflow execution using its unique `workflowId`. Input data and an optional `groupId` can be provided for better organization and tracking.
130
+
131
+ **Parameters:**
132
+ - `workflowId` *(string)*: The unique ID of the workflow.
133
+ - `data` *(object)*: Input parameters for the workflow.
134
+ - `groupId` *(string, optional)*: A custom identifier for grouping runs.
135
+
136
+ **Usage:**
137
+ ```javascript
138
+ const workflowId = "bncu0a1kipv";
139
+ const groupId = "test_group";
140
+
141
+ const inputs = {
142
+ "text_51536": "Prompt test",
143
+ "image_1234": { /* File or Blob of image */ },
144
+ "video_1239": { /* File or Blob of video */ }
145
+ };
146
+
147
+ const result = await flowscale.executeWorkflow(workflowId, inputs, groupId);
148
+ console.log('Workflow Result:', result);
149
+ ```
150
+
151
+ **Response Example:**
152
+ ```json
153
+ {
154
+ "status": "success",
155
+ "data": {
156
+ "number": 0,
157
+ "node_errors": {},
158
+ "output_names": [
159
+ "filename_prefix_58358_5WWF7GQUYF"
160
+ ],
161
+ "run_id": "808f34d0-ef97-4b78-a00f-1268077ea6db"
162
+ }
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ### 4. `getOutput(filename)`
169
+
170
+ **Description:**
171
+ Fetch the output of a completed workflow using its `filename`. Outputs typically include downloadable files or results.
172
+
173
+ **Parameters:**
174
+ - `filename` *(string)*: The name of the output file.
175
+
176
+ **Usage:**
177
+ ```javascript
178
+ const output = await flowscale.getOutput('filename_prefix_58358_5WWF7GQUYF.png');
179
+ console.log('Workflow Output:', output);
180
+ ```
181
+
182
+ **Response Example:**
183
+ ```json
184
+ {
185
+ "status": "success",
186
+ "data": {
187
+ "download_url": "https://runs-dev.s3.amazonaws.com/generations/...",
188
+ "generation_status": "success"
189
+ }
190
+ }
191
+ ```
192
+
193
+ ---
194
+
195
+ ### 5. `cancelRun(runId)`
196
+
197
+ **Description:**
198
+ Cancel a running workflow execution using its unique `runId`.
199
+
200
+ **Parameters:**
201
+ - `runId` *(string)*: The unique identifier of the running workflow.
202
+
203
+ **Usage:**
204
+ ```javascript
205
+ const result = await flowscale.cancelRun('808f34d0-ef97-4b78-a00f-1268077ea6db');
206
+ console.log('Cancellation Result:', result);
207
+ ```
208
+
209
+ **Response Example:**
210
+ ```json
211
+ {
212
+ "status": "success",
213
+ "data": "Run cancelled successfully"
214
+ }
215
+ ```
216
+
217
+ ---
218
+
219
+ ### 6. `getRun(runId)`
220
+
221
+ **Description:**
222
+ Retrieve detailed information about a specific workflow run.
223
+
224
+ **Parameters:**
225
+ - `runId` *(string)*: The unique identifier of the run.
226
+
227
+ **Usage:**
228
+ ```javascript
229
+ const runDetails = await flowscale.getRun('808f34d0-ef97-4b78-a00f-1268077ea6db');
230
+ console.log('Run Details:', runDetails);
231
+ ```
232
+
233
+ **Response Example:**
234
+ ```json
235
+ {
236
+ "status": "success",
237
+ "data": {
238
+ "_id": "808f34d0-ef97-4b78-a00f-1268077ea6db",
239
+ "status": "completed",
240
+ "inputs": [
241
+ {
242
+ "path": "text_51536",
243
+ "value": "The text \"How To\", a cowgirl in 1800s wild west..."
244
+ }
245
+ ],
246
+ "outputs": [
247
+ {
248
+ "filename": "filename_prefix_58358_5WWF7GQUYF.png",
249
+ "url": "https://runs-dev.s3.amazonaws.com/generations/..."
250
+ }
251
+ ]
252
+ }
253
+ }
254
+ ```
255
+
256
+ ---
257
+
258
+ ### 7. `getRuns(groupId)`
259
+
260
+ **Description:**
261
+ Retrieve all workflow runs associated with a specific `groupId`. If no `groupId` is provided, all runs for the team are returned.
262
+
263
+ **Parameters:**
264
+ - `groupId` *(string, optional)*: The identifier for grouping runs.
265
+
266
+ **Usage:**
267
+ ```javascript
268
+ const runs = await flowscale.getRuns('test_group');
269
+ console.log('Runs for Group:', runs);
270
+
271
+ // Get all runs for the team
272
+ const allRuns = await flowscale.getRuns();
273
+ console.log('All Runs:', allRuns);
274
+ ```
275
+
276
+ **Response Example:**
277
+ ```json
278
+ {
279
+ "status": "success",
280
+ "data": {
281
+ "group_id": "test_group",
282
+ "count": 2,
283
+ "runs": [
284
+ {
285
+ "_id": "cc29a72d-75b9-4c7b-b991-ccaf2a04d6ea",
286
+ "status": "completed",
287
+ "outputs": [
288
+ {
289
+ "filename": "filename_prefix_58358_G3DRLIVVYP.png",
290
+ "url": "https://runs-dev.s3.amazonaws.com/generations/..."
291
+ }
292
+ ]
293
+ }
294
+ ]
295
+ }
296
+ }
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Best Practices
302
+
303
+ ### Environment Configuration
304
+ - Always store sensitive information such as API keys in environment variables.
305
+ - Use `.env` files and libraries like `dotenv` for easy environment management.
306
+
307
+ ### Error Handling
308
+ - Wrap API calls in try-catch blocks to handle errors gracefully.
309
+ - Log errors for debugging and improve resilience.
310
+
311
+ ### Testing and Debugging
312
+ - Test workflows in a development environment before deploying to production.
313
+ - Validate inputs to ensure they match the workflow requirements.
314
+
315
+ ---
316
+
317
+ ## Support
318
+
319
+ For any questions or assistance, join the Flowscale community on **Discord** or refer to the [Flowscale Documentation](https://docs.flowscale.ai/).
10
320
 
11
- ## Methods
321
+ ---
12
322
 
13
- - checkHealth(): Promise<HealthCheckResponse>
14
- - getQueue(): Promise<QueueResponse>
15
- - executeWorkflow(workflowId: string, data: WorkflowData, groupId?: string): Promise<ExecuteWorkflowResponse>
16
- - getOutput(filename: string): Promise<GetOutputResponse | null>
17
- - cancelRun(runId: string): Promise<CancelRunResponse>
18
- - getRun(runId: string): Promise<RunDetailResponse>
19
- - getRuns(groupId: string): Promise<RunListResponse>
323
+ Simplify your workflow management with the Flowscale Node.js SDK. Happy coding!
@@ -0,0 +1,53 @@
1
+ import { HealthCheckResponse, QueueResponse, ExecuteWorkflowResponse, GetOutputResponse, RunDetailResponse, RunListResponse, CancelRunResponse } from './types';
2
+ export declare class FlowscaleAPI {
3
+ private apiKey;
4
+ private baseUrl;
5
+ private client;
6
+ constructor(apiKey: string, baseUrl: string);
7
+ /**
8
+ * Checks the health status of all ComfyUI instances within the specified cluster.
9
+ */
10
+ checkHealth(): Promise<HealthCheckResponse>;
11
+ /**
12
+ * Retrieves the queue data for all ComfyUI instances in the cluster.
13
+ */
14
+ getQueue(): Promise<QueueResponse>;
15
+ /**
16
+ * Executes a specified workflow by processing dynamic form data.
17
+ * @param workflowId - The ID of the workflow to execute.
18
+ * @param data - Form data including text fields and file uploads.
19
+ * @param groupId - Optional group ID.
20
+ */
21
+ executeWorkflow(workflowId: string, data: {
22
+ [key: string]: any;
23
+ }, groupId?: string): Promise<ExecuteWorkflowResponse>;
24
+ /**
25
+ * Retrieves the output of a specific run by providing the filename.
26
+ * @param filename - The filename of the output to retrieve.
27
+ */
28
+ getOutput(filename: string): Promise<GetOutputResponse | null>;
29
+ /**
30
+ * Cancels a specific run using its unique run ID.
31
+ * @param runId - The ID of the run to cancel.
32
+ */
33
+ cancelRun(runId: string): Promise<CancelRunResponse>;
34
+ /**
35
+ * Retrieves detailed information about a specific run using its unique run ID.
36
+ * @param runId - The ID of the run to retrieve.
37
+ */
38
+ getRun(runId: string): Promise<RunDetailResponse>;
39
+ /**
40
+ * Retrieves a list of all runs associated with a specific group ID.
41
+ * If no group ID is provided, all runs will be returned.
42
+ * @param groupId - The group ID to filter runs.
43
+ */
44
+ getRuns(groupId?: string): Promise<RunListResponse>;
45
+ /**
46
+ * Helper method to append data to FormData.
47
+ */
48
+ private appendFormData;
49
+ /**
50
+ * Error handling helper.
51
+ */
52
+ private handleError;
53
+ }
package/dist/index.js ADDED
@@ -0,0 +1,325 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.FlowscaleAPI = void 0;
54
+ var axios_1 = __importDefault(require("axios"));
55
+ var form_data_1 = __importDefault(require("form-data"));
56
+ var fs_1 = __importDefault(require("fs"));
57
+ var path_1 = __importDefault(require("path"));
58
+ var FlowscaleAPI = /** @class */ (function () {
59
+ function FlowscaleAPI(apiKey, baseUrl) {
60
+ var _this = this;
61
+ this.apiKey = apiKey;
62
+ this.baseUrl = baseUrl;
63
+ this.client = axios_1.default.create({
64
+ baseURL: this.baseUrl,
65
+ });
66
+ // Add the API key to all requests
67
+ this.client.interceptors.request.use(function (config) {
68
+ if (!config.headers) {
69
+ config.headers = {};
70
+ }
71
+ config.headers['X-API-KEY'] = _this.apiKey;
72
+ return config;
73
+ });
74
+ }
75
+ /**
76
+ * Checks the health status of all ComfyUI instances within the specified cluster.
77
+ */
78
+ FlowscaleAPI.prototype.checkHealth = function () {
79
+ return __awaiter(this, void 0, void 0, function () {
80
+ var response, error_1;
81
+ return __generator(this, function (_a) {
82
+ switch (_a.label) {
83
+ case 0:
84
+ _a.trys.push([0, 2, , 3]);
85
+ return [4 /*yield*/, this.client.get('/api/v1/comfy/health')];
86
+ case 1:
87
+ response = _a.sent();
88
+ return [2 /*return*/, response.data];
89
+ case 2:
90
+ error_1 = _a.sent();
91
+ this.handleError(error_1);
92
+ return [3 /*break*/, 3];
93
+ case 3: return [2 /*return*/];
94
+ }
95
+ });
96
+ });
97
+ };
98
+ /**
99
+ * Retrieves the queue data for all ComfyUI instances in the cluster.
100
+ */
101
+ FlowscaleAPI.prototype.getQueue = function () {
102
+ return __awaiter(this, void 0, void 0, function () {
103
+ var response, error_2;
104
+ return __generator(this, function (_a) {
105
+ switch (_a.label) {
106
+ case 0:
107
+ _a.trys.push([0, 2, , 3]);
108
+ return [4 /*yield*/, this.client.get('/api/v1/comfy/queue')];
109
+ case 1:
110
+ response = _a.sent();
111
+ return [2 /*return*/, response.data];
112
+ case 2:
113
+ error_2 = _a.sent();
114
+ this.handleError(error_2);
115
+ return [3 /*break*/, 3];
116
+ case 3: return [2 /*return*/];
117
+ }
118
+ });
119
+ });
120
+ };
121
+ /**
122
+ * Executes a specified workflow by processing dynamic form data.
123
+ * @param workflowId - The ID of the workflow to execute.
124
+ * @param data - Form data including text fields and file uploads.
125
+ * @param groupId - Optional group ID.
126
+ */
127
+ FlowscaleAPI.prototype.executeWorkflow = function (workflowId, data, groupId) {
128
+ return __awaiter(this, void 0, void 0, function () {
129
+ var formData_1, _loop_1, this_1, key, headers, url, response, error_3;
130
+ var _this = this;
131
+ return __generator(this, function (_a) {
132
+ switch (_a.label) {
133
+ case 0:
134
+ _a.trys.push([0, 2, , 3]);
135
+ formData_1 = new form_data_1.default();
136
+ _loop_1 = function (key) {
137
+ if (data.hasOwnProperty(key)) {
138
+ var value = data[key];
139
+ if (Array.isArray(value)) {
140
+ // Handle arrays (for multiple files)
141
+ value.forEach(function (item) {
142
+ _this.appendFormData(formData_1, key, item);
143
+ });
144
+ }
145
+ else {
146
+ this_1.appendFormData(formData_1, key, value);
147
+ }
148
+ }
149
+ };
150
+ this_1 = this;
151
+ // Append data to formData
152
+ for (key in data) {
153
+ _loop_1(key);
154
+ }
155
+ headers = __assign(__assign({}, formData_1.getHeaders()), { 'X-API-KEY': this.apiKey });
156
+ url = "/api/v1/runs?workflow_id=".concat(encodeURIComponent(workflowId)).concat(groupId ? "&group_id=".concat(encodeURIComponent(groupId)) : '');
157
+ return [4 /*yield*/, this.client.post(url, formData_1, { headers: headers })];
158
+ case 1:
159
+ response = _a.sent();
160
+ return [2 /*return*/, response.data];
161
+ case 2:
162
+ error_3 = _a.sent();
163
+ this.handleError(error_3);
164
+ return [3 /*break*/, 3];
165
+ case 3: return [2 /*return*/];
166
+ }
167
+ });
168
+ });
169
+ };
170
+ /**
171
+ * Retrieves the output of a specific run by providing the filename.
172
+ * @param filename - The filename of the output to retrieve.
173
+ */
174
+ FlowscaleAPI.prototype.getOutput = function (filename) {
175
+ return __awaiter(this, void 0, void 0, function () {
176
+ var response, error_4, axiosError;
177
+ return __generator(this, function (_a) {
178
+ switch (_a.label) {
179
+ case 0:
180
+ _a.trys.push([0, 2, , 3]);
181
+ return [4 /*yield*/, this.client.get('/api/v1/runs/output', {
182
+ params: { filename: filename },
183
+ })];
184
+ case 1:
185
+ response = _a.sent();
186
+ if (response.status === 204) {
187
+ return [2 /*return*/, null];
188
+ }
189
+ return [2 /*return*/, response.data];
190
+ case 2:
191
+ error_4 = _a.sent();
192
+ axiosError = error_4;
193
+ if (axiosError.response && axiosError.response.status === 204) {
194
+ return [2 /*return*/, null]; // No output found
195
+ }
196
+ else if (axiosError.response &&
197
+ axiosError.response.status === 408) {
198
+ throw new Error('Run Timeout');
199
+ }
200
+ else {
201
+ this.handleError(error_4);
202
+ }
203
+ return [3 /*break*/, 3];
204
+ case 3: return [2 /*return*/];
205
+ }
206
+ });
207
+ });
208
+ };
209
+ /**
210
+ * Cancels a specific run using its unique run ID.
211
+ * @param runId - The ID of the run to cancel.
212
+ */
213
+ FlowscaleAPI.prototype.cancelRun = function (runId) {
214
+ return __awaiter(this, void 0, void 0, function () {
215
+ var response, error_5;
216
+ return __generator(this, function (_a) {
217
+ switch (_a.label) {
218
+ case 0:
219
+ _a.trys.push([0, 2, , 3]);
220
+ return [4 /*yield*/, this.client.post("/api/v1/runs/".concat(encodeURIComponent(runId), "/cancel"))];
221
+ case 1:
222
+ response = _a.sent();
223
+ return [2 /*return*/, response.data];
224
+ case 2:
225
+ error_5 = _a.sent();
226
+ this.handleError(error_5);
227
+ return [3 /*break*/, 3];
228
+ case 3: return [2 /*return*/];
229
+ }
230
+ });
231
+ });
232
+ };
233
+ /**
234
+ * Retrieves detailed information about a specific run using its unique run ID.
235
+ * @param runId - The ID of the run to retrieve.
236
+ */
237
+ FlowscaleAPI.prototype.getRun = function (runId) {
238
+ return __awaiter(this, void 0, void 0, function () {
239
+ var response, error_6;
240
+ return __generator(this, function (_a) {
241
+ switch (_a.label) {
242
+ case 0:
243
+ _a.trys.push([0, 2, , 3]);
244
+ return [4 /*yield*/, this.client.get("/api/v1/runs/".concat(encodeURIComponent(runId)))];
245
+ case 1:
246
+ response = _a.sent();
247
+ return [2 /*return*/, response.data];
248
+ case 2:
249
+ error_6 = _a.sent();
250
+ this.handleError(error_6);
251
+ return [3 /*break*/, 3];
252
+ case 3: return [2 /*return*/];
253
+ }
254
+ });
255
+ });
256
+ };
257
+ /**
258
+ * Retrieves a list of all runs associated with a specific group ID.
259
+ * If no group ID is provided, all runs will be returned.
260
+ * @param groupId - The group ID to filter runs.
261
+ */
262
+ FlowscaleAPI.prototype.getRuns = function (groupId) {
263
+ return __awaiter(this, void 0, void 0, function () {
264
+ var params, response, error_7;
265
+ return __generator(this, function (_a) {
266
+ switch (_a.label) {
267
+ case 0:
268
+ _a.trys.push([0, 2, , 3]);
269
+ params = groupId ? { group_id: groupId } : {};
270
+ return [4 /*yield*/, this.client.get('/api/v1/runs', { params: params })];
271
+ case 1:
272
+ response = _a.sent();
273
+ return [2 /*return*/, response.data];
274
+ case 2:
275
+ error_7 = _a.sent();
276
+ this.handleError(error_7);
277
+ return [3 /*break*/, 3];
278
+ case 3: return [2 /*return*/];
279
+ }
280
+ });
281
+ });
282
+ };
283
+ /**
284
+ * Helper method to append data to FormData.
285
+ */
286
+ FlowscaleAPI.prototype.appendFormData = function (formData, key, value) {
287
+ if (value instanceof fs_1.default.ReadStream) {
288
+ // It's a file stream
289
+ formData.append(key, value);
290
+ }
291
+ else if (Buffer.isBuffer(value)) {
292
+ // It's a Buffer
293
+ formData.append(key, value, { filename: "".concat(key, ".dat") });
294
+ }
295
+ else if (typeof value === 'string' && fs_1.default.existsSync(value)) {
296
+ // If the value is a file path
297
+ var fileName = path_1.default.basename(value);
298
+ formData.append(key, fs_1.default.createReadStream(value), fileName);
299
+ }
300
+ else {
301
+ // Assume it's a string or other value
302
+ formData.append(key, value);
303
+ }
304
+ };
305
+ /**
306
+ * Error handling helper.
307
+ */
308
+ FlowscaleAPI.prototype.handleError = function (error) {
309
+ if (axios_1.default.isAxiosError(error)) {
310
+ if (error.response) {
311
+ // Server responded with a status code outside 2xx
312
+ throw new Error("Error: ".concat(error.response.status, " ").concat(error.response.statusText, " - ").concat(JSON.stringify(error.response.data)));
313
+ }
314
+ else if (error.request) {
315
+ // Request was made but no response
316
+ throw new Error('No response received from API server');
317
+ }
318
+ }
319
+ console.error(error);
320
+ // Something else happened
321
+ throw new Error("Error: ".concat(error.message));
322
+ };
323
+ return FlowscaleAPI;
324
+ }());
325
+ exports.FlowscaleAPI = FlowscaleAPI;
@@ -0,0 +1,72 @@
1
+ export interface HealthCheckResponse {
2
+ status: string;
3
+ data: Array<{
4
+ container: string;
5
+ status: string;
6
+ }>;
7
+ }
8
+ export interface QueueResponse {
9
+ status: string;
10
+ data: Array<{
11
+ container: string;
12
+ queue: {
13
+ queue_running: any[];
14
+ queue_pending: any[];
15
+ };
16
+ }>;
17
+ }
18
+ export interface ExecuteWorkflowResponse {
19
+ status: string;
20
+ data: {
21
+ output_names: string[];
22
+ run_id: string;
23
+ };
24
+ }
25
+ export interface GetOutputResponse {
26
+ status: string;
27
+ data: {
28
+ download_url: string;
29
+ generation_status: string;
30
+ };
31
+ }
32
+ export interface RunDetail {
33
+ _id: string;
34
+ team_id: string;
35
+ workflow_id: string;
36
+ group_id?: string;
37
+ status: string;
38
+ inputs: Array<{
39
+ path: string;
40
+ value: string;
41
+ s3_key?: string;
42
+ url?: string;
43
+ }>;
44
+ outputs: Array<{
45
+ filename: string;
46
+ s3_key?: string;
47
+ url?: string;
48
+ }>;
49
+ created_at: string;
50
+ started_at?: string;
51
+ completed_at?: string;
52
+ }
53
+ export interface RunDetailResponse {
54
+ status: string;
55
+ data: RunDetail;
56
+ }
57
+ export interface RunListResponse {
58
+ status: string;
59
+ data: {
60
+ group_id: string;
61
+ count: number;
62
+ runs: RunDetail[];
63
+ };
64
+ }
65
+ export interface CancelRunResponse {
66
+ status: string;
67
+ data: string;
68
+ }
69
+ export interface ErrorResponse {
70
+ status: string;
71
+ errors: string;
72
+ }
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // src/types.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "flowscale",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "An NPM library for communicating with the Flowscale APIs",
5
- "main": "build/index.js",
6
- "files": ["build/**/*"],
5
+ "main": "dist/index.js",
7
6
  "types": "dist/index.d.ts",
8
7
  "keywords": [
9
8
  "flowscale",
@@ -13,8 +12,7 @@
13
12
  ],
14
13
  "scripts": {
15
14
  "build": "tsc",
16
- "test": "echo \"No tests yet\"",
17
- "obfuscate": "javascript-obfuscator dist --output build --compact true --control-flow-flattening true"
15
+ "test": "echo \"No tests yet\""
18
16
  },
19
17
  "author": "flowscale",
20
18
  "license": "MIT",
@@ -25,7 +23,6 @@
25
23
  "devDependencies": {
26
24
  "@types/form-data": "^2.5.2",
27
25
  "@types/node": "^22.9.1",
28
- "javascript-obfuscator": "^4.1.1",
29
26
  "typescript": "^5.6.3"
30
27
  }
31
28
  }
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES5",
4
+ "module": "CommonJS",
5
+ "declaration": true,
6
+ "outDir": "./dist",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "sourceMap": false
10
+ },
11
+ "include": ["src/**/*"]
12
+ }
package/build/index.js DELETED
@@ -1 +0,0 @@
1
- 'use strict';function a0_0x5a40(_0xe945df,_0xd68e0e){const _0xe834c4=a0_0xe834();return a0_0x5a40=function(_0x5a40dd,_0x460441){_0x5a40dd=_0x5a40dd-0x8d;let _0x3349be=_0xe834c4[_0x5a40dd];return _0x3349be;},a0_0x5a40(_0xe945df,_0xd68e0e);}const a0_0x5ed9ff=a0_0x5a40;(function(_0x41dd83,_0x44d2e2){const _0x203116=a0_0x5a40,_0x521bf8=_0x41dd83();while(!![]){try{const _0x24a456=parseInt(_0x203116(0xcd))/0x1*(parseInt(_0x203116(0xc3))/0x2)+parseInt(_0x203116(0x92))/0x3*(parseInt(_0x203116(0xc6))/0x4)+-parseInt(_0x203116(0x96))/0x5+parseInt(_0x203116(0xa7))/0x6+parseInt(_0x203116(0xb6))/0x7*(parseInt(_0x203116(0xa5))/0x8)+-parseInt(_0x203116(0xb0))/0x9+parseInt(_0x203116(0xb1))/0xa*(-parseInt(_0x203116(0xcf))/0xb);if(_0x24a456===_0x44d2e2)break;else _0x521bf8['push'](_0x521bf8['shift']());}catch(_0x5a2034){_0x521bf8['push'](_0x521bf8['shift']());}}}(a0_0xe834,0xdbcae));var __importDefault=this&&this['__importDefault']||function(_0x329175){return _0x329175&&_0x329175['__esModule']?_0x329175:{'default':_0x329175};};Object[a0_0x5ed9ff(0x97)](exports,'__esModule',{'value':!![]}),exports['FlowscaleAPI']=void 0x0;const axios_1=__importDefault(require(a0_0x5ed9ff(0xb7))),form_data_1=__importDefault(require(a0_0x5ed9ff(0xaf))),fs_1=__importDefault(require('fs')),path_1=__importDefault(require('path'));function a0_0xe834(){const _0x29c3ea=['jVnBK','basename','handleError','getHeaders','getRuns','LOdVU','default','16293EKlBoF','status','stringify','.dat','196830QdYunZ','defineProperty','pJVjV','apiKey','dJLQq','isAxiosError','/api/v1/runs','No\x20response\x20received\x20from\x20API\x20server','/cancel','headers','ZjcsO','&group_id=','Run\x20Timeout','ReadStream','get','9904noIEDH','error','2784996cHoHEo','hasOwnProperty','cMqok','append','createReadStream','AOfDO','post','RqHEZ','form-data','5296401BYTkmh','10184730MNpiCC','appendFormData','create','response','baseUrl','6447mpnvdi','axios','isBuffer','isArray','message','\x20-\x20','Error:\x20','X-API-KEY','/api/v1/runs/','getOutput','executeWorkflow','/api/v1/runs/output','PYGkf','3738sQheyw','use','getQueue','252HmTOBc','request','checkHealth','/api/v1/comfy/queue','client','/api/v1/comfy/health','FlowscaleAPI','866xxBAxk','assign','22Ttrpsz','cancelRun','data'];a0_0xe834=function(){return _0x29c3ea;};return a0_0xe834();}class FlowscaleAPI{constructor(_0x11d681,_0x33822d){const _0x9d379e=a0_0x5ed9ff,_0x16b3f9={'RqHEZ':_0x9d379e(0xbd)};this['apiKey']=_0x11d681,this[_0x9d379e(0xb5)]=_0x33822d,this[_0x9d379e(0xca)]=axios_1[_0x9d379e(0x91)][_0x9d379e(0xb3)]({'baseURL':this[_0x9d379e(0xb5)]}),this[_0x9d379e(0xca)]['interceptors'][_0x9d379e(0xc7)][_0x9d379e(0xc4)](_0x453ba8=>{const _0x4899de=_0x9d379e;return!_0x453ba8[_0x4899de(0x9f)]&&(_0x453ba8[_0x4899de(0x9f)]={}),_0x453ba8['headers'][_0x16b3f9[_0x4899de(0xae)]]=this[_0x4899de(0x99)],_0x453ba8;});}async[a0_0x5ed9ff(0xc8)](){const _0x1b7103=a0_0x5ed9ff,_0x49df63={'dJLQq':_0x1b7103(0xcb)};try{const _0x3a5c79=await this[_0x1b7103(0xca)][_0x1b7103(0xa4)](_0x49df63[_0x1b7103(0x9a)]);return _0x3a5c79[_0x1b7103(0xd1)];}catch(_0x4a9ca6){this['handleError'](_0x4a9ca6);}}async[a0_0x5ed9ff(0xc5)](){const _0x40bc0e=a0_0x5ed9ff;try{const _0x5b4779=await this[_0x40bc0e(0xca)][_0x40bc0e(0xa4)](_0x40bc0e(0xc9));return _0x5b4779['data'];}catch(_0xe24c63){this[_0x40bc0e(0x8d)](_0xe24c63);}}async[a0_0x5ed9ff(0xc0)](_0x3a9eeb,_0x5a922a,_0x3062eb){const _0x547371=a0_0x5ed9ff,_0x56623b={'cMqok':function(_0x46e8c9,_0x33e5ce){return _0x46e8c9(_0x33e5ce);},'PYGkf':function(_0xe1bb80,_0x2e7296){return _0xe1bb80(_0x2e7296);}};try{const _0xcb00a2=new form_data_1[(_0x547371(0x91))]();for(const _0x5d84e9 in _0x5a922a){if(_0x5a922a[_0x547371(0xa8)](_0x5d84e9)){const _0x88984c=_0x5a922a[_0x5d84e9];Array[_0x547371(0xb9)](_0x88984c)?_0x88984c['forEach'](_0x234eb0=>{this['appendFormData'](_0xcb00a2,_0x5d84e9,_0x234eb0);}):this[_0x547371(0xb2)](_0xcb00a2,_0x5d84e9,_0x88984c);}}const _0x43e13c=Object['assign'](Object[_0x547371(0xce)]({},_0xcb00a2[_0x547371(0x8e)]()),{'X-API-KEY':this[_0x547371(0x99)]}),_0x32f8ba='/api/v1/runs?workflow_id='+_0x56623b[_0x547371(0xa9)](encodeURIComponent,_0x3a9eeb)+(_0x3062eb?_0x547371(0xa1)+_0x56623b[_0x547371(0xc2)](encodeURIComponent,_0x3062eb):''),_0x33e601=await this[_0x547371(0xca)][_0x547371(0xad)](_0x32f8ba,_0xcb00a2,{'headers':_0x43e13c});return _0x33e601[_0x547371(0xd1)];}catch(_0x522fd3){this['handleError'](_0x522fd3);}}async[a0_0x5ed9ff(0xbf)](_0x2355b5){const _0x5833da=a0_0x5ed9ff,_0x1c94f4={'pJVjV':function(_0x3b9ed6,_0x42d9a4){return _0x3b9ed6===_0x42d9a4;},'JXHXf':_0x5833da(0xa2)};try{const _0x1fb445=await this[_0x5833da(0xca)][_0x5833da(0xa4)](_0x5833da(0xc1),{'params':{'filename':_0x2355b5}});if(_0x1fb445['status']===0xcc)return null;return _0x1fb445[_0x5833da(0xd1)];}catch(_0x3acd2e){const _0x35e577=_0x3acd2e;if(_0x35e577[_0x5833da(0xb4)]&&_0x1c94f4['pJVjV'](_0x35e577[_0x5833da(0xb4)][_0x5833da(0x93)],0xcc))return null;else{if(_0x35e577[_0x5833da(0xb4)]&&_0x1c94f4[_0x5833da(0x98)](_0x35e577[_0x5833da(0xb4)][_0x5833da(0x93)],0x198))throw new Error(_0x1c94f4['JXHXf']);else this[_0x5833da(0x8d)](_0x3acd2e);}}}async[a0_0x5ed9ff(0xd0)](_0x232193){const _0x508f76=a0_0x5ed9ff,_0x2cf794={'OdMms':function(_0x5712f9,_0x403582){return _0x5712f9(_0x403582);}};try{const _0x3a3e68=await this[_0x508f76(0xca)]['post'](_0x508f76(0xbe)+_0x2cf794['OdMms'](encodeURIComponent,_0x232193)+_0x508f76(0x9e));return _0x3a3e68[_0x508f76(0xd1)];}catch(_0x13f420){this['handleError'](_0x13f420);}}async['getRun'](_0x464afd){const _0x42f799=a0_0x5ed9ff,_0x3a06f8={'ZjcsO':function(_0x126d51,_0x4aac7e){return _0x126d51(_0x4aac7e);}};try{const _0x268884=await this[_0x42f799(0xca)][_0x42f799(0xa4)](_0x42f799(0xbe)+_0x3a06f8[_0x42f799(0xa0)](encodeURIComponent,_0x464afd));return _0x268884[_0x42f799(0xd1)];}catch(_0x29f7b3){this['handleError'](_0x29f7b3);}}async[a0_0x5ed9ff(0x8f)](_0x50b836){const _0x57b4c8=a0_0x5ed9ff;try{const _0x4abe6c=_0x50b836?{'group_id':_0x50b836}:{},_0x14e784=await this[_0x57b4c8(0xca)]['get'](_0x57b4c8(0x9c),{'params':_0x4abe6c});return _0x14e784[_0x57b4c8(0xd1)];}catch(_0x8fb1db){this[_0x57b4c8(0x8d)](_0x8fb1db);}}['appendFormData'](_0x1fe3f7,_0x28a0fe,_0x4a9f9b){const _0x3eb78e=a0_0x5ed9ff,_0x34fd50={'AOfDO':function(_0x408972,_0x4cf185){return _0x408972 instanceof _0x4cf185;},'LOdVU':function(_0x185cc3,_0x443302){return _0x185cc3===_0x443302;}};if(_0x34fd50[_0x3eb78e(0xac)](_0x4a9f9b,fs_1[_0x3eb78e(0x91)][_0x3eb78e(0xa3)]))_0x1fe3f7[_0x3eb78e(0xaa)](_0x28a0fe,_0x4a9f9b);else{if(Buffer[_0x3eb78e(0xb8)](_0x4a9f9b))_0x1fe3f7[_0x3eb78e(0xaa)](_0x28a0fe,_0x4a9f9b,{'filename':_0x28a0fe+_0x3eb78e(0x95)});else{if(_0x34fd50[_0x3eb78e(0x90)](typeof _0x4a9f9b,'string')&&fs_1[_0x3eb78e(0x91)]['existsSync'](_0x4a9f9b)){const _0x12f911=path_1[_0x3eb78e(0x91)][_0x3eb78e(0xd3)](_0x4a9f9b);_0x1fe3f7[_0x3eb78e(0xaa)](_0x28a0fe,fs_1[_0x3eb78e(0x91)][_0x3eb78e(0xab)](_0x4a9f9b),_0x12f911);}else _0x1fe3f7[_0x3eb78e(0xaa)](_0x28a0fe,_0x4a9f9b);}}}[a0_0x5ed9ff(0x8d)](_0x56b03e){const _0x22aa77=a0_0x5ed9ff,_0x4bd758={'jVnBK':_0x22aa77(0x9d)};if(axios_1[_0x22aa77(0x91)][_0x22aa77(0x9b)](_0x56b03e)){if(_0x56b03e['response'])throw new Error(_0x22aa77(0xbc)+_0x56b03e[_0x22aa77(0xb4)][_0x22aa77(0x93)]+'\x20'+_0x56b03e['response']['statusText']+_0x22aa77(0xbb)+JSON[_0x22aa77(0x94)](_0x56b03e[_0x22aa77(0xb4)][_0x22aa77(0xd1)]));else{if(_0x56b03e['request'])throw new Error(_0x4bd758[_0x22aa77(0xd2)]);}}console[_0x22aa77(0xa6)](_0x56b03e);throw new Error('Error:\x20'+_0x56b03e[_0x22aa77(0xba)]);}}exports[a0_0x5ed9ff(0xcc)]=FlowscaleAPI;
package/build/types.js DELETED
@@ -1 +0,0 @@
1
- 'use strict';function a1_0x1b1a(_0x36037a,_0x40f7bc){var _0x314667=a1_0x3146();return a1_0x1b1a=function(_0x1b1a97,_0x171d59){_0x1b1a97=_0x1b1a97-0x91;var _0x2f973d=_0x314667[_0x1b1a97];return _0x2f973d;},a1_0x1b1a(_0x36037a,_0x40f7bc);}var a1_0x17e3e5=a1_0x1b1a;(function(_0x8d28f,_0x4ac3ab){var _0xc3d43d=a1_0x1b1a,_0x4012aa=_0x8d28f();while(!![]){try{var _0x498b9c=parseInt(_0xc3d43d(0x9d))/0x1*(parseInt(_0xc3d43d(0x94))/0x2)+-parseInt(_0xc3d43d(0x9c))/0x3*(parseInt(_0xc3d43d(0x9a))/0x4)+-parseInt(_0xc3d43d(0x9b))/0x5*(-parseInt(_0xc3d43d(0x99))/0x6)+parseInt(_0xc3d43d(0x91))/0x7+parseInt(_0xc3d43d(0x92))/0x8*(-parseInt(_0xc3d43d(0x98))/0x9)+parseInt(_0xc3d43d(0x96))/0xa*(-parseInt(_0xc3d43d(0x95))/0xb)+parseInt(_0xc3d43d(0x97))/0xc;if(_0x498b9c===_0x4ac3ab)break;else _0x4012aa['push'](_0x4012aa['shift']());}catch(_0x46efc7){_0x4012aa['push'](_0x4012aa['shift']());}}}(a1_0x3146,0x91b07));function a1_0x3146(){var _0x5f15a4=['16381824RxlyWM','549VgKbrd','1027902MYLjFE','124xhXdRO','15lFlVdX','102099RrYhiy','1aqhobI','1252083mkaTKP','50376vALnMF','__esModule','1101034sKiyxY','153626DLyiau','410ebYvBj'];a1_0x3146=function(){return _0x5f15a4;};return a1_0x3146();}Object['defineProperty'](exports,a1_0x17e3e5(0x93),{'value':!![]});