kb-server 0.0.11 → 0.0.12-beta.1

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.
Files changed (2) hide show
  1. package/README.md +426 -18
  2. package/package.json +3 -2
package/README.md CHANGED
@@ -1,44 +1,452 @@
1
1
  # KB Server
2
2
 
3
- 快速创建一个 `Node` 服务 - 基于 `Express`
3
+ 基于 `Express` 的快速 Node.js 服务框架,提供简洁的 API 开发体验、标准错误码、SSE 支持、统一鉴权和完善的日志系统。
4
4
 
5
- 快速创建 `API`、标准错误码、`Server`、支持统一鉴权函数(API 级别)、自定义中间件、日志、支持 `SSE`
5
+ ## 特性
6
+
7
+ - 🚀 快速创建 REST API
8
+ - 🎯 基于类的参数校验(使用 class-validator)
9
+ - 🔒 统一鉴权函数(API 级别)
10
+ - 📡 原生支持 SSE (Server-Sent Events)
11
+ - 📋 标准错误码系统
12
+ - 🔌 支持自定义 Express 中间件
13
+ - 📊 内置日志系统(基于 pino)
14
+ - 🌍 统一的响应格式
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ npm install kb-server
20
+ ```
21
+
22
+ 要求 Node.js >= 18.0.0
23
+
24
+ ## 快速开始
25
+
26
+ ### 基础用法
6
27
 
7
28
  ```typescript
8
29
  import { createServer } from "kb-server";
9
30
  import * as apis from "./apis";
10
31
 
11
- // 写法一
32
+ // 写法一:直接创建并启动
12
33
  const server = createServer({ apis });
13
34
  server.listen(3000);
14
35
 
15
- // 写法二
36
+ // 写法二:异步初始化后启动
16
37
  (async () => {
17
- // 其他的异步操作,例如:初始化数据库
38
+ // 其他异步操作,例如:初始化数据库
18
39
  return createServer({ apis });
19
40
  })().then((app) => app.listen(3000));
20
41
  ```
21
42
 
22
- ## SSE 支持
43
+ ### 创建 API
44
+
45
+ 使用 `implementAPI` 创建带有类型安全的 API:
46
+
47
+ ```typescript
48
+ import { implementAPI } from "kb-server";
49
+ import { IsString, IsNotEmpty } from "class-validator";
50
+
51
+ // 定义请求参数类
52
+ class CreateUserParams {
53
+ @IsString()
54
+ @IsNotEmpty()
55
+ name: string;
56
+
57
+ @IsString()
58
+ @IsNotEmpty()
59
+ email: string;
60
+ }
61
+
62
+ // 定义 API 函数类型
63
+ type CreateUserFn = (params: CreateUserParams) => Promise<{ id: string }>;
64
+
65
+ // 实现 API
66
+ export const createUser = implementAPI<CreateUserFn>(
67
+ {} as CreateUserFn,
68
+ CreateUserParams,
69
+ async (params, ctx) => {
70
+ // ctx.RequestId - 请求 ID
71
+ // ctx.AuthInfo - 鉴权信息(如果配置了 authFn)
72
+ console.log(`Request ID: ${ctx.RequestId}`);
73
+
74
+ // 业务逻辑
75
+ const user = await database.createUser(params);
76
+
77
+ return { id: user.id };
78
+ }
79
+ );
80
+
81
+ // 导出所有 API
82
+ export default {
83
+ CreateUser: createUser,
84
+ };
85
+ ```
86
+
87
+ ### 配置服务器
23
88
 
24
89
  ```typescript
25
90
  import { createServer } from "kb-server";
91
+ import cors from "cors";
26
92
  import * as apis from "./apis";
27
93
  import * as sse from "./sse";
28
94
 
95
+ const server = createServer(
96
+ {
97
+ apis, // API 列表
98
+ authFn, // 鉴权函数(可选)
99
+ log: true, // 是否开启请求日志
100
+ middlewares: [cors()], // 自定义中间件列表
101
+ sse: { // SSE 配置(可选)
102
+ handlers: sse, // SSE 处理函数
103
+ route: "/sse", // SSE 路由(默认: /sse)
104
+ timeout: 30000, // 超时时间(毫秒,默认: 30000)
105
+ },
106
+ },
107
+ {
108
+ limit: "10mb", // 请求体大小限制(默认: 10mb)
109
+ }
110
+ );
29
111
 
