banatie-service/apps/api-service/src/routes/textToImage.ts

141 lines
4.8 KiB
TypeScript

import { Response, Router } from 'express';
import type { Router as RouterType } from 'express';
import { randomUUID } from 'crypto';
import { ImageGenService } from '../services/ImageGenService';
import { validateTextToImageRequest, logTextToImageRequest } from '../middleware/jsonValidation';
import { autoEnhancePrompt, logEnhancementResult } from '../middleware/promptEnhancement';
import { asyncHandler } from '../middleware/errorHandler';
import { validateApiKey } from '../middleware/auth/validateApiKey';
import { requireProjectKey } from '../middleware/auth/requireProjectKey';
import { rateLimitByApiKey } from '../middleware/auth/rateLimiter';
import { GenerateImageResponse } from '../types/api';
export const textToImageRouter: RouterType = Router();
let imageGenService: ImageGenService;
/**
* POST /api/text-to-image - Generate image from text prompt only (JSON)
*/
textToImageRouter.post(
'/text-to-image',
// Authentication middleware
validateApiKey,
requireProjectKey,
rateLimitByApiKey,
// JSON validation middleware
logTextToImageRequest,
validateTextToImageRequest,
// Auto-enhancement middleware (optional)
autoEnhancePrompt,
logEnhancementResult,
// Main handler
asyncHandler(async (req: any, res: Response) => {
// Initialize service if not already done
if (!imageGenService) {
const apiKey = process.env['GEMINI_API_KEY'];
if (!apiKey) {
return res.status(500).json({
success: false,
message: 'Server configuration error',
error: 'GEMINI_API_KEY not configured',
} as GenerateImageResponse);
}
imageGenService = new ImageGenService(apiKey);
}
const timestamp = new Date().toISOString();
const requestId = req.requestId;
const { prompt, aspectRatio, meta } = req.body;
// Extract org/project slugs from validated API key
const orgSlug = req.apiKey?.organizationSlug || undefined;
const projectSlug = req.apiKey?.projectSlug!; // Guaranteed by requireProjectKey middleware
// Generate imageId (UUID) - this will be the filename in storage
const imageId = randomUUID();
console.log(
`[${timestamp}] [${requestId}] Starting text-to-image generation process for org:${orgSlug}, project:${projectSlug}`,
);
try {
// Generate the image (no reference images for this endpoint)
console.log(
`[${timestamp}] [${requestId}] Calling ImageGenService.generateImage() (text-only)`,
);
const result = await imageGenService.generateImage({
prompt,
imageId,
...(aspectRatio && { aspectRatio }),
orgSlug,
projectSlug,
...(meta && { meta }),
});
// Log the result
console.log(`[${timestamp}] [${requestId}] Text-to-image generation completed:`, {
success: result.success,
model: result.model,
imageId: result.imageId,
hasError: !!result.error,
});
// Send response
if (result.success) {
const successResponse: GenerateImageResponse = {
success: true,
message: 'Image generated successfully',
data: {
filename: result.imageId!,
filepath: result.filepath!,
...(result.url && { url: result.url }),
...(result.description && { description: result.description }),
model: result.model,
generatedAt: timestamp,
...(result.geminiParams && { geminiParams: result.geminiParams }),
...(req.enhancedPrompt && {
promptEnhancement: {
originalPrompt: req.originalPrompt,
enhancedPrompt: req.enhancedPrompt,
detectedLanguage: req.enhancementMetadata?.detectedLanguage,
appliedTemplate: req.enhancementMetadata?.appliedTemplate,
enhancements: req.enhancementMetadata?.enhancements || [],
},
}),
},
};
console.log(`[${timestamp}] [${requestId}] Sending success response`);
return res.status(200).json(successResponse);
} else {
const errorResponse: GenerateImageResponse = {
success: false,
message: 'Image generation failed',
error: result.error || 'Unknown error occurred',
};
console.log(`[${timestamp}] [${requestId}] Sending error response: ${result.error}`);
return res.status(500).json(errorResponse);
}
} catch (error) {
console.error(
`[${timestamp}] [${requestId}] Unhandled error in text-to-image endpoint:`,
error,
);
const errorResponse: GenerateImageResponse = {
success: false,
message: 'Image generation failed',
error: error instanceof Error ? error.message : 'Unknown error occurred',
};
return res.status(500).json(errorResponse);
}
}),
);