@thinkbun/middleware 1.0.3 → 1.0.4

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @thinkbun/middleware
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - docs
8
+ - Updated dependencies
9
+ - @thinkbun/core@1.0.7
10
+
3
11
  ## 1.0.3
4
12
 
5
13
  ### Patch Changes
package/README.md CHANGED
@@ -78,81 +78,7 @@ app.use(logger({
78
78
  | `logger` | `(message: string) => void` | `console.log` | Custom logger function |
79
79
  | `ignorePaths` | `string[]` | `[]` | Array of paths to exclude from logging |
80
80
 
81
- ### 3. Validator
82
-
83
- Request parameter validation middleware that validates request body, query parameters, and route parameters using Ajv schema validation.
84
-
85
- #### Usage
86
-
87
- ```typescript
88
- import { validator } from '@thinkbun/middleware';
89
-
90
- app.use(validator({
91
- rules: [
92
- {
93
- path: '/api/users',
94
- method: 'POST',
95
- schema: {
96
- body: {
97
- type: 'object',
98
- properties: {
99
- name: { type: 'string' },
100
- email: { type: 'string', format: 'email' },
101
- age: { type: 'number', minimum: 18 }
102
- },
103
- required: ['name', 'email']
104
- },
105
- query: {
106
- type: 'object',
107
- properties: {
108
- active: { type: 'boolean' }
109
- }
110
- }
111
- }
112
- },
113
- {
114
- path: '/api/users/:id',
115
- method: 'GET',
116
- schema: {
117
- params: {
118
- type: 'object',
119
- properties: {
120
- id: { type: 'string', pattern: '^\\d+$' }
121
- },
122
- required: ['id']
123
- }
124
- }
125
- }
126
- ],
127
- errorHandler: (errors, ctx) => {
128
- // Custom validation error handling
129
- ctx.throw(400, `Validation error: ${errors[0].message}`);
130
- }
131
- }));
132
- ```
133
-
134
- #### Options
135
-
136
- | Option | Type | Default | Description |
137
- | -------------- | --------------------------------------- | ------- | ----------------------------------------- |
138
- | `rules` | `ValidationRule[]` | - | Array of validation rules |
139
- | `errorHandler` | `(errors: any[], ctx: Context) => void` | - | Custom validation error handling function |
140
-
141
- #### ValidationRule Interface
142
-
143
- ```typescript
144
- interface ValidationRule {
145
- path: string; // Request path pattern to match
146
- method: string; // HTTP method to match (GET, POST, etc.)
147
- schema: {
148
- body?: any; // Request body schema
149
- query?: any; // Query parameters schema
150
- params?: any; // Route parameters schema
151
- };
152
- }
153
- ```
154
-
155
- ### 4. CORS
81
+ ### 3. CORS
156
82
 
157
83
  CORS configuration middleware that handles Cross-Origin Resource Sharing, supporting flexible configuration options.
158
84
 
@@ -188,9 +114,9 @@ app.use(cors({
188
114
  | `maxAge` | `number` | `86400` (24 hours) | Preflight request cache time (seconds) |
189
115
  | `preflightContinue` | `boolean` | `true` | Whether to continue processing preflight requests |
190
116
 
191
- ### 5. Static Serve
117
+ ### 4. Static Serve
192
118
 
193
- Static file serving middleware that serves static files from the specified directory, with support for request path prefixes, cache control, and more.
119
+ Static file serving middleware that serves static files from specified directory, with support for request path prefixes, cache control, and more.
194
120
 
195
121
  #### Usage
196
122
 
@@ -215,10 +141,10 @@ app.use(staticServe({
215
141
  #### Options
216
142
 
217
143
  | Option | Type | Default | Description |
218
- | -------------- | --------- | -------------- | -------------------------------- |
219
- | `root` | `string` | - | Static file directory (required) |
220
- | `prefix` | `string` | `''` | Request path prefix |
221
- | `index` | `string` | `'index.html'` | Default index file |
144
+ | -------------- | --------- | -------------- | ------------------------- |
145
+ | `root` | `string` | - | Static file directory (required) |
146
+ | `prefix` | `string` | `''` | Request path prefix |
147
+ | `index` | `string` | `'index.html'` | Default index file |
222
148
  | `maxAge` | `number` | `3600` | Cache control max-age (seconds) |
223
149
  | `gzip` | `boolean` | `true` | Enable gzip compression |
224
150
  | `brotli` | `boolean` | `true` | Enable Brotli compression |
@@ -240,7 +166,7 @@ app.use(middlewares.staticServe({ root: './public' }));
240
166
 
241
167
  ## Middleware Execution Flow
242
168
 
243
- The middleware follows the Koa onion model, where each middleware can execute code before and after subsequent middleware:
169
+ The middleware follows Koa onion model, where each middleware can execute code before and after subsequent middleware:
244
170
 
245
171
  ```typescript
246
172
  app.use(async (ctx, next) => {
@@ -275,11 +201,11 @@ app.use(async (ctx, next) => {
275
201
 
276
202
  ## Best Practices
277
203
 
278
- 1. **Order Matters**: Middleware execution follows the order in which they are added with `app.use()`. Place global middleware (like error handler, logger, CORS) before route-specific middleware.
204
+ 1. **Order Matters**: Middleware execution follows order in which they are added with `app.use()`. Place global middleware (like error handler, logger, CORS) before route-specific middleware.
279
205
 
280
206
  2. **Error Handler Placement**: Always place the error handler middleware first to ensure it can capture errors from all subsequent middleware.
281
207
 
282
- 3. **Static Files**: Place the static file serving middleware before route handlers to improve performance (static files are served directly without going through route processing).
208
+ 3. **Static Files**: Place static file serving middleware before route handlers to improve performance (static files are served directly without going through route processing).
283
209
 
284
210
  4. **Validation Scope**: Use the validator middleware with specific paths and methods to avoid unnecessary validation overhead.
285
211
 
package/README_CN.md ADDED
@@ -0,0 +1,290 @@
1
+ # ThinkBun 中间件集合
2
+
3
+ 为 ThinkBun 框架提供的全面中间件集合,遵循 Koa 中间件规范,支持 async/await 语法和洋葱模型执行流程。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ bun add @thinkbun/middleware
9
+ ```
10
+
11
+ ## 可用中间件
12
+
13
+ ### 1. 错误处理器
14
+
15
+ 全局错误处理中间件,捕获并处理后续中间件抛出的错误,支持在开发和生产环境中显示不同的错误信息。
16
+
17
+ #### 使用方法
18
+
19
+ ```typescript
20
+ import { errorHandler } from '@thinkbun/middleware';
21
+
22
+ // 基本使用
23
+ app.use(errorHandler());
24
+
25
+ // 使用自定义选项
26
+ app.use(errorHandler({
27
+ exposeStackTrace: true, // 在错误响应中显示堆栈跟踪(仅建议在开发环境使用)
28
+ customHandler: (error, ctx) => {
29
+ // 自定义错误处理逻辑
30
+ return new Response(JSON.stringify({ error: error.message }), {
31
+ status: (error as any).status || 500,
32
+ headers: { 'Content-Type': 'application/json' }
33
+ });
34
+ },
35
+ logger: (error) => {
36
+ // 自定义错误日志记录
37
+ console.error('Error occurred:', error);
38
+ }
39
+ }));
40
+ ```
41
+
42
+ #### 选项
43
+
44
+ | 选项 | 类型 | 默认值 | 描述 |
45
+ | ----------------- | ------------------------------------------ | ------- | -------------------------------------- |
46
+ | `exposeStackTrace` | `boolean` | `false` | 是否在错误响应中暴露堆栈跟踪 |
47
+ | `customHandler` | `(error: Error, ctx: Context) => Response` | - | 自定义错误处理函数 |
48
+ | `logger` | `(error: Error, ctx: Context) => void` | - | 自定义错误日志记录函数 |
49
+
50
+ ### 2. 日志记录器
51
+
52
+ 请求日志记录中间件,记录请求和响应信息,支持自定义日志格式、路径过滤和日志记录器。
53
+
54
+ #### 使用方法
55
+
56
+ ```typescript
57
+ import { logger } from '@thinkbun/middleware';
58
+
59
+ // 基本使用
60
+ app.use(logger());
61
+
62
+ // 使用自定义选项
63
+ app.use(logger({
64
+ format: (ctx) => `${ctx.method} ${ctx.path} ${ctx.header('user-agent')}`,
65
+ logger: (message) => {
66
+ // 自定义日志记录
67
+ console.log('[LOG]', message);
68
+ },
69
+ ignorePaths: ['/health', '/metrics'] // 从日志中排除的路径
70
+ }));
71
+ ```
72
+
73
+ #### 选项
74
+
75
+ | 选项 | 类型 | 默认值 | 描述 |
76
+ | ------------ | --------------------------- | ------------- | ------------------------- |
77
+ | `format` | `(ctx: Context) => string` | - | 自定义日志格式函数 |
78
+ | `logger` | `(message: string) => void` | `console.log` | 自定义日志记录函数 |
79
+ | `ignorePaths`| `string[]` | `[]` | 从日志中排除的路径数组 |
80
+
81
+ ### 3. 验证器
82
+
83
+ 请求参数验证中间件,使用 Ajv 模式验证验证请求体、查询参数和路由参数。
84
+
85
+ #### 使用方法
86
+
87
+ ```typescript
88
+ import { validator } from '@thinkbun/middleware';
89
+
90
+ app.use(validator({
91
+ rules: [
92
+ {
93
+ path: '/api/users',
94
+ method: 'POST',
95
+ schema: {
96
+ body: {
97
+ type: 'object',
98
+ properties: {
99
+ name: { type: 'string' },
100
+ email: { type: 'string', format: 'email' },
101
+ age: { type: 'number', minimum: 18 }
102
+ },
103
+ required: ['name', 'email']
104
+ },
105
+ query: {
106
+ type: 'object',
107
+ properties: {
108
+ active: { type: 'boolean' }
109
+ }
110
+ }
111
+ }
112
+ },
113
+ {
114
+ path: '/api/users/:id',
115
+ method: 'GET',
116
+ schema: {
117
+ params: {
118
+ type: 'object',
119
+ properties: {
120
+ id: { type: 'string', pattern: '^\\d+$' }
121
+ },
122
+ required: ['id']
123
+ }
124
+ }
125
+ }
126
+ ],
127
+ errorHandler: (errors, ctx) => {
128
+ // 自定义验证错误处理
129
+ ctx.throw(400, `Validation error: ${errors[0].message}`);
130
+ }
131
+ }));
132
+ ```
133
+
134
+ #### 选项
135
+
136
+ | 选项 | 类型 | 默认值 | 描述 |
137
+ | -------------- | --------------------------------------- | ------- | ----------------------------------- |
138
+ | `rules` | `ValidationRule[]` | - | 验证规则数组 |
139
+ | `errorHandler` | `(errors: any[], ctx: Context) => void` | - | 自定义验证错误处理函数 |
140
+
141
+ #### ValidationRule 接口
142
+
143
+ ```typescript
144
+ interface ValidationRule {
145
+ path: string; // 要匹配的请求路径模式
146
+ method: string; // 要匹配的 HTTP 方法(GET、POST 等)
147
+ schema: {
148
+ body?: any; // 请求体模式
149
+ query?: any; // 查询参数模式
150
+ params?: any; // 路由参数模式
151
+ };
152
+ }
153
+ ```
154
+
155
+ ### 4. CORS
156
+
157
+ CORS 配置中间件,处理跨源资源共享,支持灵活的配置选项。
158
+
159
+ #### 使用方法
160
+
161
+ ```typescript
162
+ import { cors } from '@thinkbun/middleware';
163
+
164
+ // 基本使用(默认允许所有源)
165
+ app.use(cors());
166
+
167
+ // 使用自定义选项
168
+ app.use(cors({
169
+ origin: ['https://example.com', 'https://sub.example.com'], // 允许特定源
170
+ methods: ['GET', 'POST', 'PUT', 'DELETE'], // 允许的 HTTP 方法
171
+ allowedHeaders: ['Content-Type', 'Authorization'], // 允许的请求头
172
+ exposedHeaders: ['X-Custom-Header'], // 暴露给客户端的响应头
173
+ credentials: true, // 允许凭据
174
+ maxAge: 86400, // 预检请求缓存时间(秒)
175
+ preflightContinue: true // 继续处理预检请求
176
+ }));
177
+ ```
178
+
179
+ #### 选项
180
+
181
+ | 选项 | 类型 | 默认值 | 描述 |
182
+ | ----------------- | ----------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------- |
183
+ | `origin` | `string \| string[] \| ((origin: string) => boolean)` | `'*'` | 允许的源 |
184
+ | `methods` | `string[]` | `['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']` | 允许的 HTTP 方法 |
185
+ | `allowedHeaders` | `string[]` | - | 允许的请求头(默认为 Access-Control-Request-Headers 的值) |
186
+ | `exposedHeaders` | `string[]` | - | 暴露给客户端的响应头 |
187
+ | `credentials` | `boolean` | `false` | 是否允许凭据 |
188
+ | `maxAge` | `number` | `86400` (24 小时) | 预检请求缓存时间(秒) |
189
+ | `preflightContinue` | `boolean` | `true` | 是否继续处理预检请求 |
190
+
191
+ ### 5. 静态文件服务
192
+
193
+ 静态文件服务中间件,从指定目录服务静态文件,支持请求路径前缀、缓存控制等功能。
194
+
195
+ #### 使用方法
196
+
197
+ ```typescript
198
+ import { staticServe } from '@thinkbun/middleware';
199
+
200
+ // 基本使用
201
+ app.use(staticServe({ root: './public' }));
202
+
203
+ // 使用自定义选项
204
+ app.use(staticServe({
205
+ root: './public', // 静态文件目录
206
+ prefix: '/static', // 请求路径前缀(例如 /static/css/style.css)
207
+ index: 'index.html', // 默认索引文件
208
+ maxAge: 3600, // 缓存控制 max-age(秒)
209
+ gzip: true, // 启用 gzip 压缩
210
+ brotli: true, // 启用 Brotli 压缩
211
+ cacheControl: true // 启用缓存控制头
212
+ }));
213
+ ```
214
+
215
+ #### 选项
216
+
217
+ | 选项 | 类型 | 默认值 | 描述 |
218
+ | ------------- | --------- | -------------- | ------------------------- |
219
+ | `root` | `string` | - | 静态文件目录(必需) |
220
+ | `prefix` | `string` | `''` | 请求路径前缀 |
221
+ | `index` | `string` | `'index.html'` | 默认索引文件 |
222
+ | `maxAge` | `number` | `3600` | 缓存控制 max-age(秒) |
223
+ | `gzip` | `boolean` | `true` | 启用 gzip 压缩 |
224
+ | `brotli` | `boolean` | `true` | 启用 Brotli 压缩 |
225
+ | `cacheControl` | `boolean` | `true` | 启用缓存控制头 |
226
+
227
+ ## 使用所有中间件
228
+
229
+ 您也可以一次性导入所有中间件:
230
+
231
+ ```typescript
232
+ import { middlewares } from '@thinkbun/middleware';
233
+
234
+ // 使用所有中间件
235
+ app.use(middlewares.errorHandler());
236
+ app.use(middlewares.logger());
237
+ app.use(middlewares.cors());
238
+ app.use(middlewares.staticServe({ root: './public' }));
239
+ ```
240
+
241
+ ## 中间件执行流程
242
+
243
+ 中间件遵循 Koa 洋葱模型,每个中间件可以在后续中间件之前和之后执行代码:
244
+
245
+ ```typescript
246
+ app.use(async (ctx, next) => {
247
+ // 在下一个中间件之前执行的代码
248
+ console.log('中间件 1: 之前');
249
+
250
+ const response = await next();
251
+
252
+ // 在下一个中间件之后执行的代码
253
+ console.log('中间件 1: 之后');
254
+
255
+ return response;
256
+ });
257
+
258
+ app.use(async (ctx, next) => {
259
+ console.log('中间件 2: 之前');
260
+
261
+ const response = await next();
262
+
263
+ console.log('中间件 2: 之后');
264
+
265
+ return response;
266
+ });
267
+
268
+ // 处理请求时的输出:
269
+ // 中间件 1: 之前
270
+ // 中间件 2: 之前
271
+ // (请求处理)
272
+ // 中间件 2: 之后
273
+ // 中间件 1: 之后
274
+ ```
275
+
276
+ ## 最佳实践
277
+
278
+ 1. **顺序很重要**:中间件执行遵循使用 `app.use()` 添加时的顺序。将全局中间件(如错误处理器、日志、CORS)放在特定于路由的中间件之前。
279
+
280
+ 2. **错误处理器位置**:始终将错误处理中间件放在第一位,以确保它可以捕获所有后续中间件的错误。
281
+
282
+ 3. **静态文件**:将静态文件服务中间件放在路由处理器之前,以提高性能(静态文件直接提供服务,无需经过路由处理)。
283
+
284
+ 4. **验证范围**:将验证器中间件与特定路径和方法一起使用,以避免不必要的验证开销。
285
+
286
+ 5. **环境特定配置**:为开发和生产环境配置不同的中间件(例如,仅在开发环境中暴露堆栈跟踪)。
287
+
288
+ ## 许可证
289
+
290
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkbun/middleware",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "module": "src/index.ts",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "picocolors": "^1.1.1",
14
- "@thinkbun/core": "1.0.4"
14
+ "@thinkbun/core": "1.0.6"
15
15
  },
16
16
  "publishConfig": {
17
17
  "access": "public"