n8n-nodes-wavespeed
Version:
N8N nodes for WaveSpeed AI API - multimodal AI models for text-to-image, image-to-image, text-to-video, and image-to-video generation
150 lines (149 loc) • 6.45 kB
TypeScript
import { INodePropertyOptions, INodeProperties, IExecuteFunctions } from 'n8n-workflow';
/**
* WaveSpeed API Client with Signal Handling
*
* This client supports graceful interruption of long-running operations.
*
* Signal Handling Features:
* - Automatic Ctrl+C (SIGINT) and SIGTERM signal handling
* - Graceful cancellation of polling operations
* - AbortController support for custom cancellation scenarios
*
* Usage Examples:
*
* // Using with custom AbortSignal for manual cancellation
* const controller = new AbortController();
* const result = await WaveSpeedClient.waitForTaskCompletion(
* taskId,
* apiKey,
* 300000,
* 5000,
* 20,
* controller.signal
* );
* // To cancel: controller.abort();
*
* // Using with automatic signal handling and smart polling (default behavior)
* const result = await WaveSpeedClient.waitForTaskCompletion(taskId, apiKey);
* // This will automatically respond to Ctrl+C, use exponential backoff, and optimize intervals
*
* // Using with custom polling settings for high-frequency tasks
* const result = await WaveSpeedClient.waitForTaskCompletion(
* taskId,
* apiKey,
* 600000, // 10 minutes max wait
* 1000, // Start with 1 second interval
* 30 // Allow more retries
* );
*
* Signal Handling & Performance Optimizations:
* - The client automatically registers SIGINT (Ctrl+C) and SIGTERM handlers
* - Long-running operations like waitForTaskCompletion will be cancelled gracefully
* - Process will exit with appropriate exit codes (130 for SIGINT, 143 for SIGTERM)
* - Uses intelligent exponential backoff algorithm for efficient polling
* - Dynamic interval adjustment based on task status (pending/processing/running)
* - High-precision timing with performance.now() for accurate delays
* - Memory-efficient non-blocking sleep implementation (similar to Java Thread.sleep)
*/
export declare const WAVESPEED_API_BASE_URL = "https://api.wavespeed.ai";
export declare const WAVESPEED_CENTER_BASE_URL = "https://wavespeed.ai";
export interface WaveSpeedUploadResponse {
success: boolean;
data?: {
url: string;
file_id: string;
filename: string;
size: number;
mime_type: string;
};
error?: string;
}
export interface ModelParameter {
name: string;
displayName: string;
type: 'string' | 'number' | 'boolean' | 'options' | 'collection';
required?: boolean;
default?: any;
description?: string;
options?: {
name: string;
value: any;
description?: string;
}[];
typeOptions?: any;
displayOptions?: any;
}
export interface ModelInfo {
id: string;
name: string;
description?: string;
category: string;
parameters: ModelParameter[];
model_uuid?: string;
model_id?: number;
base_price?: number;
cover_url?: string;
poster?: string;
api_schema?: any;
input_schema?: any;
tags?: string[];
categories?: any[];
api_server_domain?: string;
}
export declare class WaveSpeedClient {
private static modelDetailCache;
private static readonly CACHE_TTL;
private static globalAbortController;
private static isSignalHandlerRegistered;
static initializeSignalHandler(): AbortSignal;
static resetSignalHandler(): void;
private static cleanExpiredCache;
static getModelCategories(): Promise<INodePropertyOptions[]>;
private static formatCategoryName;
private static getDefaultCategories;
static getModels(category: string): Promise<INodePropertyOptions[]>;
static getModelParameters(modelId: string): Promise<ModelParameter[]>;
static convertParameterToNodeProperty(param: ModelParameter): INodeProperties;
static getDynamicParameters(modelId: string): Promise<INodeProperties[]>;
static buildRequestData(baseData: any, parameters: INodeProperties[], nodeParameters: any): any;
static getModelDetail(modelId: string): Promise<ModelInfo | null>;
static convertToModelInfo(apiModel: any): ModelInfo | null;
static parseInputSchemaToParameters(inputSchema: any): ModelParameter[];
static formatDisplayName(propName: string): string;
static mapJsonSchemaTypeToNodeType(prop: any): 'string' | 'number' | 'boolean' | 'options' | 'collection';
static extractApiEndpoints(apiSchema: any): {
runUrl?: string;
resultUrl?: string;
server?: string;
};
static shouldDisableParameter(prop: any): boolean;
static getModelInfo(modelId: string): Promise<ModelInfo | null>;
static getModelsWithDetails(category: string): Promise<ModelInfo[]>;
static submitTask(modelId: string, parameters: any, apiKey: string): Promise<any>;
static getTaskStatus(taskId: string, apiKey: string): Promise<any>;
private static isRetryableError;
static waitForTaskCompletion(taskId: string, apiKey: string, maxWaitTime?: number, // Default 5 minutes
pollInterval?: number, // Initial polling interval 2 seconds (faster response)
maxRetries?: number, // Default maximum retry 20 times
abortSignal?: AbortSignal): Promise<any>;
private static calculateNextPollInterval;
private static interruptibleWait;
static validateAudioFormat(context: IExecuteFunctions, mimeType: string, filename: string): void;
static validateImageFormat(context: IExecuteFunctions, mimeType: string, filename: string): void;
static validateVideoFormat(context: IExecuteFunctions, mimeType: string, filename: string): void;
static validateFileSize(context: IExecuteFunctions, fileSize: number, maxFileSize?: number): void;
static getAudioMimeTypeFromFilename(filename: string): string;
static getImageMimeTypeFromFilename(filename: string): string;
static getVideoMimeTypeFromFilename(filename: string): string;
static getMediaMimeTypeFromFilename(filename: string): string;
static getMediaTypeFromMimeType(mimeType: string): 'audio' | 'image' | 'video' | 'unknown';
static validateMediaFormat(context: IExecuteFunctions, mimeType: string, filename: string): void;
static uploadMediaToWaveSpeed(context: IExecuteFunctions, apiKey: string, fileBuffer: Buffer, filename: string, mimeType: string, options: {
filename?: string;
tags?: string;
maxDuration?: number;
maxFileSize?: number;
sampleRate?: number;
mediaType?: 'audio' | 'image' | 'video';
}): Promise<WaveSpeedUploadResponse>;
}