cherry-studio/src/main/data/api/handlers/index.ts
icarus 281632f859 feat(ocr): add validation for OCR provider operations
- Add params validation in API handlers to ensure path ID matches body ID
- Introduce isDbOcrProvider type guard for runtime validation
- Validate provider data before database operations
2025-10-20 08:28:15 +08:00

244 lines
5.9 KiB
TypeScript

/**
* Complete API handler implementation
*
* This file implements ALL endpoints defined in ApiSchemas.
* TypeScript will error if any endpoint is missing.
*/
import { ocrService } from '@main/services/ocr/OcrService'
import type { ApiImplementation } from '@shared/data/api/apiSchemas'
import { TestService } from '../services/TestService'
// Service instances
const testService = TestService.getInstance()
// Defining all handlers here feels a bit bloated; perhaps we should modularize things?
/**
* Complete API handlers implementation
* Must implement every path+method combination from ApiSchemas
*/
export const apiHandlers: ApiImplementation = {
'/test/items': {
GET: async ({ query }) => {
return await testService.getItems({
page: (query as any)?.page,
limit: (query as any)?.limit,
search: (query as any)?.search,
type: (query as any)?.type,
status: (query as any)?.status
})
},
POST: async ({ body }) => {
return await testService.createItem({
title: body.title,
description: body.description,
type: body.type,
status: body.status,
priority: body.priority,
tags: body.tags,
metadata: body.metadata
})
}
},
'/test/items/:id': {
GET: async ({ params }) => {
const item = await testService.getItemById(params.id)
if (!item) {
throw new Error(`Test item not found: ${params.id}`)
}
return item
},
PUT: async ({ params, body }) => {
const item = await testService.updateItem(params.id, {
title: body.title,
description: body.description,
type: body.type,
status: body.status,
priority: body.priority,
tags: body.tags,
metadata: body.metadata
})
if (!item) {
throw new Error(`Test item not found: ${params.id}`)
}
return item
},
DELETE: async ({ params }) => {
const deleted = await testService.deleteItem(params.id)
if (!deleted) {
throw new Error(`Test item not found: ${params.id}`)
}
return undefined
}
},
'/test/search': {
GET: async ({ query }) => {
return await testService.searchItems(query.query, {
page: query.page,
limit: query.limit,
filters: {
type: query.type,
status: query.status
}
})
}
},
'/test/stats': {
GET: async () => {
return await testService.getStats()
}
},
'/test/bulk': {
POST: async ({ body }) => {
return await testService.bulkOperation(body.operation, body.data)
}
},
'/test/error': {
POST: async ({ body }) => {
return await testService.simulateError(body.errorType)
}
},
'/test/slow': {
POST: async ({ body }) => {
const delay = body.delay
await new Promise((resolve) => setTimeout(resolve, delay))
return {
message: `Slow response completed after ${delay}ms`,
delay,
timestamp: new Date().toISOString()
}
}
},
'/test/reset': {
POST: async () => {
await testService.resetData()
return {
message: 'Test data reset successfully',
timestamp: new Date().toISOString()
}
}
},
'/test/config': {
GET: async () => {
return {
environment: 'test',
version: '1.0.0',
debug: true,
features: {
bulkOperations: true,
search: true,
statistics: true
}
}
},
PUT: async ({ body }) => {
return {
...body,
updated: true,
timestamp: new Date().toISOString()
}
}
},
'/test/status': {
GET: async () => {
return {
status: 'healthy',
timestamp: new Date().toISOString(),
version: '1.0.0',
uptime: Math.floor(process.uptime()),
environment: 'test'
}
}
},
'/test/performance': {
GET: async () => {
const memUsage = process.memoryUsage()
return {
requestsPerSecond: Math.floor(Math.random() * 100) + 50,
averageLatency: Math.floor(Math.random() * 200) + 50,
memoryUsage: memUsage.heapUsed / 1024 / 1024, // MB
cpuUsage: Math.random() * 100,
uptime: Math.floor(process.uptime())
}
}
},
'/batch': {
POST: async ({ body }) => {
// Mock batch implementation - can be enhanced with actual batch processing
const { requests } = body
const results = requests.map(() => ({
status: 200,
data: { processed: true, timestamp: new Date().toISOString() }
}))
return {
results,
metadata: {
duration: Math.floor(Math.random() * 500) + 100,
successCount: requests.length,
errorCount: 0
}
}
}
},
'/transaction': {
POST: async ({ body }) => {
// Mock transaction implementation - can be enhanced with actual transaction support
const { operations } = body
return operations.map(() => ({
status: 200,
data: { executed: true, timestamp: new Date().toISOString() }
}))
}
},
'/ocr/providers': {
GET: async ({ query }) => {
return ocrService.listProviders(query.registered)
},
POST: async ({ body }) => {
return ocrService.createProvider(body)
}
},
'/ocr/providers/:id': {
GET: async ({ params }) => {
return ocrService.getProvider(params.id)
},
PATCH: async ({ params, body }) => {
if (params.id !== body.id) {
throw new Error('Provider ID in path does not match ID in body')
}
return ocrService.patchProvider(body)
},
PUT: async ({ params, body }) => {
if (params.id !== body.id) {
throw new Error('Provider ID in path does not match ID in body')
}
return ocrService.putProvider(body)
},
DELETE: async ({ params }) => {
return ocrService.deleteProvider(params.id)
}
}
}