feat: remove unused endpoints
This commit is contained in:
parent
2a4ba8f4ed
commit
83303f8890
11
CLAUDE.md
11
CLAUDE.md
|
|
@ -213,9 +213,7 @@ Located at `apps/api-service/.env` - used ONLY when running `pnpm dev:api` local
|
||||||
|
|
||||||
### Protected Endpoints (API Key Required)
|
### Protected Endpoints (API Key Required)
|
||||||
|
|
||||||
- `POST /api/generate` - Generate images from text + optional reference images
|
|
||||||
- `POST /api/text-to-image` - Generate images from text only (JSON)
|
- `POST /api/text-to-image` - Generate images from text only (JSON)
|
||||||
- `POST /api/enhance` - Enhance and optimize text prompts
|
|
||||||
- `GET /api/images` - List generated images
|
- `GET /api/images` - List generated images
|
||||||
|
|
||||||
**Authentication**: All protected endpoints require `X-API-Key` header
|
**Authentication**: All protected endpoints require `X-API-Key` header
|
||||||
|
|
@ -245,10 +243,13 @@ Located at `apps/api-service/.env` - used ONLY when running `pnpm dev:api` local
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Image generation with project key
|
# Image generation with project key
|
||||||
curl -X POST http://localhost:3000/api/generate \
|
curl -X POST http://localhost:3000/api/text-to-image \
|
||||||
-H "X-API-Key: YOUR_PROJECT_KEY" \
|
-H "X-API-Key: YOUR_PROJECT_KEY" \
|
||||||
-F "prompt=a sunset" \
|
-H "Content-Type: application/json" \
|
||||||
-F "filename=test_image"
|
-d '{
|
||||||
|
"prompt": "a sunset",
|
||||||
|
"filename": "test_image"
|
||||||
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key Management
|
### Key Management
|
||||||
|
|
|
||||||
17
README.md
17
README.md
|
|
@ -144,15 +144,14 @@ See individual app README files for specific environment variables.
|
||||||
### Generate Image
|
### Generate Image
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Basic text-to-image
|
# Text-to-image
|
||||||
curl -X POST http://localhost:3000/api/generate \
|
curl -X POST http://localhost:3000/api/text-to-image \
|
||||||
-F "prompt=A magical forest with glowing mushrooms" \
|
-H "Content-Type: application/json" \
|
||||||
-F "filename=magical_forest"
|
-H "X-API-Key: YOUR_API_KEY" \
|
||||||
|
-d '{
|
||||||
# With reference images
|
"prompt": "A magical forest with glowing mushrooms",
|
||||||
curl -X POST http://localhost:3000/api/generate \
|
"filename": "magical_forest"
|
||||||
-F "prompt=Character in medieval armor like the reference" \
|
}'
|
||||||
-F "referenceImages=@./reference.jpg"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
See `apps/api-service/README.md` for detailed API documentation.
|
See `apps/api-service/README.md` for detailed API documentation.
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import express, { Application } from 'express';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
import { Config } from './types/api';
|
import { Config } from './types/api';
|
||||||
import { generateRouter } from './routes/generate';
|
|
||||||
import { enhanceRouter } from './routes/enhance';
|
|
||||||
import { textToImageRouter } from './routes/textToImage';
|
import { textToImageRouter } from './routes/textToImage';
|
||||||
import { imagesRouter } from './routes/images';
|
import { imagesRouter } from './routes/images';
|
||||||
import bootstrapRoutes from './routes/bootstrap';
|
import bootstrapRoutes from './routes/bootstrap';
|
||||||
|
|
@ -72,9 +70,7 @@ export const createApp = (): Application => {
|
||||||
endpoints: {
|
endpoints: {
|
||||||
'GET /health': 'Health check',
|
'GET /health': 'Health check',
|
||||||
'GET /api/info': 'API information',
|
'GET /api/info': 'API information',
|
||||||
'POST /api/generate': 'Generate images from text prompt with optional reference images',
|
|
||||||
'POST /api/text-to-image': 'Generate images from text prompt only (JSON)',
|
'POST /api/text-to-image': 'Generate images from text prompt only (JSON)',
|
||||||
'POST /api/enhance': 'Enhance and optimize prompts for better image generation',
|
|
||||||
},
|
},
|
||||||
limits: {
|
limits: {
|
||||||
maxFileSize: `${appConfig.maxFileSize / (1024 * 1024)}MB`,
|
maxFileSize: `${appConfig.maxFileSize / (1024 * 1024)}MB`,
|
||||||
|
|
@ -120,8 +116,6 @@ export const createApp = (): Application => {
|
||||||
app.use('/api/admin/keys', adminKeysRoutes);
|
app.use('/api/admin/keys', adminKeysRoutes);
|
||||||
|
|
||||||
// Protected API routes (require valid API key)
|
// Protected API routes (require valid API key)
|
||||||
app.use('/api', generateRouter);
|
|
||||||
app.use('/api', enhanceRouter);
|
|
||||||
app.use('/api', textToImageRouter);
|
app.use('/api', textToImageRouter);
|
||||||
app.use('/api', imagesRouter);
|
app.use('/api', imagesRouter);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
import { Request, Response, Router } from 'express';
|
|
||||||
import type { Router as RouterType } from 'express';
|
|
||||||
import { PromptEnhancementService } from '../services/promptEnhancement';
|
|
||||||
import { asyncHandler } from '../middleware/errorHandler';
|
|
||||||
import { PromptEnhancementRequest, PromptEnhancementResponse } from '../types/api';
|
|
||||||
import { body, validationResult } from 'express-validator';
|
|
||||||
import { validateApiKey } from '../middleware/auth/validateApiKey';
|
|
||||||
import { rateLimitByApiKey } from '../middleware/auth/rateLimiter';
|
|
||||||
|
|
||||||
export const enhanceRouter: RouterType = Router();
|
|
||||||
|
|
||||||
let promptEnhancementService: PromptEnhancementService;
|
|
||||||
|
|
||||||
const validateEnhanceRequest = [
|
|
||||||
body('prompt')
|
|
||||||
.notEmpty()
|
|
||||||
.withMessage('Prompt is required')
|
|
||||||
.isLength({ min: 1, max: 5000 })
|
|
||||||
.withMessage('Prompt must be between 1 and 5000 characters')
|
|
||||||
.trim(),
|
|
||||||
|
|
||||||
body('options.imageStyle')
|
|
||||||
.optional()
|
|
||||||
.isIn(['photorealistic', 'illustration', 'minimalist', 'sticker', 'product', 'comic'])
|
|
||||||
.withMessage('Invalid image style'),
|
|
||||||
|
|
||||||
body('options.aspectRatio')
|
|
||||||
.optional()
|
|
||||||
.isIn(['square', 'portrait', 'landscape', 'wide', 'ultrawide'])
|
|
||||||
.withMessage('Invalid aspect ratio'),
|
|
||||||
|
|
||||||
body('options.mood')
|
|
||||||
.optional()
|
|
||||||
.isLength({ max: 100 })
|
|
||||||
.withMessage('Mood description too long')
|
|
||||||
.trim(),
|
|
||||||
|
|
||||||
body('options.lighting')
|
|
||||||
.optional()
|
|
||||||
.isLength({ max: 100 })
|
|
||||||
.withMessage('Lighting description too long')
|
|
||||||
.trim(),
|
|
||||||
|
|
||||||
body('options.cameraAngle')
|
|
||||||
.optional()
|
|
||||||
.isLength({ max: 100 })
|
|
||||||
.withMessage('Camera angle description too long')
|
|
||||||
.trim(),
|
|
||||||
|
|
||||||
body('options.outputFormat')
|
|
||||||
.optional()
|
|
||||||
.isIn(['text', 'markdown', 'detailed'])
|
|
||||||
.withMessage('Invalid output format'),
|
|
||||||
|
|
||||||
body('options.negativePrompts')
|
|
||||||
.optional()
|
|
||||||
.isArray({ max: 10 })
|
|
||||||
.withMessage('Too many negative prompts (max 10)'),
|
|
||||||
|
|
||||||
body('options.negativePrompts.*')
|
|
||||||
.optional()
|
|
||||||
.isLength({ max: 100 })
|
|
||||||
.withMessage('Negative prompt too long')
|
|
||||||
.trim(),
|
|
||||||
];
|
|
||||||
|
|
||||||
const logEnhanceRequest = (req: Request, _res: Response, next: Function) => {
|
|
||||||
const timestamp = new Date().toISOString();
|
|
||||||
const requestId = req.requestId;
|
|
||||||
const { prompt, options } = req.body as PromptEnhancementRequest;
|
|
||||||
|
|
||||||
console.log(`[${timestamp}] [${requestId}] POST /api/enhance`);
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Prompt length: ${prompt?.length || 0} characters`);
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Options:`, options || 'none');
|
|
||||||
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
enhanceRouter.post(
|
|
||||||
'/enhance',
|
|
||||||
// Authentication middleware
|
|
||||||
validateApiKey,
|
|
||||||
rateLimitByApiKey,
|
|
||||||
|
|
||||||
validateEnhanceRequest,
|
|
||||||
logEnhanceRequest,
|
|
||||||
|
|
||||||
asyncHandler(async (req: Request, res: Response) => {
|
|
||||||
if (!promptEnhancementService) {
|
|
||||||
const apiKey = process.env['GEMINI_API_KEY'];
|
|
||||||
if (!apiKey) {
|
|
||||||
return res.status(500).json({
|
|
||||||
success: false,
|
|
||||||
originalPrompt: '',
|
|
||||||
error: 'Server configuration error: GEMINI_API_KEY not configured',
|
|
||||||
} as PromptEnhancementResponse);
|
|
||||||
}
|
|
||||||
promptEnhancementService = new PromptEnhancementService(apiKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = validationResult(req);
|
|
||||||
if (!errors.isEmpty()) {
|
|
||||||
console.log(
|
|
||||||
`[${new Date().toISOString()}] [${req.requestId}] Validation failed:`,
|
|
||||||
errors.array(),
|
|
||||||
);
|
|
||||||
return res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
originalPrompt: req.body.prompt || '',
|
|
||||||
error: `Validation failed: ${errors
|
|
||||||
.array()
|
|
||||||
.map((e) => e.msg)
|
|
||||||
.join(', ')}`,
|
|
||||||
} as PromptEnhancementResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timestamp = new Date().toISOString();
|
|
||||||
const requestId = req.requestId;
|
|
||||||
const { prompt, options } = req.body as PromptEnhancementRequest;
|
|
||||||
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Starting prompt enhancement`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Extract orgId and projectId from validated API key
|
|
||||||
const orgId = req.apiKey?.organizationSlug || 'unknown';
|
|
||||||
const projectId = req.apiKey?.projectSlug || 'unknown';
|
|
||||||
|
|
||||||
const result = await promptEnhancementService.enhancePrompt(prompt, options || {}, {
|
|
||||||
orgId,
|
|
||||||
projectId,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Enhancement completed:`, {
|
|
||||||
success: result.success,
|
|
||||||
detectedLanguage: result.detectedLanguage,
|
|
||||||
appliedTemplate: result.appliedTemplate,
|
|
||||||
enhancementsCount: result.metadata?.enhancements.length || 0,
|
|
||||||
hasError: !!result.error,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
const successResponse: PromptEnhancementResponse = {
|
|
||||||
success: true,
|
|
||||||
originalPrompt: result.originalPrompt,
|
|
||||||
enhancedPrompt: result.enhancedPrompt!,
|
|
||||||
...(result.detectedLanguage && {
|
|
||||||
detectedLanguage: result.detectedLanguage,
|
|
||||||
}),
|
|
||||||
...(result.appliedTemplate && {
|
|
||||||
appliedTemplate: result.appliedTemplate,
|
|
||||||
}),
|
|
||||||
...(result.metadata && { metadata: result.metadata }),
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Sending success response`);
|
|
||||||
return res.status(200).json(successResponse);
|
|
||||||
} else {
|
|
||||||
const errorResponse: PromptEnhancementResponse = {
|
|
||||||
success: false,
|
|
||||||
originalPrompt: result.originalPrompt,
|
|
||||||
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 enhance endpoint:`, error);
|
|
||||||
|
|
||||||
const errorResponse: PromptEnhancementResponse = {
|
|
||||||
success: false,
|
|
||||||
originalPrompt: prompt,
|
|
||||||
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
||||||
};
|
|
||||||
|
|
||||||
return res.status(500).json(errorResponse);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
import { Response, Router } from 'express';
|
|
||||||
import type { Router as RouterType } from 'express';
|
|
||||||
import { ImageGenService } from '../services/ImageGenService';
|
|
||||||
import { uploadReferenceImages, handleUploadErrors } from '../middleware/upload';
|
|
||||||
import { validateGenerateRequest, logRequestDetails } from '../middleware/validation';
|
|
||||||
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';
|
|
||||||
// Create router
|
|
||||||
export const generateRouter: RouterType = Router();
|
|
||||||
|
|
||||||
// Initialize ImageGenService (will be created in the route handler to avoid circular dependency)
|
|
||||||
let imageGenService: ImageGenService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /api/generate - Generate image from text prompt with optional reference images
|
|
||||||
*/
|
|
||||||
generateRouter.post(
|
|
||||||
'/generate',
|
|
||||||
// Authentication middleware
|
|
||||||
validateApiKey,
|
|
||||||
requireProjectKey,
|
|
||||||
rateLimitByApiKey,
|
|
||||||
|
|
||||||
// File upload middleware
|
|
||||||
uploadReferenceImages,
|
|
||||||
handleUploadErrors,
|
|
||||||
|
|
||||||
// Validation middleware
|
|
||||||
logRequestDetails,
|
|
||||||
validateGenerateRequest,
|
|
||||||
|
|
||||||
// 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, filename, aspectRatio, meta } = req.body;
|
|
||||||
const files = (req.files as Express.Multer.File[]) || [];
|
|
||||||
|
|
||||||
// Extract org/project slugs from validated API key
|
|
||||||
const orgId = req.apiKey?.organizationSlug || undefined;
|
|
||||||
const projectId = req.apiKey?.projectSlug!; // Guaranteed by requireProjectKey middleware
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`[${timestamp}] [${requestId}] Starting image generation process for org:${orgId}, project:${projectId}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Validate reference images if provided
|
|
||||||
if (files.length > 0) {
|
|
||||||
const validation = ImageGenService.validateReferenceImages(files);
|
|
||||||
if (!validation.valid) {
|
|
||||||
console.log(
|
|
||||||
`[${timestamp}] [${requestId}] Reference image validation failed: ${validation.error}`,
|
|
||||||
);
|
|
||||||
return res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
message: 'Reference image validation failed',
|
|
||||||
error: validation.error,
|
|
||||||
} as GenerateImageResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Reference images validation passed`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert files to reference images
|
|
||||||
const referenceImages =
|
|
||||||
files.length > 0 ? ImageGenService.convertFilesToReferenceImages(files) : undefined;
|
|
||||||
|
|
||||||
// Generate the image
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Calling ImageGenService.generateImage()`);
|
|
||||||
|
|
||||||
const result = await imageGenService.generateImage({
|
|
||||||
prompt,
|
|
||||||
filename,
|
|
||||||
...(aspectRatio && { aspectRatio }),
|
|
||||||
orgId,
|
|
||||||
projectId,
|
|
||||||
...(referenceImages && { referenceImages }),
|
|
||||||
...(meta && { meta }),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Log the result
|
|
||||||
console.log(`[${timestamp}] [${requestId}] Image generation completed:`, {
|
|
||||||
success: result.success,
|
|
||||||
model: result.model,
|
|
||||||
filename: result.filename,
|
|
||||||
hasError: !!result.error,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send response
|
|
||||||
if (result.success) {
|
|
||||||
const successResponse: GenerateImageResponse = {
|
|
||||||
success: true,
|
|
||||||
message: 'Image generated successfully',
|
|
||||||
data: {
|
|
||||||
filename: result.filename!,
|
|
||||||
filepath: result.filepath!,
|
|
||||||
...(result.description && { description: result.description }),
|
|
||||||
model: result.model,
|
|
||||||
generatedAt: timestamp,
|
|
||||||
...(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 generate 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);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
@ -46,26 +46,6 @@ DELETE {{base}}/api/admin/keys/KEY_ID_HERE
|
||||||
X-API-Key: {{masterKey}}
|
X-API-Key: {{masterKey}}
|
||||||
|
|
||||||
|
|
||||||
### Enhance Prompt (Requires API Key)
|
|
||||||
|
|
||||||
POST {{base}}/api/enhance
|
|
||||||
Content-Type: application/json
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"prompt": "Два мага сражаются в снежном лесу. У одного из них в руках посох, из которого вырывается молния, а другой маг защищается щитом из льда. Вокруг них падают снежинки, и на заднем плане видны заснеженные деревья и горы.",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "photorealistic",
|
|
||||||
"aspectRatio": "landscape",
|
|
||||||
"mood": "serene and peaceful",
|
|
||||||
"lighting": "golden hour",
|
|
||||||
"cameraAngle": "wide shot",
|
|
||||||
"outputFormat": "detailed",
|
|
||||||
"negativePrompts": ["blurry", "low quality"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
### Generate Image from Text (Requires API Key)
|
### Generate Image from Text (Requires API Key)
|
||||||
|
|
||||||
POST {{base}}/api/text-to-image
|
POST {{base}}/api/text-to-image
|
||||||
|
|
@ -78,37 +58,7 @@ X-API-Key: {{apiKey}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
### Generate Image with Files (Requires API Key)
|
### Generate Image - Text to Image (alternative format)
|
||||||
|
|
||||||
POST {{base}}/api/generate
|
|
||||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
|
|
||||||
X-API-Key: {{apiKey}}
|
|
||||||
|
|
||||||
------WebKitFormBoundary
|
|
||||||
Content-Disposition: form-data; name="prompt"
|
|
||||||
|
|
||||||
A majestic dragon soaring through a crystal cave filled with glowing blue crystals, sunbeams piercing through cracks in the ceiling creating dramatic lighting, highly detailed fantasy art style
|
|
||||||
------WebKitFormBoundary
|
|
||||||
Content-Disposition: form-data; name="filename"
|
|
||||||
|
|
||||||
dragon-crystal-cave
|
|
||||||
------WebKitFormBoundary
|
|
||||||
Content-Disposition: form-data; name="autoEnhance"
|
|
||||||
|
|
||||||
true
|
|
||||||
------WebKitFormBoundary
|
|
||||||
Content-Disposition: form-data; name="enhancementOptions"
|
|
||||||
|
|
||||||
{"imageStyle":"illustration","aspectRatio":"landscape","mood":"mystical and dramatic","lighting":"magical glow with sunbeams","cameraAngle":"wide shot","negativePrompts":["blurry","low quality","amateur"]}
|
|
||||||
------WebKitFormBoundary
|
|
||||||
Content-Disposition: form-data; name="referenceImages"; filename="reference.jpg"
|
|
||||||
Content-Type: image/jpeg
|
|
||||||
|
|
||||||
< ./reference.jpg
|
|
||||||
------WebKitFormBoundary--
|
|
||||||
|
|
||||||
|
|
||||||
### Generate Image - Text to Image
|
|
||||||
POST http://localhost:3000/api/text-to-image
|
POST http://localhost:3000/api/text-to-image
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
X-API-Key: bnt_61ba018f01474491cbaacec4509220d7154fffcd011f005eece4dba7889fba99
|
X-API-Key: bnt_61ba018f01474491cbaacec4509220d7154fffcd011f005eece4dba7889fba99
|
||||||
|
|
|
||||||
16
test-api.sh
16
test-api.sh
|
|
@ -16,17 +16,11 @@ echo "2. Testing API info endpoint..."
|
||||||
curl -s "$BASE_URL/api/info" | jq '.' || echo "API info endpoint failed"
|
curl -s "$BASE_URL/api/info" | jq '.' || echo "API info endpoint failed"
|
||||||
echo -e "\n"
|
echo -e "\n"
|
||||||
|
|
||||||
# Test 3: Generate endpoint validation (should fail without prompt)
|
# Test 3: Text-to-image endpoint validation (should fail without API key)
|
||||||
echo "3. Testing generate endpoint validation..."
|
echo "3. Testing text-to-image endpoint (should fail without valid API key)..."
|
||||||
curl -s -X POST "$BASE_URL/api/generate" \
|
curl -s -X POST "$BASE_URL/api/text-to-image" \
|
||||||
-F "filename=test" | jq '.' || echo "Generate endpoint validation test failed"
|
-H "Content-Type: application/json" \
|
||||||
echo -e "\n"
|
-d '{"prompt": "A simple test image", "filename": "test"}' | jq '.' || echo "Text-to-image endpoint test failed"
|
||||||
|
|
||||||
# Test 4: Generate endpoint validation (should fail without API key)
|
|
||||||
echo "4. Testing generate endpoint with prompt (should fail without valid API key)..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/generate" \
|
|
||||||
-F "prompt=A simple test image" \
|
|
||||||
-F "filename=test" | jq '.' || echo "Generate endpoint test failed"
|
|
||||||
echo -e "\n"
|
echo -e "\n"
|
||||||
|
|
||||||
echo "✅ API tests completed!"
|
echo "✅ API tests completed!"
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Test script for Banatie Prompt Enhancement API endpoints
|
|
||||||
BASE_URL="http://localhost:3000"
|
|
||||||
|
|
||||||
echo "🧪 Testing Banatie Prompt Enhancement API"
|
|
||||||
echo "========================================="
|
|
||||||
|
|
||||||
# Test 1: Health check first
|
|
||||||
echo "1. Testing health endpoint..."
|
|
||||||
curl -s "$BASE_URL/health" | jq '.status' || echo "Health endpoint failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 2: API info (should now include enhance endpoint)
|
|
||||||
echo "2. Testing API info endpoint..."
|
|
||||||
curl -s "$BASE_URL/api/info" | jq '.endpoints' || echo "API info endpoint failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 3: Basic prompt enhancement
|
|
||||||
echo "3. Testing basic prompt enhancement..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "cat"
|
|
||||||
}' | jq '.' || echo "Basic enhancement test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 4: Prompt enhancement with options
|
|
||||||
echo "4. Testing prompt enhancement with options..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "beautiful sunset",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "photorealistic",
|
|
||||||
"aspectRatio": "landscape",
|
|
||||||
"mood": "serene",
|
|
||||||
"lighting": "golden hour"
|
|
||||||
}
|
|
||||||
}' | jq '.' || echo "Enhancement with options test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 5: Multilingual prompt enhancement (Spanish)
|
|
||||||
echo "5. Testing Spanish prompt enhancement..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "un gato hermoso con ojos azules",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "illustration"
|
|
||||||
}
|
|
||||||
}' | jq '.' || echo "Spanish enhancement test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 6: Multilingual prompt enhancement (Chinese)
|
|
||||||
echo "6. Testing Chinese prompt enhancement..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "美丽的山景",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "minimalist"
|
|
||||||
}
|
|
||||||
}' | jq '.' || echo "Chinese enhancement test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 7: Sticker style prompt
|
|
||||||
echo "7. Testing sticker style enhancement..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "happy panda",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "sticker",
|
|
||||||
"negativePrompts": ["dark", "scary"]
|
|
||||||
}
|
|
||||||
}' | jq '.' || echo "Sticker style test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 8: Validation error test (empty prompt)
|
|
||||||
echo "8. Testing validation error (empty prompt)..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": ""
|
|
||||||
}' | jq '.' || echo "Validation error test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 9: Validation error test (invalid image style)
|
|
||||||
echo "9. Testing validation error (invalid style)..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/enhance" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"prompt": "test",
|
|
||||||
"options": {
|
|
||||||
"imageStyle": "invalid_style"
|
|
||||||
}
|
|
||||||
}' | jq '.' || echo "Invalid style test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 10: Auto-enhancement in generate endpoint
|
|
||||||
echo "10. Testing auto-enhancement in generate endpoint..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/generate" \
|
|
||||||
-F "prompt=gato bonito" \
|
|
||||||
-F "filename=test_autoenhance" \
|
|
||||||
-F "autoEnhance=true" \
|
|
||||||
-F "enhancementOptions[imageStyle]=photorealistic" | jq '.' || echo "Auto-enhancement test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
# Test 11: Generate without auto-enhancement (normal behavior)
|
|
||||||
echo "11. Testing generate without auto-enhancement..."
|
|
||||||
curl -s -X POST "$BASE_URL/api/generate" \
|
|
||||||
-F "prompt=a simple cat" \
|
|
||||||
-F "filename=test_normal" | jq '.' || echo "Normal generate test failed"
|
|
||||||
echo -e "\n"
|
|
||||||
|
|
||||||
echo "✅ Enhancement API tests completed!"
|
|
||||||
echo ""
|
|
||||||
echo "📋 Test Summary:"
|
|
||||||
echo "- Basic enhancement functionality"
|
|
||||||
echo "- Enhancement with styling options"
|
|
||||||
echo "- Multilingual support (Spanish, Chinese)"
|
|
||||||
echo "- Different image styles (photorealistic, illustration, minimalist, sticker)"
|
|
||||||
echo "- Validation error handling"
|
|
||||||
echo "- Auto-enhancement integration with generate endpoint"
|
|
||||||
echo ""
|
|
||||||
echo "💡 To run with API key, ensure GEMINI_API_KEY is set in your environment"
|
|
||||||
Loading…
Reference in New Issue