flowscale 1.0.17 → 1.0.18-beta.1

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/CLAUDE.md ADDED
@@ -0,0 +1,73 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ - **Build**: `npm run build` or `tsc` - Compiles TypeScript to JavaScript in `/dist`
8
+ - **Test**: `echo "No tests yet"` - Currently no test framework is configured
9
+ - **Publish Beta**: `npm run publish:beta` - Publishes to npm with beta tag
10
+ - **Publish Latest**: `npm run publish:latest` - Publishes to npm as latest version
11
+
12
+ ## Architecture Overview
13
+
14
+ This is a TypeScript SDK for interacting with the Flowscale ComfyUI API. The codebase is structured as follows:
15
+
16
+ ### Core Components
17
+
18
+ - **FlowscaleAPI Class** (`src/index.ts`): The main SDK class that provides all API methods
19
+ - Uses Axios for HTTP requests with built-in retry logic and timeout handling
20
+ - Supports both Node.js and browser environments with security warnings for browser usage
21
+ - Includes WebSocket support for real-time communication (browser only)
22
+ - Has configurable logging with different levels (debug, info, warn, error)
23
+
24
+ - **Type Definitions** (`src/types.ts`): Comprehensive TypeScript interfaces for:
25
+ - API responses (HealthCheckResponse, WorkflowResponse, etc.)
26
+ - Configuration options (FlowscaleConfig)
27
+ - WebSocket-related types (WebSocketOptions, WebSocketMessage)
28
+
29
+ ### Key Features
30
+
31
+ 1. **Environment Detection**: Automatically detects Node.js vs browser environments
32
+ 2. **Security**: Multiple security modes including secure proxy mode for frontend usage and API key protection
33
+ 3. **Input Validation**: Comprehensive validation for all required parameters with helpful error messages
34
+ 4. **File Upload Support**: Handles FormData for file uploads in workflow execution
35
+ 5. **Async Workflow Execution**: `executeWorkflowAsync` method polls for all outputs and waits for completion automatically
36
+ 6. **WebSocket Integration**: Real-time updates for workflow status (supports both browser and Node.js with WebSocket polyfill) with proper memory management
37
+ 7. **Error Handling**: Consistent error handling with retry logic for timeouts and 504 errors
38
+
39
+ ### API Methods Structure
40
+
41
+ All API methods follow this pattern:
42
+ - Make HTTP requests using the internal `makeRequest` method
43
+ - Return typed responses based on interfaces in `types.ts`
44
+ - Handle authentication via X-API-KEY header
45
+ - Support both individual operations and bulk operations where applicable
46
+
47
+ ### Configuration
48
+
49
+ The SDK requires:
50
+ - `apiKey`: Flowscale API key (optional in proxy mode)
51
+ - `baseUrl`: API endpoint URL
52
+ - Optional: timeout, retry settings
53
+ - Optional: `proxyMode` - Enable secure frontend usage without exposing API key
54
+ - Optional: `customHeaders` - For JWT tokens, session cookies, etc.
55
+ - Optional: `WebSocketImpl` - For Node.js environments, pass the 'ws' WebSocket constructor to enable WebSocket functionality
56
+
57
+ ### Build Configuration
58
+
59
+ - TypeScript compiler targets ES5 with CommonJS modules
60
+ - Outputs declaration files for TypeScript consumers
61
+ - Uses strict type checking
62
+ - Builds to `dist/` directory
63
+
64
+ ## Important Notes
65
+
66
+ - No test framework is currently configured
67
+ - WebSocket functionality works in both browser and Node.js environments (Node.js requires passing `WebSocketImpl: require('ws')`)
68
+ - **Security**: Supports both direct API key usage and secure proxy mode for frontend applications
69
+ - **Proxy Mode**: Enables secure frontend usage by routing requests through a backend proxy that holds the API key
70
+ - All file uploads are handled through FormData with support for File/Blob objects
71
+ - The SDK has built-in retry logic for network timeouts and gateway errors
72
+ - Comprehensive input validation prevents common configuration errors
73
+ - Dynamic header management supports JWT token refresh and session management
package/README.md CHANGED
@@ -4,20 +4,39 @@ A comprehensive SDK designed to simplify interaction with the FlowScale ComfyUI
4
4
 
5
5
  ---
6
6
 
7
- ## ⚠️ Important Security Notice for Browser Usage
7
+ ## 🔒 Secure Frontend Usage (Recommended)
8
8
 
9
- When using this SDK in a browser environment, your API key will be exposed to end users. This is a significant security risk. We strongly recommend:
9
+ For secure frontend usage, use **Proxy Mode** to keep your API key safe on the backend:
10
10
 
