@qlover/create-app 0.7.13 → 0.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/README.en.md +131 -0
- package/dist/templates/next-app/README.md +115 -20
- package/dist/templates/next-app/config/IOCIdentifier.ts +14 -1
- package/dist/templates/next-app/config/Identifier/index.ts +1 -0
- package/dist/templates/next-app/config/Identifier/page.admin.ts +48 -0
- package/dist/templates/next-app/config/i18n/admin18n.ts +33 -0
- package/dist/templates/next-app/config/i18n/index.ts +3 -1
- package/dist/templates/next-app/docs/en/api.md +387 -0
- package/dist/templates/next-app/docs/en/component.md +544 -0
- package/dist/templates/next-app/docs/en/database.md +496 -0
- package/dist/templates/next-app/docs/en/development-guide.md +727 -0
- package/dist/templates/next-app/docs/en/env.md +563 -0
- package/dist/templates/next-app/docs/en/i18n.md +287 -0
- package/dist/templates/next-app/docs/en/index.md +166 -0
- package/dist/templates/next-app/docs/en/page.md +457 -0
- package/dist/templates/next-app/docs/en/project-structure.md +177 -0
- package/dist/templates/next-app/docs/en/router.md +427 -0
- package/dist/templates/next-app/docs/en/theme.md +532 -0
- package/dist/templates/next-app/docs/en/validator.md +478 -0
- package/dist/templates/next-app/docs/zh/api.md +387 -0
- package/dist/templates/next-app/docs/zh/component.md +544 -0
- package/dist/templates/next-app/docs/zh/database.md +496 -0
- package/dist/templates/next-app/docs/zh/development-guide.md +727 -0
- package/dist/templates/next-app/docs/zh/env.md +563 -0
- package/dist/templates/next-app/docs/zh/i18n.md +287 -0
- package/dist/templates/next-app/docs/zh/index.md +166 -0
- package/dist/templates/next-app/docs/zh/page.md +457 -0
- package/dist/templates/next-app/docs/zh/project-structure.md +177 -0
- package/dist/templates/next-app/docs/zh/router.md +427 -0
- package/dist/templates/next-app/docs/zh/theme.md +532 -0
- package/dist/templates/next-app/docs/zh/validator.md +476 -0
- package/dist/templates/next-app/migrations/schema/UserSchema.ts +2 -2
- package/dist/templates/next-app/next.config.ts +1 -1
- package/dist/templates/next-app/package.json +3 -1
- package/dist/templates/next-app/public/locales/en.json +8 -1
- package/dist/templates/next-app/public/locales/zh.json +8 -1
- package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +14 -16
- package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +10 -3
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/login/page.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/page.tsx +2 -3
- package/dist/templates/next-app/src/app/[locale]/register/page.tsx +1 -1
- package/dist/templates/next-app/src/app/api/ai/completions/route.ts +32 -0
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +3 -0
- package/dist/templates/next-app/src/base/cases/ChatAction.ts +21 -0
- package/dist/templates/next-app/src/base/cases/FocusBarAction.ts +36 -0
- package/dist/templates/next-app/src/base/port/AdminPageInterface.ts +1 -3
- package/dist/templates/next-app/src/base/services/AdminUserService.ts +1 -1
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +1 -1
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +23 -1
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +2 -2
- package/dist/templates/next-app/src/base/types/PageProps.ts +1 -1
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +1 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +1 -0
- package/dist/templates/next-app/src/core/globals.ts +2 -0
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +4 -1
- package/dist/templates/next-app/src/{base/cases → server}/PageParams.ts +1 -1
- package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +31 -0
- package/dist/templates/next-app/src/server/port/DBTableInterface.ts +1 -1
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +6 -4
- package/dist/templates/next-app/src/server/services/AIService.ts +43 -0
- package/dist/templates/next-app/src/server/services/ApiUserService.ts +1 -1
- package/dist/templates/next-app/src/server/{SupabaseBridge.ts → sqlBridges/SupabaseBridge.ts} +16 -11
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +4 -4
- package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +1 -1
- package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +32 -25
- package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +12 -26
- package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +37 -5
- package/dist/templates/next-app/src/uikit/components/ChatRoot.tsx +17 -0
- package/dist/templates/next-app/src/uikit/components/ClientSeo.tsx +36 -0
- package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +5 -6
- package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +2 -0
- package/dist/templates/next-app/src/uikit/components/With.tsx +17 -0
- package/dist/templates/next-app/src/uikit/components/chat/ChatActionInterface.ts +30 -0
- package/dist/templates/next-app/src/uikit/components/chat/ChatFocusBar.tsx +65 -0
- package/dist/templates/next-app/src/uikit/components/chat/ChatMessages.tsx +59 -0
- package/dist/templates/next-app/src/uikit/components/chat/ChatWrap.tsx +28 -0
- package/dist/templates/next-app/src/uikit/components/chat/FocusBarActionInterface.ts +19 -0
- package/package.json +1 -1
- package/dist/templates/next-app/docs/env.md +0 -94
- package/dist/templates/next-app/src/base/port/DBBridgeInterface.ts +0 -21
- package/dist/templates/next-app/src/base/port/DBMigrationInterface.ts +0 -92
- package/dist/templates/next-app/src/base/port/MigrationApiInterface.ts +0 -3
- package/dist/templates/next-app/src/base/port/ServerApiResponseInterface.ts +0 -6
- package/dist/templates/next-app/src/base/services/migrations/MigrationsApi.ts +0 -43
- package/dist/templates/next-app/config/i18n/{HomeI18n .ts → HomeI18n.ts} +0 -0
- package/dist/templates/next-app/{build → make}/generateLocales.ts +2 -2
- /package/dist/templates/next-app/src/{base → server}/port/PaginationInterface.ts +0 -0
- /package/dist/templates/next-app/src/{base → server}/port/ParamsHandlerInterface.ts +0 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# API Development Guide
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [API Architecture Overview](#api-architecture-overview)
|
|
6
|
+
2. [Client-Side API Implementation](#client-side-api-implementation)
|
|
7
|
+
3. [Server-Side API Implementation](#server-side-api-implementation)
|
|
8
|
+
4. [Error Handling and Validation](#error-handling-and-validation)
|
|
9
|
+
5. [Best Practices and Examples](#best-practices-and-examples)
|
|
10
|
+
|
|
11
|
+
## API Architecture Overview
|
|
12
|
+
|
|
13
|
+
### 1. Overall Architecture
|
|
14
|
+
|
|
15
|
+
The project adopts a layered API architecture design:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Client Layer Server Layer
|
|
19
|
+
┌──────────────┐ ┌──────────────┐
|
|
20
|
+
│ API Interface│ │ API Routes │
|
|
21
|
+
├──────────────┤ ├──────────────┤
|
|
22
|
+
│ API Services │ HTTP │ Service │
|
|
23
|
+
├──────────────┤ Requests ├──────────────┤
|
|
24
|
+
│API Requester │ ◄──────► │ Validation │
|
|
25
|
+
├──────────────┤ ├──────────────┤
|
|
26
|
+
│Plugin System │ │ Data Layer │
|
|
27
|
+
└──────────────┘ └──────────────┘
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Core Components
|
|
31
|
+
|
|
32
|
+
- **Interface Definitions**: `AppApiInterface`, `AppUserApiInterface`, etc.
|
|
33
|
+
- **Request Clients**: `AppApiRequester`, `AdminApiRequester`
|
|
34
|
+
- **Service Implementations**: `AppUserApi`, `AdminUserApi`, etc.
|
|
35
|
+
- **Plugin System**: `AppApiPlugin`, `RequestEncryptPlugin`, etc.
|
|
36
|
+
|
|
37
|
+
### 3. Unified Response Format
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Success response
|
|
41
|
+
interface AppApiSuccessInterface<T = unknown> {
|
|
42
|
+
success: true;
|
|
43
|
+
data?: T;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Error response
|
|
47
|
+
interface AppApiErrorInterface {
|
|
48
|
+
success: false;
|
|
49
|
+
id: string;
|
|
50
|
+
message?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Unified response type
|
|
54
|
+
type AppApiResult<T = unknown> =
|
|
55
|
+
| AppApiSuccessInterface<T>
|
|
56
|
+
| AppApiErrorInterface;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Client-Side API Implementation
|
|
60
|
+
|
|
61
|
+
### 1. API Requester
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
@injectable()
|
|
65
|
+
export class AppApiRequester extends RequestTransaction<AppApiConfig> {
|
|
66
|
+
constructor(
|
|
67
|
+
@inject(FetchAbortPlugin) protected abortPlugin: FetchAbortPlugin
|
|
68
|
+
) {
|
|
69
|
+
super(
|
|
70
|
+
new RequestAdapterFetch({
|
|
71
|
+
baseURL: '/api',
|
|
72
|
+
responseType: 'json'
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 2. API Service Implementation
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
@injectable()
|
|
83
|
+
export class AppUserApi implements AppUserApiInterface {
|
|
84
|
+
constructor(
|
|
85
|
+
@inject(AppApiRequester)
|
|
86
|
+
protected client: RequestTransaction<AppApiConfig>
|
|
87
|
+
) {}
|
|
88
|
+
|
|
89
|
+
async login(params: UserApiLoginTransaction['data']): Promise<AppApiResult> {
|
|
90
|
+
const response = await this.client.request<UserApiLoginTransaction>({
|
|
91
|
+
url: '/user/login',
|
|
92
|
+
method: 'POST',
|
|
93
|
+
data: params,
|
|
94
|
+
encryptProps: 'password' // Automatically encrypt password field
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return response.data;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 3. API Plugin System
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
|
|
106
|
+
onBefore({ parameters: { ioc } }: BootstrapContext): void {
|
|
107
|
+
const appUserApi = ioc.get<AppApiRequester>(AppApiRequester);
|
|
108
|
+
|
|
109
|
+
// Register plugins
|
|
110
|
+
appUserApi.usePlugin(new FetchURLPlugin());
|
|
111
|
+
appUserApi.usePlugin(new RequestEncryptPlugin(ioc.get(StringEncryptor)));
|
|
112
|
+
appUserApi.usePlugin(
|
|
113
|
+
new RequestCommonPlugin({
|
|
114
|
+
requestDataSerializer: this.requestDataSerializer.bind(this)
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
appUserApi.usePlugin(new AppApiPlugin(ioc.get(I.Logger)));
|
|
118
|
+
appUserApi.usePlugin(ioc.get(DialogErrorPlugin));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Server-Side API Implementation
|
|
124
|
+
|
|
125
|
+
### 1. API Route Handling
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// app/api/admin/users/route.ts
|
|
129
|
+
export async function GET(req: NextRequest) {
|
|
130
|
+
const server = new BootstrapServer();
|
|
131
|
+
|
|
132
|
+
const result = await server
|
|
133
|
+
.use(new AdminAuthPlugin()) // Use authentication plugin
|
|
134
|
+
.execNoError(async ({ parameters: { IOC } }) => {
|
|
135
|
+
// 1. Parameter validation
|
|
136
|
+
const searchParams = Object.fromEntries(
|
|
137
|
+
req.nextUrl.searchParams.entries()
|
|
138
|
+
);
|
|
139
|
+
const paginationParams = IOC(PaginationValidator).getThrow(searchParams);
|
|
140
|
+
|
|
141
|
+
// 2. Call service
|
|
142
|
+
const apiUserService = IOC(ApiUserService);
|
|
143
|
+
const result = await apiUserService.getUsers({
|
|
144
|
+
page: paginationParams.page,
|
|
145
|
+
pageSize: paginationParams.pageSize
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return result;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// 3. Error handling
|
|
152
|
+
if (result instanceof ExecutorError) {
|
|
153
|
+
return NextResponse.json(new AppErrorApi(result.id, result.message), {
|
|
154
|
+
status: 400
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 4. Success response
|
|
159
|
+
return NextResponse.json(new AppSuccessApi(result));
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 2. Service Layer Implementation
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
@injectable()
|
|
167
|
+
export class ApiUserService {
|
|
168
|
+
constructor(
|
|
169
|
+
@inject(IOCIdentifier.UserRepository)
|
|
170
|
+
private userRepository: UserRepositoryInterface
|
|
171
|
+
) {}
|
|
172
|
+
|
|
173
|
+
async getUsers(params: PaginationInterface): Promise<PaginationResult<User>> {
|
|
174
|
+
return this.userRepository.findUsers(params);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 3. Authentication and Middleware
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
export class AdminAuthPlugin implements BootstrapExecutorPlugin {
|
|
183
|
+
async onBefore(context: BootstrapContext): Promise<void> {
|
|
184
|
+
const { IOC } = context.parameters;
|
|
185
|
+
const serverAuth = IOC(ServerAuth);
|
|
186
|
+
|
|
187
|
+
// Verify admin permissions
|
|
188
|
+
await serverAuth.verifyAdmin();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Error Handling and Validation
|
|
194
|
+
|
|
195
|
+
### 1. Error Response
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
export class AppErrorApi implements AppApiErrorInterface {
|
|
199
|
+
success = false as const;
|
|
200
|
+
|
|
201
|
+
constructor(
|
|
202
|
+
public id: string,
|
|
203
|
+
public message?: string
|
|
204
|
+
) {}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export class AppSuccessApi<T = unknown> implements AppApiSuccessInterface<T> {
|
|
208
|
+
success = true as const;
|
|
209
|
+
|
|
210
|
+
constructor(public data?: T) {}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 2. Parameter Validation
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
@injectable()
|
|
218
|
+
export class PaginationValidator implements ValidatorInterface {
|
|
219
|
+
validate(data: unknown): ValidationResult {
|
|
220
|
+
// Implement validation logic
|
|
221
|
+
const errors: ValidationError[] = [];
|
|
222
|
+
|
|
223
|
+
if (!this.isValidPageNumber(data.page)) {
|
|
224
|
+
errors.push({ field: 'page', message: 'Invalid page number' });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
valid: errors.length === 0,
|
|
229
|
+
errors
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
getThrow(data: unknown): PaginationInterface {
|
|
234
|
+
const result = this.validate(data);
|
|
235
|
+
if (!result.valid) {
|
|
236
|
+
throw new ValidationError(result.errors);
|
|
237
|
+
}
|
|
238
|
+
return data as PaginationInterface;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Best Practices and Examples
|
|
244
|
+
|
|
245
|
+
### 1. API Interface Definition
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// 1. Define interface
|
|
249
|
+
interface UserApiInterface {
|
|
250
|
+
login(params: LoginParams): Promise<AppApiResult<LoginResult>>;
|
|
251
|
+
logout(): Promise<AppApiResult<void>>;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 2. Implement interface
|
|
255
|
+
@injectable()
|
|
256
|
+
class UserApi implements UserApiInterface {
|
|
257
|
+
constructor(
|
|
258
|
+
@inject(AppApiRequester)
|
|
259
|
+
private client: AppApiRequester
|
|
260
|
+
) {}
|
|
261
|
+
|
|
262
|
+
async login(params: LoginParams): Promise<AppApiResult<LoginResult>> {
|
|
263
|
+
// Implement login logic
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async logout(): Promise<AppApiResult<void>> {
|
|
267
|
+
// Implement logout logic
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 2. Error Handling Best Practices
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// 1. Use unified error handling
|
|
276
|
+
try {
|
|
277
|
+
const result = await userApi.login(params);
|
|
278
|
+
if (!result.success) {
|
|
279
|
+
// Handle business error
|
|
280
|
+
handleBusinessError(result);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
// Handle success response
|
|
284
|
+
handleSuccess(result.data);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
// Handle network errors etc.
|
|
287
|
+
handleNetworkError(error);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// 2. Use error plugin
|
|
291
|
+
class DialogErrorPlugin implements ExecutorPlugin {
|
|
292
|
+
onError(error: Error, context: ExecutorContext): void {
|
|
293
|
+
// Show error dialog
|
|
294
|
+
this.dialogHandler.showError({
|
|
295
|
+
title: 'Error',
|
|
296
|
+
content: error.message
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 3. API Testing Example
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
describe('UserApi', () => {
|
|
306
|
+
let userApi: UserApi;
|
|
307
|
+
let mockClient: jest.Mocked<AppApiRequester>;
|
|
308
|
+
|
|
309
|
+
beforeEach(() => {
|
|
310
|
+
mockClient = {
|
|
311
|
+
request: jest.fn()
|
|
312
|
+
} as any;
|
|
313
|
+
userApi = new UserApi(mockClient);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should handle login success', async () => {
|
|
317
|
+
const mockResponse = {
|
|
318
|
+
success: true,
|
|
319
|
+
data: { token: 'test-token' }
|
|
320
|
+
};
|
|
321
|
+
mockClient.request.mockResolvedValue({ data: mockResponse });
|
|
322
|
+
|
|
323
|
+
const result = await userApi.login({
|
|
324
|
+
email: 'test@example.com',
|
|
325
|
+
password: 'password'
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(result).toEqual(mockResponse);
|
|
329
|
+
expect(mockClient.request).toHaveBeenCalledWith({
|
|
330
|
+
url: '/user/login',
|
|
331
|
+
method: 'POST',
|
|
332
|
+
data: {
|
|
333
|
+
email: 'test@example.com',
|
|
334
|
+
password: 'password'
|
|
335
|
+
},
|
|
336
|
+
encryptProps: 'password'
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 4. API Documentation Generation
|
|
343
|
+
|
|
344
|
+
Use TypeScript types and comments to generate API documentation:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
/**
|
|
348
|
+
* User login API
|
|
349
|
+
* @param params - Login parameters
|
|
350
|
+
* @param params.email - User email
|
|
351
|
+
* @param params.password - User password (will be automatically encrypted)
|
|
352
|
+
* @returns Login result containing user token
|
|
353
|
+
* @throws {ValidationError} When parameter validation fails
|
|
354
|
+
* @throws {AuthError} When authentication fails
|
|
355
|
+
*/
|
|
356
|
+
async login(params: LoginParams): Promise<AppApiResult<LoginResult>>;
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Summary
|
|
360
|
+
|
|
361
|
+
The project's API design follows these principles:
|
|
362
|
+
|
|
363
|
+
1. **Layered Architecture**:
|
|
364
|
+
- Clear interface definitions
|
|
365
|
+
- Service layer implements business logic
|
|
366
|
+
- Unified request handling
|
|
367
|
+
- Plugin-based feature extension
|
|
368
|
+
|
|
369
|
+
2. **Type Safety**:
|
|
370
|
+
- Complete TypeScript type definitions
|
|
371
|
+
- Runtime parameter validation
|
|
372
|
+
- Compile-time type checking
|
|
373
|
+
|
|
374
|
+
3. **Error Handling**:
|
|
375
|
+
- Unified error response format
|
|
376
|
+
- Plugin-based error handling
|
|
377
|
+
- Complete error tracking
|
|
378
|
+
|
|
379
|
+
4. **Extensibility**:
|
|
380
|
+
- Plugin system supports feature extension
|
|
381
|
+
- Dependency injection achieves loose coupling
|
|
382
|
+
- Middleware supports cross-cutting concerns
|
|
383
|
+
|
|
384
|
+
5. **Security**:
|
|
385
|
+
- Automatic parameter encryption
|
|
386
|
+
- Unified authentication mechanism
|
|
387
|
+
- Parameter validation and sanitization
|