Configuración
Guía de configuración y configuración para Qwen Image Edit
Configuración Inicial
Variables de Entorno
Configura las variables de entorno necesarias para tu aplicación:
# .env.local
QWEN_API_KEY=tu-clave-api-aqui
QWEN_REGION=us-east-1
QWEN_ENDPOINT=https://api.qwen.com/v1
QWEN_TIMEOUT=30000
QWEN_MAX_RETRIES=3
Configuración del Cliente
import { QwenImageEdit } from 'qwen-image-edit';
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
region: 'us-east-1',
timeout: 30000,
maxRetries: 3,
debug: process.env.NODE_ENV === 'development'
});
Configuración Avanzada
Configuración Completa
interface QwenImageEditConfig {
// Autenticación
apiKey: string;
region?: string;
endpoint?: string;
// Timeouts y Reintentos
timeout?: number; // Timeout en ms (por defecto: 30000)
maxRetries?: number; // Reintentos máximos (por defecto: 3)
retryDelay?: number; // Delay entre reintentos en ms (por defecto: 1000)
// Caché
cache?: boolean; // Habilitar caché (por defecto: false)
cacheConfig?: CacheConfig;
// Logging y Debug
debug?: boolean; // Modo debug (por defecto: false)
logLevel?: 'error' | 'warn' | 'info' | 'debug';
// Límites
maxImageSize?: number; // Tamaño máximo en bytes (por defecto: 25MB)
maxConcurrent?: number; // Solicitudes concurrentes (por defecto: 5)
// Webhooks
webhookSecret?: string; // Secreto para verificar webhooks
// Proxy
proxy?: ProxyConfig;
}
Configuración de Caché
interface CacheConfig {
ttl: number; // Tiempo de vida en segundos
maxSize: number; // Máximo elementos en caché
storage: 'memory' | 'disk' | 'redis';
// Para storage 'disk'
cacheDir?: string;
// Para storage 'redis'
redis?: {
host: string;
port: number;
password?: string;
db?: number;
};
}
// Ejemplo de configuración de caché
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
cache: true,
cacheConfig: {
ttl: 3600, // 1 hora
maxSize: 1000,
storage: 'redis',
redis: {
host: 'localhost',
port: 6379,
password: process.env.REDIS_PASSWORD,
db: 0
}
}
});
Configuración de Proxy
interface ProxyConfig {
host: string;
port: number;
protocol?: 'http' | 'https';
auth?: {
username: string;
password: string;
};
}
// Ejemplo de configuración de proxy
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
proxy: {
host: 'proxy.empresa.com',
port: 8080,
protocol: 'https',
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
}
});
Configuración por Entorno
Desarrollo
// config/development.ts
export const developmentConfig: QwenImageEditConfig = {
apiKey: process.env.QWEN_API_KEY!,
region: 'us-east-1',
timeout: 60000, // Timeout más largo para debug
maxRetries: 1, // Menos reintentos para fallar rápido
debug: true, // Habilitar logs debug
logLevel: 'debug',
cache: false, // Sin caché en desarrollo
maxConcurrent: 2 // Menos concurrencia
};
Producción
// config/production.ts
export const productionConfig: QwenImageEditConfig = {
apiKey: process.env.QWEN_API_KEY!,
region: process.env.QWEN_REGION || 'us-east-1',
timeout: 30000,
maxRetries: 3,
debug: false,
logLevel: 'error',
cache: true,
cacheConfig: {
ttl: 3600,
maxSize: 10000,
storage: 'redis',
redis: {
host: process.env.REDIS_HOST!,
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD
}
},
maxConcurrent: 10,
webhookSecret: process.env.WEBHOOK_SECRET
};
Testing
// config/test.ts
export const testConfig: QwenImageEditConfig = {
apiKey: 'test-api-key',
endpoint: 'http://localhost:3001/mock-api',
timeout: 5000,
maxRetries: 0, // Sin reintentos en tests
debug: false,
cache: false,
maxConcurrent: 1 // Secuencial para tests
};
Configuración de Logging
Logger Personalizado
import { Logger } from 'qwen-image-edit';
class CustomLogger implements Logger {
error(message: string, meta?: any) {
console.error(`[QWEN ERROR] ${message}`, meta);
// Enviar a servicio de logging
}
warn(message: string, meta?: any) {
console.warn(`[QWEN WARN] ${message}`, meta);
}
info(message: string, meta?: any) {
console.info(`[QWEN INFO] ${message}`, meta);
}
debug(message: string, meta?: any) {
if (process.env.NODE_ENV === 'development') {
console.debug(`[QWEN DEBUG] ${message}`, meta);
}
}
}
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logger: new CustomLogger()
});
Integración con Winston
import winston from 'winston';
import { QwenImageEdit } from 'qwen-image-edit';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'qwen-error.log', level: 'error' }),
new winston.transports.File({ filename: 'qwen-combined.log' })
]
});
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logger: {
error: (msg, meta) => logger.error(msg, meta),
warn: (msg, meta) => logger.warn(msg, meta),
info: (msg, meta) => logger.info(msg, meta),
debug: (msg, meta) => logger.debug(msg, meta)
}
});
Configuración de Seguridad
Validación de Entrada
import Joi from 'joi';
const configSchema = Joi.object({
apiKey: Joi.string().required(),
region: Joi.string().valid('us-east-1', 'us-west-2', 'eu-west-1'),
timeout: Joi.number().min(1000).max(300000),
maxRetries: Joi.number().min(0).max(10),
debug: Joi.boolean(),
maxImageSize: Joi.number().min(1024).max(52428800) // 1KB - 50MB
});
function validateConfig(config: any): QwenImageEditConfig {
const { error, value } = configSchema.validate(config);
if (error) {
throw new Error(`Configuración inválida: ${error.message}`);
}
return value;
}
Rotación de Claves API
class RotatingApiKeyProvider {
private keys: string[];
private currentIndex = 0;
constructor(keys: string[]) {
this.keys = keys;
}
getCurrentKey(): string {
return this.keys[this.currentIndex];
}
rotateKey(): void {
this.currentIndex = (this.currentIndex + 1) % this.keys.length;
}
}
const keyProvider = new RotatingApiKeyProvider([
process.env.QWEN_API_KEY_1!,
process.env.QWEN_API_KEY_2!,
process.env.QWEN_API_KEY_3!
]);
const editor = new QwenImageEdit({
apiKey: keyProvider.getCurrentKey(),
onAuthError: () => {
keyProvider.rotateKey();
// Reintentar con nueva clave
}
});
Configuración de Performance
Pool de Conexiones
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
connectionPool: {
maxConnections: 20,
keepAlive: true,
keepAliveMsecs: 30000,
timeout: 30000
}
});
Compresión de Imágenes
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
compression: {
enabled: true,
quality: 85, // Calidad JPEG (1-100)
format: 'auto', // 'auto', 'jpeg', 'png', 'webp'
maxDimension: 2048 // Redimensionar si es mayor
}
});
Configuración de Memoria
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
memory: {
maxBufferSize: 100 * 1024 * 1024, // 100MB
gcInterval: 60000, // Garbage collection cada minuto
streamThreshold: 10 * 1024 * 1024 // Stream para archivos > 10MB
}
});
Configuración de Monitoreo
Métricas
import { QwenImageEdit, MetricsCollector } from 'qwen-image-edit';
class CustomMetrics implements MetricsCollector {
onRequestStart(operacion: string) {
console.time(`qwen-${operacion}`);
}
onRequestEnd(operacion: string, exito: boolean, duracion: number) {
console.timeEnd(`qwen-${operacion}`);
// Enviar métricas a servicio de monitoreo
this.enviarMetrica({
operacion,
exito,
duracion,
timestamp: Date.now()
});
}
private enviarMetrica(metrica: any) {
// Implementar envío a DataDog, New Relic, etc.
}
}
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
metrics: new CustomMetrics()
});
Health Checks
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
healthCheck: {
enabled: true,
interval: 30000, // Cada 30 segundos
timeout: 5000,
onHealthChange: (healthy: boolean) => {
if (!healthy) {
console.error('Qwen Image Edit no está disponible');
// Alertar sistema de monitoreo
}
}
}
});
Configuración de Desarrollo
Hot Reload
// webpack.config.js
module.exports = {
// ... otras configuraciones
devServer: {
hot: true,
proxy: {
'/api/qwen': {
target: 'https://api.qwen.com',
changeOrigin: true,
pathRewrite: {
'^/api/qwen': ''
}
}
}
}
};
Mock para Testing
// __mocks__/qwen-image-edit.ts
export class QwenImageEdit {
async editText(options: any) {
return {
imagenUrl: 'http://localhost:3000/mock-image.jpg',
imagenOriginal: options.imagen,
metadatos: {
ancho: 1024,
alto: 768,
formato: 'jpeg',
tamaño: 102400
},
procesamiento: {
tiempoMs: 1000,
modelo: 'qwen-mock',
version: '1.0.0'
}
};
}
}
Mejores Prácticas
1. Separación de Configuración
// config/index.ts
const configs = {
development: () => import('./development'),
production: () => import('./production'),
test: () => import('./test')
};
export async function getConfig() {
const env = process.env.NODE_ENV || 'development';
const config = await configs[env]();
return config.default;
}
2. Validación de Configuración
function validateRequiredEnvVars() {
const required = ['QWEN_API_KEY'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Variables de entorno faltantes: ${missing.join(', ')}`);
}
}
validateRequiredEnvVars();
3. Configuración Tipada
interface AppConfig {
qwen: QwenImageEditConfig;
server: {
port: number;
host: string;
};
database: {
url: string;
};
}
const config: AppConfig = {
qwen: {
apiKey: process.env.QWEN_API_KEY!,
region: process.env.QWEN_REGION as any,
timeout: parseInt(process.env.QWEN_TIMEOUT || '30000')
},
server: {
port: parseInt(process.env.PORT || '3000'),
host: process.env.HOST || 'localhost'
},
database: {
url: process.env.DATABASE_URL!
}
};
Solución de Problemas
Problemas Comunes
-
Error de Autenticación
- Verificar que la clave API sea válida
- Comprobar que la región sea correcta
-
Timeouts
- Aumentar el valor de timeout
- Verificar conectividad de red
-
Límites de Cuota
- Verificar uso actual en el dashboard
- Considerar actualizar el plan
-
Errores de Caché
- Limpiar caché manualmente
- Verificar configuración de Redis
Debug
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
debug: true,
logLevel: 'debug',
onRequest: (config) => {
console.log('Enviando solicitud:', config);
},
onResponse: (response) => {
console.log('Respuesta recibida:', response);
},
onError: (error) => {
console.error('Error en solicitud:', error);
}
});