11
- 1. Using this SDK in a Node.js backend environment
12
- 2. Creating a proxy API that securely handles the API key server-side
11
+ ```javascript
12
+ // SECURE: No API key exposed to frontend users
13
+ const flowscale = new FlowscaleAPI({
14
+ baseUrl: 'https://your-backend-proxy.com', // Your secure backend proxy
15
+ proxyMode: true, // Enable proxy mode
16
+ customHeaders: {
17
+ 'Authorization': 'Bearer jwt-token-here' // Use JWT tokens instead
18
+ }
19
+ });
20
+ ```
21
+
22
+ ### Security Options:
13
23
 
14
- If you understand the risks and still need to use the SDK directly in the browser, you must explicitly acknowledge this by setting the `allowDangerouslyExposeApiKey` option:
24
+ 1. **🔒 Backend-Only (MOST SECURE)**: Use SDK only on backend, frontend makes simple API calls to your server
25
+ 2. **🔒 Proxy Mode**: Frontend SDK routes through your backend proxy (provides SDK convenience with security)
26
+ 3. **⚠️ Direct Mode**: API key is exposed in browser (only for development/demos)
27
+
28
+ **Recommendation:** For production apps, use Backend-Only approach for maximum security and simplicity.
29
+
30
+ ## ⚠️ Direct Browser Usage Warning
31
+
32
+ If you use the SDK directly in the browser with an API key, it will be exposed to end users. Only do this for development:
15
33
 
16
34
  ```javascript
35
+ // ⚠️ WARNING: API key will be visible to users
17
36
  const flowscale = new FlowscaleAPI({
18
37
  apiKey: 'your-api-key',
19
38
  baseUrl: 'your-api-url',
20
- allowDangerouslyExposeApiKey: false // Only set to true if you understand the security risks
39
+ allowDangerouslyExposeApiKey: true // Required acknowledgment
21
40
  });
22
41
  ```
23
42
 
@@ -240,14 +259,14 @@ console.log('Workflow Result:', result);
240
259
  ### 5 `executeWorkflowAsync(workflowId, data, groupId?, pollIntervalMs?, timeoutMs?)`
241
260
 
242
261
  **Description:**
243
- Execute a workflow and automatically wait for the result by polling the output. This is a convenience method that combines `executeWorkflow` and `getOutput` with automatic polling.
262
+ Execute a workflow and automatically wait for all outputs by polling. This is a convenience method that combines `executeWorkflow` and `getOutput` with automatic polling for all workflow outputs.
244
263
 
245
264
  **Parameters:**
246
265
  - `workflowId` *(string)*: The unique ID of the workflow.
247
266
  - `data` *(object)*: Input parameters for the workflow.
248
267
  - `groupId` *(string, optional)*: A custom identifier for grouping runs.
249
- - `pollIntervalMs` *(number, optional)*: Polling interval in milliseconds (default: 1000).
250
- - `timeoutMs` *(number, optional)*: Maximum time to wait for results in milliseconds (default: 300000 - 5 minutes).
268
+ - `pollIntervalMs` *(number, optional)*: Polling interval in milliseconds (default: 2000).
269
+ - `timeoutMs` *(number, optional)*: Maximum time to wait for results in milliseconds (default: 600000 - 10 minutes).
251
270
 
252
271
  **Usage:**
253
272
  ```javascript
@@ -273,10 +292,18 @@ try {
273
292
  ```json
274
293
  {
275
294
  "status": "success",
276
- "data": {
277
- "download_url": "https://runs.s3.amazonaws.com/generations/...",
278
- "generation_status": "success"
279
- }
295
+ "data": [
296
+ {
297
+ "filename": "output_image_1.png",
298
+ "download_url": "https://runs.s3.amazonaws.com/generations/...",
299
+ "generation_status": "success"
300
+ },
301
+ {
302
+ "filename": "output_image_2.png",
303
+ "download_url": "https://runs.s3.amazonaws.com/generations/...",
304
+ "generation_status": "success"
305
+ }
306
+ ]
280
307
  }