30
- (async () => {
31
- // 其他的异步操作,例如:初始化数据库
32
- return createServer({
33
- apis,
34
- sse: {
35
- handlers: sse, // ...SSE处理函数
112
+ server.listen(3000);
113
+ ```
114
+
115
+ ## SSE 支持
116
+
117
+ 创建 SSE API 实现实时数据推送:
118
+
119
+ ```typescript
120
+ import { implementSseAPI } from "kb-server";
121
+ import { IsString } from "class-validator";
122
+
123
+ // 定义请求参数
124
+ class StreamChatParams {
125
+ @IsString()
126
+ prompt: string;
127
+ }
128
+
129
+ // 定义 SSE 函数类型
130
+ type StreamChatFn = (params: StreamChatParams) => Promise<void>;
131
+
132
+ // 实现 SSE API
133
+ export const streamChat = implementSseAPI<StreamChatFn>(
134
+ {} as StreamChatFn,
135
+ StreamChatParams,
136
+ async (params, sse, ctx) => {
137
+ // sse.push(data) - 推送数据到客户端
138
+ // sse.close() - 主动关闭连接
139
+ // sse.abortController - 中止控制器
140
+
141
+ try {
142
+ // 模拟流式推送
143
+ for (let i = 0; i < 10; i++) {
144
+ sse.push({
145
+ chunk: `消息片段 ${i + 1}`,
146
+ progress: (i + 1) * 10,
147
+ });
148
+
149
+ // 模拟延迟
150
+ await new Promise(resolve => setTimeout(resolve, 500));
151
+ }
152
+
153
+ // 完成后关闭连接
154
+ sse.close();
155
+ } catch (error) {
156
+ // 可以使用 abortController 中止操作
157
+ if (!sse.abortController.signal.aborted) {
158
+ throw error;
159
+ }
160
+ }
161
+ }
162
+ );
163
+
164
+ // 导出 SSE API
165
+ export default {
166
+ StreamChat: streamChat,
167
+ };
168
+ ```
169
+
170
+ ## 统一鉴权
171
+
172
+ 在 API 级别实现统一的鉴权逻辑:
173
+
174
+ ```typescript
175
+ import { createServer } from "kb-server";
176
+
177
+ const authFn = async (action: string, req: express.Request) => {
178
+ // 从请求中获取 token
179
+ const token = req.headers.authorization?.replace('Bearer ', '');
180
+
181
+ if (!token) {
182
+ return false; // 返回 false 表示无权限
183
+ }
184
+
185
+ // 验证 token
186
+ const userInfo = await verifyToken(token);
187
+ if (!userInfo) {
188
+ return false;
189
+ }
190
+
191
+ // 返回对象会将信息注入到 ctx.AuthInfo
192
+ return {
193
+ userId: userInfo.id,
194
+ role: userInfo.role,
195
+ };
196
+ };
197
+
198
+ const server = createServer({
199
+ apis,
200
+ authFn,
201
+ });
202
+
203
+ // 在 API 中使用鉴权信息
204
+ const myAPI = implementAPI<SomeFn>(
205
+ {} as SomeFn,
206
+ ParamsClass,
207
+ async (params, ctx) => {
208
+ const { userId, role } = ctx.AuthInfo || {};
209
+ console.log(`当前用户: ${userId}, 角色: ${role}`);
210
+
211
+ // 业务逻辑...
212
+ }
213
+ );
214
+ ```
215
+
216
+ ## 自定义错误码
217
+
218
+ 使用 `createErrors` 创建业务特定的错误码:
219
+
220
+ ```typescript
221
+ import { createErrors } from "kb-server";
222
+
223
+ // 创建自定义错误码
224
+ const CustomErrors = createErrors({
225
+ // 一级错误码(可选)
226
+ // InvalidParameter: {
227
+ // // 扩展默认错误码
228
+ // },
229
+ BusinessError: {
230
+ // 新增业务错误码
231
+ InsufficientBalance: "余额不足",
232
+ OrderExpired: "订单已过期",
233
+ ProductOutOfStock: "商品库存不足",
234
+ },
235
+ });
236
+
237
+ // 使用自定义错误
238
+ const someAPI = implementAPI<SomeFn>(
239
+ {} as SomeFn,
240
+ ParamsClass,
241
+ async (params, ctx) => {
242
+ const balance = await getBalance(ctx.AuthInfo?.userId);
243
+ if (balance < 100) {
244
+ throw new CustomErrors.BusinessError.InsufficientBalance();
245
+ }
246
+
247
+ // 业务逻辑...
248
+ }
249
+ );
250
+ ```
251
+
252
+ ## 请求与响应格式
253
+
254
+ ### 请求格式
255
+
256
+ 所有 POST 请求体应包含以下结构:
257
+
258
+ ```json
259
+ {
260
+ "Action": "API名称",
261
+ "其他参数": "..."
262
+ }
263
+ ```
264
+
265
+ ### 成功响应
266
+
267
+ ```json
268
+ {
269
+ "Response": {
270
+ "Data": {
271
+ // 返回的数据
36
272
  },
37
- authFn: (action, req) => {
38
- // ...统一鉴权函数
273
+ "RequestId": "uuid-v4"
274
+ }
275
+ }
276
+ ```
277
+
278
+ ### 错误响应
279
+
280
+ ```json
281
+ {
282
+ "Response": {
283
+ "Error": {
284
+ "Code": "InvalidParameter.ValidationError",
285
+ "Message": "参数校验失败"
39
286
  },
40
- middlewares: [], // ...中间键列表
41
- log: true, // ...框架日志
42
- });
43
- })().then((app) => app.listen(3000));
287
+ "RequestId": "uuid-v4"
288
+ }
289
+ }
44
290
  ```
291
+
292
+ ## 内置错误码
293
+
294
+ | 一级错误码 | 二级错误码 | 说明 |
295
+ |-----------|-----------|------|
296
+ | InvalidParameter | EmptyParameter | 请求参数不能为空 |
297
+ | InvalidParameter | EmptyAPIRequest | 未指定 API 的请求 |
298
+ | InvalidParameter | ValidationError | 参数校验失败 |
299
+ | InvalidParameter | RouteError | 路由错误 |
300
+ | ResourceNotFound | APINotFound | 不存在的 API |
301
+ | ResourceNotFound | AuthFunctionNotFound | 鉴权函数不存在 |
302
+ | FailOperation | NoPermission | 无权操作 |
303
+ | FailOperation | NotLogin | 未登录 |
304
+ | InternalError | UnknownError | 未知错误 |
305
+ | InternalError | ServiceError | 内部服务错误 |
306
+ | InternalError | DatabaseError | DB 异常 |
307
+
308
+ ## 日志系统
309
+
310
+ 框架内置基于 pino 的日志系统,支持结构化日志:
311
+
312
+ ```typescript
313
+ import { logger } from "kb-server";
314
+
315
+ // 使用日志
316
+ logger.info({ userId: 123, action: "login" }, "用户登录");
317
+ logger.warn({ ip: "192.168.1.1" }, "异常访问");
318
+ logger.error({ error: err }, "系统错误");
319
+ ```
320
+
321
+ 环境变量:
322
+ - `LOG_LEVEL` - 日志级别(默认: info)
323
+ - `NODE_ENV` - 环境模式(非 production 时使用 pino-pretty 格式化输出)
324
+
325
+ ## 完整示例
326
+
327
+ ```typescript
328
+ import { createServer, implementAPI, createErrors } from "kb-server";
329
+ import { IsString, IsEmail } from "class-validator";
330
+ import cors from "cors";
331
+
332
+ // 自定义错误码
333
+ const AppErrors = createErrors({
334
+ UserError: {
335
+ DuplicateEmail: "邮箱已被注册",
336
+ },
337
+ });
338
+
339
+ // 参数类
340
+ class RegisterParams {
341
+ @IsString()
342
+ @IsNotEmpty()
343
+ username: string;
344
+
345
+ @IsString()
346
+ @IsEmail()
347
+ email: string;
348
+
349
+ @IsString()
350
+ @IsNotEmpty()
351
+ password: string;
352
+ }
353
+
354
+ // 定义 API 类型
355
+ type RegisterFn = (params: RegisterParams) => Promise<{ id: string }>;
356
+
357
+ // 实现 API
358
+ export const register = implementAPI<RegisterFn>(
359
+ {} as RegisterFn,
360
+ RegisterParams,
361
+ async (params, ctx) => {
362
+ // 检查邮箱是否已注册
363
+ const exists = await checkEmailExists(params.email);
364
+ if (exists) {
365
+ throw new AppErrors.UserError.DuplicateEmail();
366
+ }
367
+
368
+ // 创建用户
369
+ const user = await createUser(params);
370
+
371
+ return { id: user.id };
372
+ }
373
+ );
374
+
375
+ // 导出 API
376
+ const apis = {
377
+ User_Register: register,
378
+ };
379
+
380
+ // 鉴权函数
381
+ const authFn = async (action, req) => {
382
+ // 公开接口不需要鉴权
383
+ if (action.startsWith("User_")) {
384
+ return true;
385
+ }
386
+
387
+ // 其他接口需要鉴权
388
+ const token = req.headers.authorization?.replace('Bearer ', '');
389
+ return await verifyToken(token);
390
+ };
391
+
392
+ // 创建服务器
393
+ const server = createServer({
394
+ apis,
395
+ authFn,
396
+ log: true,
397
+ middlewares: [cors()],
398
+ });
399
+
400
+ server.listen(3000, () => {
401
+ console.log('Server is running on http://localhost:3000');
402
+ });
403
+ ```
404
+
405
+ ## API 参考
406
+
407
+ ### createServer
408
+
409
+ 创建 Express 服务器实例。
410
+
411
+ ```typescript
412
+ function createServer(
413
+ params: ICreateServerParams,
414
+ options?: ICreateServerOptions
415
+ ): express.Application
416
+ ```
417
+
418
+ **参数**:
419
+ - `params.apis` - API 列表
420
+ - `params.authFn` - 鉴权函数(可选)
421
+ - `params.log` - 是否开启日志(默认: true)
422
+ - `params.middlewares` - 自定义中间件列表(可选)
423
+ - `params.sse` - SSE 配置(可选)
424
+ - `options.limit` - 请求体大小限制(默认: "10mb")
425
+
426
+ ### implementAPI
427
+
428
+ 实现带有类型检查的 API。
429
+
430
+ ```typescript
431
+ function implementAPI<F, A = Record<string, any>>(
432
+ actionStub: F,
433
+ ParamsClass: Class<StubParam<F>>,
434
+ execution: APIExecution<StubParam<F>, ReturnType<F>, A>
435
+ ): API<StubParam<F>, ReturnType<F>>
436
+ ```
437
+
438
+ ### implementSseAPI
439
+
440
+ 实现 SSE API。
441
+
442
+ ```typescript
443
+ function implementSseAPI<F, A = Record<string, any>>(
444
+ actionStub: F,
445
+ ParamsClass: Class<StubParam<F>>,
446
+ execution: SseExecution<StubParam<F>, ReturnType<F>, A>
447
+ ): API<StubParam<F>, ReturnType<F>>
448
+ ```
449
+
450
+ ## License
451
+
452
+ ISC
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "kb-server",
3
- "version": "0.0.11",
3
+ "version": "0.0.12-beta.1",
4
4
  "description": "A fast server for Node.JS,made by express.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "rm -rf ./dist && tsc",
8
- "release": "npm run build && npm version patch && npm publish"
8
+ "release": "npm run build && npm version patch && npm publish",
9
+ "release:beta": "npm run build && npm version prerelease --preid=beta && npm publish --tag beta"
9
10
  },
10
11
  "keywords": [
11
12
  "2kb",