mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 04:31:27 +08:00
- Removed outdated API model and schema files to simplify the structure. - Consolidated API types and schemas for better organization and clarity. - Updated import paths across the codebase to reflect the new structure. - Enhanced documentation in related README files to guide usage of the new API schema organization. |
||
|---|---|---|
| .. | ||
| schemas | ||
| apiPaths.ts | ||
| apiTypes.ts | ||
| errorCodes.ts | ||
| index.ts | ||
| README.md | ||
Data API Type System
This directory contains the type definitions and utilities for Cherry Studio's Data API system, which provides type-safe IPC communication between renderer and main processes.
Directory Structure
packages/shared/data/api/
├── index.ts # Barrel export for infrastructure types
├── apiTypes.ts # Core request/response types and API utilities
├── apiPaths.ts # Path template literal type utilities
├── errorCodes.ts # Error handling utilities and factories
└── schemas/
├── index.ts # Schema composition (merges all domain schemas)
├── test.ts # Test API schema and DTOs
└── batch.ts # Batch/transaction API schema
File Responsibilities
| File | Purpose |
|---|---|
apiTypes.ts |
Core types (DataRequest, DataResponse, ApiClient) and schema utilities |
apiPaths.ts |
Template literal types for path resolution (/items/:id → /items/${string}) |
errorCodes.ts |
DataApiErrorFactory, error codes, and error handling utilities |
index.ts |
Unified export of infrastructure types (not domain DTOs) |
schemas/index.ts |
Composes all domain schemas into ApiSchemas using intersection types |
schemas/*.ts |
Domain-specific API definitions and DTOs |
Import Conventions
Infrastructure Types (via barrel export)
Use the barrel export for common API infrastructure:
import type {
DataRequest,
DataResponse,
ApiClient,
PaginatedResponse,
ErrorCode
} from '@shared/data/api'
import { DataApiErrorFactory, isDataApiError } from '@shared/data/api'
Domain DTOs (directly from schema files)
Import domain-specific types directly from their schema files:
// Topic domain
import type { Topic, CreateTopicDto, UpdateTopicDto } from '@shared/data/api/schemas/topic'
// Message domain
import type { Message, CreateMessageDto } from '@shared/data/api/schemas/message'
// Test domain (development)
import type { TestItem, CreateTestItemDto } from '@shared/data/api/schemas/test'
Adding a New Domain Schema
- Create the schema file (e.g.,
schemas/topic.ts):
import type { PaginatedResponse } from '../apiTypes'
// Domain models
export interface Topic {
id: string
name: string
createdAt: string
}
export interface CreateTopicDto {
name: string
}
// API Schema - validation happens via AssertValidSchemas in index.ts
export interface TopicSchemas {
'/topics': {
GET: {
response: PaginatedResponse<Topic> // response is required
}
POST: {
body: CreateTopicDto
response: Topic
}
}
'/topics/:id': {
GET: {
params: { id: string }
response: Topic
}
}
}
Validation: Schemas are validated at composition level via AssertValidSchemas in schemas/index.ts:
- Ensures only valid HTTP methods (GET, POST, PUT, DELETE, PATCH)
- Requires
responsefield for each endpoint - Invalid schemas cause TypeScript errors at the composition point
- Register in
schemas/index.ts:
import type { TopicSchemas } from './topic'
// AssertValidSchemas provides fallback validation even if ValidateSchema is forgotten
export type ApiSchemas = AssertValidSchemas<TestSchemas & BatchSchemas & TopicSchemas>
- Implement handlers in
src/main/data/api/handlers/
Type Safety Features
Path Resolution
The system uses template literal types to map concrete paths to schema paths:
// Concrete path '/topics/abc123' maps to schema path '/topics/:id'
api.get('/topics/abc123') // TypeScript knows this returns Topic
Exhaustive Handler Checking
ApiImplementation type ensures all schema endpoints have handlers:
// TypeScript will error if any endpoint is missing
const handlers: ApiImplementation = {
'/topics': {
GET: async () => { /* ... */ },
POST: async ({ body }) => { /* ... */ }
}
// Missing '/topics/:id' would cause compile error
}
Type-Safe Client
ApiClient provides fully typed methods:
const topic = await api.get('/topics/123') // Returns Topic
const topics = await api.get('/topics', { query: { page: 1 } }) // Returns PaginatedResponse<Topic>
await api.post('/topics', { body: { name: 'New' } }) // Body is typed as CreateTopicDto
Error Handling
Use DataApiErrorFactory for consistent error creation:
import { DataApiErrorFactory, ErrorCode } from '@shared/data/api'
// Create errors
throw DataApiErrorFactory.notFound('Topic', id)
throw DataApiErrorFactory.validationError('Name is required')
throw DataApiErrorFactory.fromCode(ErrorCode.DATABASE_ERROR, 'Connection failed')
// Check errors
if (isDataApiError(error)) {
console.log(error.code, error.status)
}
Architecture Overview
Renderer Main
────────────────────────────────────────────────────
DataApiService ──IPC──► IpcAdapter ──► ApiServer
│ │
│ ▼
ApiClient MiddlewareEngine
(typed) │
▼
Handlers
(typed)
- Renderer: Uses
DataApiServicewith type-safeApiClientinterface - IPC: Requests serialized via
IpcAdapter - Main:
ApiServerroutes to handlers throughMiddlewareEngine - Type Safety: End-to-end types from client call to handler implementation