281
308
  ```
282
309
 
@@ -421,47 +448,6 @@ console.log('All Runs:', allRuns);
421
448
  - Always store sensitive information such as API keys in environment variables.
422
449
  - Use `.env` files and libraries like `dotenv` for easy environment management.
423
450
 
424
- ### Logging Configuration
425
- The SDK includes configurable logging to help with debugging and monitoring. By default, logging is enabled with the 'info' level.
426
-
427
- #### Configuration Options
428
- ```javascript
429
- const flowscale = new FlowscaleAPI({
430
- apiKey: 'your-api-key',
431
- baseUrl: 'https://your-api-url.pod.flowscale.ai',
432
- enableLogging: true, // Enable/disable logging (default: true)
433
- logLevel: 'info' // Set log level: 'debug', 'info', 'warn', 'error' (default: 'info')
434
- });
435
- ```
436
-
437
- #### Dynamic Logging Control
438
- You can also change logging settings after initialization:
439
-
440
- ```javascript
441
- // Enable debug logging
442
- flowscale.setLoggingConfig(true, 'debug');
443
-
444
- // Disable logging completely
445
- flowscale.setLoggingConfig(false);
446
-
447
- // Check current logging configuration
448
- const loggingConfig = flowscale.getLoggingConfig();
449
- console.log(loggingConfig); // { enabled: true, level: 'debug' }
450
- ```
451
-
452
- #### Log Levels
453
- - **debug**: Most verbose, includes detailed operation information
454
- - **info**: General information about operations (default)
455
- - **warn**: Warning messages for potential issues
456
- - **error**: Only error messages
457
-
458
- #### Log Format
459
- All logs are prefixed with timestamp and level:
460
- ```
461
- [Flowscale INFO] 2025-06-03T10:30:45.123Z: WebSocket connection established
462
- [Flowscale DEBUG] 2025-06-03T10:30:46.456Z: Polling workflow output: {...}
463
- ```
464
-
465
451
  ### Error Handling
466
452
  - Wrap API calls in try-catch blocks to handle errors gracefully.
467
453
  - Log errors for debugging and improve resilience.
@@ -583,12 +569,100 @@ See `examples/websocket-example.html` for a complete browser example with a user
583
569
  #### Node.js Example
584
570
  Node.js requires a custom WebSocket implementation since the WebSocket API is not built-in. See `examples/node-websocket-example.js` for an example using the 'ws' library.
585
571
 
586
- **Note:** To use WebSockets in Node.js, you'll need to install the 'ws' package:
572
+ **Note:** To use WebSockets in Node.js, you'll need to install the 'ws' package and pass it to the SDK:
587
573
  ```bash
588
574
  npm install ws
589
575
  ```
590
576
 
591
- **Note:** WebSocket functionality is natively available only in browser environments. For Node.js, you need to use a WebSocket library like `ws`.
577
+ ```javascript
578
+ const WebSocket = require('ws');
579
+ const flowscale = new FlowscaleAPI({
580
+ apiKey: 'your-api-key',
581
+ baseUrl: 'https://your-api-url.pod.flowscale.ai',
582
+ WebSocketImpl: WebSocket // Pass the WebSocket implementation for Node.js
583
+ });
584
+
585
+ // Now you can use WebSocket methods directly in Node.js!
586
+ const disconnect = flowscale.connectWebSocket({
587
+ onOpen: () => console.log('Connected!'),
588
+ onMessage: (message) => console.log('Message:', message),
589
+ onClose: (event) => console.log('Closed:', event),
590
+ onError: (error) => console.error('Error:', error)
591
+ });
592
+ ```
593
+
594
+ ---
595
+
596
+ ## 🔒 Advanced Security Features
597
+
598
+ ### Proxy Mode Configuration
599
+
600
+ ```javascript
601
+ const flowscale = new FlowscaleAPI({
602
+ baseUrl: 'https://your-backend-proxy.com',
603
+ proxyMode: true,
604
+ customHeaders: {
605
+ 'Authorization': 'Bearer your-jwt-token',
606
+ 'X-User-ID': 'user123' // Additional custom headers
607
+ }
608
+ });
609
+ ```
610
+
611
+ ### Dynamic Header Management
612
+
613
+ ```javascript
614
+ // Update JWT token without recreating SDK instance
615
+ flowscale.updateCustomHeaders({
616
+ 'Authorization': 'Bearer new-jwt-token'
617
+ });
618
+
619
+ // Get current headers
620
+ const headers = flowscale.getCustomHeaders();
621
+
622
+ // Clear all custom headers
623
+ flowscale.clearCustomHeaders();
624
+ ```
625
+
626
+ ### Architecture Options
627
+
628
+ #### Option 1: Backend-Only (Recommended)
629
+ ```javascript
630
+ // Backend - Use Flowscale SDK
631
+ const flowscale = new FlowscaleAPI({
632
+ apiKey: process.env.FLOWSCALE_API_KEY,
633
+ baseUrl: process.env.FLOWSCALE_API_URL
634
+ });
635
+
636
+ app.post('/api/workflows/execute', async (req, res) => {
637
+ const result = await flowscale.executeWorkflowAsync(req.body.workflowId, req.body.data);
638
+ res.json(result);
639
+ });
640
+
641
+ // Frontend - Simple API calls
642
+ const result = await fetch('/api/workflows/execute', {
643
+ method: 'POST',
644
+ headers: { 'Authorization': 'Bearer ' + token },
645
+ body: JSON.stringify({ workflowId, data })
646
+ });
647
+ ```
648
+
649
+ #### Option 2: Proxy Mode (SDK Convenience)
650
+ ```javascript
651
+ // Backend - SDK + Proxy endpoints
652
+ const flowscale = new FlowscaleAPI({
653
+ apiKey: process.env.FLOWSCALE_API_KEY,
654
+ baseUrl: process.env.FLOWSCALE_API_URL
655
+ });
656
+
657
+ // Frontend - SDK through proxy
658
+ const flowscale = new FlowscaleAPI({
659
+ baseUrl: 'https://your-backend.com',
660
+ proxyMode: true,
661
+ customHeaders: { 'Authorization': 'Bearer jwt-token' }
662
+ });
663
+ ```
664
+
665
+ See `examples/secure-frontend-example.html` and `examples/backend-proxy-example.js` for complete implementation examples.
592
666
 
593
667
  ---
594
668
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HealthCheckResponse, QueueResponse, ExecuteWorkflowResponse, GetOutputResponse, RunDetailResponse, RunListResponse, CancelRunResponse, FlowscaleConfig, WorkflowResponse, WebSocketOptions } from './types';
1
+ import { HealthCheckResponse, QueueResponse, ExecuteWorkflowResponse, GetOutputResponse, GetAllOutputsResponse, RunDetailResponse, RunListResponse, CancelRunResponse, FlowscaleConfig, WorkflowResponse, WebSocketOptions } from './types';
2
2
  export declare class FlowscaleAPI {
3
3
  private apiKey;
4
4
  private baseUrl;
@@ -9,6 +9,10 @@ export declare class FlowscaleAPI {
9
9
  private ws;
10
10
  private wsConnected;
11
11
  private reconnectAttempts;
12
+ private reconnectTimeout;
13
+ private WebSocketImpl;
14
+ private proxyMode;
15
+ private customHeaders;
12
16
  constructor(config: FlowscaleConfig);
13
17
  /**
14
18
  * Checks the health status of all ComfyUI instances within the specified cluster.
@@ -32,7 +36,7 @@ export declare class FlowscaleAPI {
32
36
  [key: string]: any;
33
37
  }, groupId?: string): Promise<ExecuteWorkflowResponse>;
34
38
  /**
35
- * Executes a workflow and waits for the output by polling.
39
+ * Executes a workflow and waits for all outputs by polling.
36
40
  * @param workflowId - The ID of the workflow to execute.
37
41
  * @param data - Form data including text fields and file uploads.
38
42
  * @param groupId - Optional group ID.
@@ -41,7 +45,7 @@ export declare class FlowscaleAPI {
41
45
  */
42
46
  executeWorkflowAsync(workflowId: string, data: {
43
47
  [key: string]: any;
44
- }, groupId?: string, pollIntervalMs?: number, timeoutMs?: number): Promise<GetOutputResponse>;
48
+ }, groupId?: string, pollIntervalMs?: number, timeoutMs?: number): Promise<GetAllOutputsResponse>;
45
49
  /**
46
50
  * Retrieves the output of a specific run by providing the filename.
47
51
  * @param filename - The filename of the output to retrieve.
@@ -99,9 +103,28 @@ export declare class FlowscaleAPI {
99
103
  * @returns Whether the message was sent successfully
100
104
  */
101
105
  sendWebSocketMessage(message: any): boolean;
106
+ /**
107
+ * Updates custom headers for authentication (useful for refreshing JWT tokens)
108
+ * @param headers - Object containing header key-value pairs
109
+ */
110
+ updateCustomHeaders(headers: {
111
+ [key: string]: string;
112
+ }): void;
113
+ /**
114
+ * Clears all custom headers
115
+ */
116
+ clearCustomHeaders(): void;
117
+ /**
118
+ * Gets current custom headers
119
+ * @returns Copy of current custom headers
120
+ */
121
+ getCustomHeaders(): {
122
+ [key: string]: string;
123
+ };
102
124
  /**
103
125
  * Checks if the WebSocket connection is currently open.
104
126
  * @returns True if the WebSocket is connected, false otherwise
105
127
  */
106
128
  isWebSocketConnected(): boolean;
107
129
  }
130
+ export * from './types';