@pori15/logixlysia 6.0.1 → 6.0.2
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/dist/index.d.ts +36 -10
- package/dist/index.js +7 -7
- package/package.json +2 -2
- package/src/Error/errors.ts +258 -258
- package/src/Error/type.ts +51 -51
- package/src/extensions/banner.ts +26 -26
- package/src/extensions/index.ts +28 -28
- package/src/helpers/status.ts +58 -58
- package/src/index.ts +162 -141
- package/src/interfaces.ts +138 -145
- package/src/logger/create-logger.ts +240 -246
- package/src/logger/handle-http-error.ts +60 -63
- package/src/logger/index.ts +138 -139
- package/src/output/file.ts +85 -85
- package/src/output/fs.ts +5 -5
- package/src/output/index.ts +58 -58
- package/src/output/rotation-manager.ts +122 -122
- package/src/utils/error.ts +13 -13
- package/src/utils/handle-error.ts +284 -289
- package/src/utils/rotation.ts +91 -91
package/src/Error/errors.ts
CHANGED
|
@@ -1,258 +1,258 @@
|
|
|
1
|
-
// src/libs/elysia-http-problem-json/errors.ts
|
|
2
|
-
|
|
3
|
-
export interface ProblemDocument {
|
|
4
|
-
type: string
|
|
5
|
-
title: string
|
|
6
|
-
status?: number
|
|
7
|
-
detail?: string
|
|
8
|
-
instance?: string
|
|
9
|
-
[key: string]: unknown
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* RFC 9457 Problem Details Error Base Class
|
|
14
|
-
*
|
|
15
|
-
* Core members as per RFC 9457:
|
|
16
|
-
* - type: A URI reference [RFC3986] that identifies the problem type.
|
|
17
|
-
* Defaults to "about:blank" when omitted.
|
|
18
|
-
* - title: A short, human-readable summary of the problem type.
|
|
19
|
-
* - status: The HTTP status code ([RFC7231], Section 6).
|
|
20
|
-
* - detail: A human-readable explanation specific to this occurrence of the problem.
|
|
21
|
-
* - instance: A URI reference that identifies the specific occurrence of the problem.
|
|
22
|
-
*
|
|
23
|
-
* Extension members: Additional properties can be added to provide more context.
|
|
24
|
-
* These are serialized as-is in the JSON response.
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* RFC 9457 Error Base Class
|
|
28
|
-
* * 修改思路:直接使用 public readonly 属性,拒绝嵌套,拒绝 Getter。
|
|
29
|
-
*/
|
|
30
|
-
export class ProblemError extends Error {
|
|
31
|
-
// 1. 直接声明公开属性
|
|
32
|
-
public readonly status: number
|
|
33
|
-
public readonly title: string
|
|
34
|
-
public readonly type: string
|
|
35
|
-
public readonly detail?: string
|
|
36
|
-
public readonly instance?: string
|
|
37
|
-
public readonly extensions?: Record<string, unknown
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
type =
|
|
41
|
-
title: string,
|
|
42
|
-
status: number,
|
|
43
|
-
detail?: string,
|
|
44
|
-
instance?: string,
|
|
45
|
-
extensions: Record<string, unknown> = {}
|
|
46
|
-
) {
|
|
47
|
-
super(detail || title)
|
|
48
|
-
Object.setPrototypeOf(this, ProblemError.prototype)
|
|
49
|
-
|
|
50
|
-
// 2. 直接赋值给 this
|
|
51
|
-
this.status = status
|
|
52
|
-
this.title = title
|
|
53
|
-
this.type = type
|
|
54
|
-
this.detail = detail
|
|
55
|
-
this.instance = instance
|
|
56
|
-
this.extensions = extensions
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// 3. toJSON 的时候动态组装一下即可
|
|
60
|
-
toJSON(): ProblemDocument {
|
|
61
|
-
return {
|
|
62
|
-
type: this.type,
|
|
63
|
-
title: this.title,
|
|
64
|
-
status: this.status,
|
|
65
|
-
...(this.detail ? { detail: this.detail } : {}),
|
|
66
|
-
...(this.instance ? { instance: this.instance } : {}),
|
|
67
|
-
// 把扩展字段展开 (extensions)
|
|
68
|
-
...this.extensions
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// --- 40X Errors ---
|
|
74
|
-
class BadRequest extends ProblemError {
|
|
75
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
76
|
-
super(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
400,
|
|
80
|
-
detail,
|
|
81
|
-
undefined,
|
|
82
|
-
extensions
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
class Unauthorized extends ProblemError {
|
|
88
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
89
|
-
super(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
401,
|
|
93
|
-
detail,
|
|
94
|
-
undefined,
|
|
95
|
-
extensions
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
class Forbidden extends ProblemError {
|
|
101
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
102
|
-
super(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
403,
|
|
106
|
-
detail,
|
|
107
|
-
undefined,
|
|
108
|
-
extensions
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
class NotFound extends ProblemError {
|
|
114
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
115
|
-
super(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
404,
|
|
119
|
-
detail,
|
|
120
|
-
undefined,
|
|
121
|
-
extensions
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
class Conflict extends ProblemError {
|
|
127
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
128
|
-
super(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
409,
|
|
132
|
-
detail,
|
|
133
|
-
undefined,
|
|
134
|
-
extensions
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
class PaymentRequired extends ProblemError {
|
|
140
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
141
|
-
super(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
402,
|
|
145
|
-
detail,
|
|
146
|
-
undefined,
|
|
147
|
-
extensions
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
class MethodNotAllowed extends ProblemError {
|
|
153
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
154
|
-
super(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
405,
|
|
158
|
-
detail,
|
|
159
|
-
undefined,
|
|
160
|
-
extensions
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
class NotAcceptable extends ProblemError {
|
|
166
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
167
|
-
super(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
406,
|
|
171
|
-
detail,
|
|
172
|
-
undefined,
|
|
173
|
-
extensions
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// 50X Errors
|
|
179
|
-
class InternalServerError extends ProblemError {
|
|
180
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
181
|
-
super(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
500,
|
|
185
|
-
detail,
|
|
186
|
-
undefined,
|
|
187
|
-
extensions
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
class NotImplemented extends ProblemError {
|
|
193
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
194
|
-
super(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
501,
|
|
198
|
-
detail,
|
|
199
|
-
undefined,
|
|
200
|
-
extensions
|
|
201
|
-
)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
class BadGateway extends ProblemError {
|
|
206
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
207
|
-
super(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
502,
|
|
211
|
-
detail,
|
|
212
|
-
undefined,
|
|
213
|
-
extensions
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
class ServiceUnavailable extends ProblemError {
|
|
219
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
220
|
-
super(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
503,
|
|
224
|
-
detail,
|
|
225
|
-
undefined,
|
|
226
|
-
extensions
|
|
227
|
-
)
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
class GatewayTimeout extends ProblemError {
|
|
232
|
-
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
233
|
-
super(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
504,
|
|
237
|
-
detail,
|
|
238
|
-
undefined,
|
|
239
|
-
extensions
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export const HttpError = {
|
|
245
|
-
BadRequest,
|
|
246
|
-
Unauthorized,
|
|
247
|
-
PaymentRequired,
|
|
248
|
-
Forbidden,
|
|
249
|
-
NotFound,
|
|
250
|
-
MethodNotAllowed,
|
|
251
|
-
NotAcceptable,
|
|
252
|
-
Conflict,
|
|
253
|
-
InternalServerError,
|
|
254
|
-
NotImplemented,
|
|
255
|
-
BadGateway,
|
|
256
|
-
ServiceUnavailable,
|
|
257
|
-
GatewayTimeout
|
|
258
|
-
} as const
|
|
1
|
+
// src/libs/elysia-http-problem-json/errors.ts
|
|
2
|
+
|
|
3
|
+
export interface ProblemDocument {
|
|
4
|
+
type: string
|
|
5
|
+
title: string
|
|
6
|
+
status?: number
|
|
7
|
+
detail?: string
|
|
8
|
+
instance?: string
|
|
9
|
+
[key: string]: unknown
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* RFC 9457 Problem Details Error Base Class
|
|
14
|
+
*
|
|
15
|
+
* Core members as per RFC 9457:
|
|
16
|
+
* - type: A URI reference [RFC3986] that identifies the problem type.
|
|
17
|
+
* Defaults to "about:blank" when omitted.
|
|
18
|
+
* - title: A short, human-readable summary of the problem type.
|
|
19
|
+
* - status: The HTTP status code ([RFC7231], Section 6).
|
|
20
|
+
* - detail: A human-readable explanation specific to this occurrence of the problem.
|
|
21
|
+
* - instance: A URI reference that identifies the specific occurrence of the problem.
|
|
22
|
+
*
|
|
23
|
+
* Extension members: Additional properties can be added to provide more context.
|
|
24
|
+
* These are serialized as-is in the JSON response.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* RFC 9457 Error Base Class
|
|
28
|
+
* * 修改思路:直接使用 public readonly 属性,拒绝嵌套,拒绝 Getter。
|
|
29
|
+
*/
|
|
30
|
+
export class ProblemError extends Error {
|
|
31
|
+
// 1. 直接声明公开属性
|
|
32
|
+
public readonly status: number
|
|
33
|
+
public readonly title: string
|
|
34
|
+
public readonly type: string
|
|
35
|
+
public readonly detail?: string
|
|
36
|
+
public readonly instance?: string
|
|
37
|
+
public readonly extensions?: Record<string, unknown>
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
type = 'about:blank',
|
|
41
|
+
title: string,
|
|
42
|
+
status: number,
|
|
43
|
+
detail?: string,
|
|
44
|
+
instance?: string,
|
|
45
|
+
extensions: Record<string, unknown> = {}
|
|
46
|
+
) {
|
|
47
|
+
super(detail || title)
|
|
48
|
+
Object.setPrototypeOf(this, ProblemError.prototype)
|
|
49
|
+
|
|
50
|
+
// 2. 直接赋值给 this
|
|
51
|
+
this.status = status
|
|
52
|
+
this.title = title
|
|
53
|
+
this.type = type
|
|
54
|
+
this.detail = detail
|
|
55
|
+
this.instance = instance
|
|
56
|
+
this.extensions = extensions
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 3. toJSON 的时候动态组装一下即可
|
|
60
|
+
toJSON(): ProblemDocument {
|
|
61
|
+
return {
|
|
62
|
+
type: this.type,
|
|
63
|
+
title: this.title,
|
|
64
|
+
status: this.status,
|
|
65
|
+
...(this.detail ? { detail: this.detail } : {}),
|
|
66
|
+
...(this.instance ? { instance: this.instance } : {}),
|
|
67
|
+
// 把扩展字段展开 (extensions)
|
|
68
|
+
...this.extensions
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// --- 40X Errors ---
|
|
74
|
+
class BadRequest extends ProblemError {
|
|
75
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
76
|
+
super(
|
|
77
|
+
'https://httpstatuses.com/400',
|
|
78
|
+
'Bad Request',
|
|
79
|
+
400,
|
|
80
|
+
detail,
|
|
81
|
+
undefined,
|
|
82
|
+
extensions
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class Unauthorized extends ProblemError {
|
|
88
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
89
|
+
super(
|
|
90
|
+
'https://httpstatuses.com/401',
|
|
91
|
+
'Unauthorized',
|
|
92
|
+
401,
|
|
93
|
+
detail,
|
|
94
|
+
undefined,
|
|
95
|
+
extensions
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class Forbidden extends ProblemError {
|
|
101
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
102
|
+
super(
|
|
103
|
+
'https://httpstatuses.com/403',
|
|
104
|
+
'Forbidden',
|
|
105
|
+
403,
|
|
106
|
+
detail,
|
|
107
|
+
undefined,
|
|
108
|
+
extensions
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class NotFound extends ProblemError {
|
|
114
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
115
|
+
super(
|
|
116
|
+
'https://httpstatuses.com/404',
|
|
117
|
+
'Not Found',
|
|
118
|
+
404,
|
|
119
|
+
detail,
|
|
120
|
+
undefined,
|
|
121
|
+
extensions
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
class Conflict extends ProblemError {
|
|
127
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
128
|
+
super(
|
|
129
|
+
'https://httpstatuses.com/409',
|
|
130
|
+
'Conflict',
|
|
131
|
+
409,
|
|
132
|
+
detail,
|
|
133
|
+
undefined,
|
|
134
|
+
extensions
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
class PaymentRequired extends ProblemError {
|
|
140
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
141
|
+
super(
|
|
142
|
+
'https://httpstatuses.com/402',
|
|
143
|
+
'Payment Required',
|
|
144
|
+
402,
|
|
145
|
+
detail,
|
|
146
|
+
undefined,
|
|
147
|
+
extensions
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
class MethodNotAllowed extends ProblemError {
|
|
153
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
154
|
+
super(
|
|
155
|
+
'https://httpstatuses.com/405',
|
|
156
|
+
'Method Not Allowed',
|
|
157
|
+
405,
|
|
158
|
+
detail,
|
|
159
|
+
undefined,
|
|
160
|
+
extensions
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
class NotAcceptable extends ProblemError {
|
|
166
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
167
|
+
super(
|
|
168
|
+
'https://httpstatuses.com/406',
|
|
169
|
+
'Not Acceptable',
|
|
170
|
+
406,
|
|
171
|
+
detail,
|
|
172
|
+
undefined,
|
|
173
|
+
extensions
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 50X Errors
|
|
179
|
+
class InternalServerError extends ProblemError {
|
|
180
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
181
|
+
super(
|
|
182
|
+
'https://httpstatuses.com/500',
|
|
183
|
+
'Internal Server Error',
|
|
184
|
+
500,
|
|
185
|
+
detail,
|
|
186
|
+
undefined,
|
|
187
|
+
extensions
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
class NotImplemented extends ProblemError {
|
|
193
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
194
|
+
super(
|
|
195
|
+
'https://httpstatuses.com/501',
|
|
196
|
+
'Not Implemented',
|
|
197
|
+
501,
|
|
198
|
+
detail,
|
|
199
|
+
undefined,
|
|
200
|
+
extensions
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
class BadGateway extends ProblemError {
|
|
206
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
207
|
+
super(
|
|
208
|
+
'https://httpstatuses.com/502',
|
|
209
|
+
'Bad Gateway',
|
|
210
|
+
502,
|
|
211
|
+
detail,
|
|
212
|
+
undefined,
|
|
213
|
+
extensions
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
class ServiceUnavailable extends ProblemError {
|
|
219
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
220
|
+
super(
|
|
221
|
+
'https://httpstatuses.com/503',
|
|
222
|
+
'Service Unavailable',
|
|
223
|
+
503,
|
|
224
|
+
detail,
|
|
225
|
+
undefined,
|
|
226
|
+
extensions
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
class GatewayTimeout extends ProblemError {
|
|
232
|
+
constructor(detail?: string, extensions?: Record<string, any>) {
|
|
233
|
+
super(
|
|
234
|
+
'https://httpstatuses.com/504',
|
|
235
|
+
'Gateway Timeout',
|
|
236
|
+
504,
|
|
237
|
+
detail,
|
|
238
|
+
undefined,
|
|
239
|
+
extensions
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export const HttpError = {
|
|
245
|
+
BadRequest,
|
|
246
|
+
Unauthorized,
|
|
247
|
+
PaymentRequired,
|
|
248
|
+
Forbidden,
|
|
249
|
+
NotFound,
|
|
250
|
+
MethodNotAllowed,
|
|
251
|
+
NotAcceptable,
|
|
252
|
+
Conflict,
|
|
253
|
+
InternalServerError,
|
|
254
|
+
NotImplemented,
|
|
255
|
+
BadGateway,
|
|
256
|
+
ServiceUnavailable,
|
|
257
|
+
GatewayTimeout
|
|
258
|
+
} as const
|
package/src/Error/type.ts
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
// src/libs/elysia-http-problem-json/types.ts
|
|
2
|
-
|
|
3
|
-
import { HttpError, ProblemError } from
|
|
4
|
-
|
|
5
|
-
export type Code =
|
|
6
|
-
| number
|
|
7
|
-
|
|
|
8
|
-
|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
16
|
-
// 获取 HttpError 对象的所有 Key (例如 "BadRequest" | "NotFound")
|
|
17
|
-
export type HttpErrorType = keyof typeof HttpError
|
|
18
|
-
|
|
19
|
-
export interface ErrorContext {
|
|
20
|
-
request: Request
|
|
21
|
-
path: string
|
|
22
|
-
code: string | number
|
|
23
|
-
error: unknown
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface HttpProblemJsonOptions {
|
|
27
|
-
/**
|
|
28
|
-
* 自定义错误类型的 Base URL
|
|
29
|
-
* @example "https://api.mysite.com/errors"
|
|
30
|
-
*/
|
|
31
|
-
typeBaseUrl?: string
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 🪝 Transform Hook
|
|
35
|
-
* 将未知错误转换为 HttpError。
|
|
36
|
-
* 返回 undefined/null 表示不处理(走默认逻辑)。
|
|
37
|
-
*/
|
|
38
|
-
transform?: (
|
|
39
|
-
error: unknown,
|
|
40
|
-
context: ErrorContext
|
|
41
|
-
) => ProblemError | undefined | null
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 📢 Listen Hook
|
|
45
|
-
* 在响应发送前触发(用于日志)。
|
|
46
|
-
*/
|
|
47
|
-
onBeforeRespond?: (
|
|
48
|
-
problem: ProblemError,
|
|
49
|
-
context: ErrorContext
|
|
50
|
-
) => void | Promise<void
|
|
51
|
-
}
|
|
1
|
+
// src/libs/elysia-http-problem-json/types.ts
|
|
2
|
+
|
|
3
|
+
import type { HttpError, ProblemError } from './errors'
|
|
4
|
+
|
|
5
|
+
export type Code =
|
|
6
|
+
| number
|
|
7
|
+
| 'PROBLEM_ERROR'
|
|
8
|
+
| 'UNKNOWN'
|
|
9
|
+
| 'VALIDATION'
|
|
10
|
+
| 'NOT_FOUND'
|
|
11
|
+
| 'PARSE'
|
|
12
|
+
| 'INTERNAL_SERVER_ERROR'
|
|
13
|
+
| 'INVALID_COOKIE_SIGNATURE'
|
|
14
|
+
| 'INVALID_FILE_TYPE'
|
|
15
|
+
|
|
16
|
+
// 获取 HttpError 对象的所有 Key (例如 "BadRequest" | "NotFound")
|
|
17
|
+
export type HttpErrorType = keyof typeof HttpError
|
|
18
|
+
|
|
19
|
+
export interface ErrorContext {
|
|
20
|
+
request: Request
|
|
21
|
+
path: string
|
|
22
|
+
code: string | number
|
|
23
|
+
error: unknown
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface HttpProblemJsonOptions {
|
|
27
|
+
/**
|
|
28
|
+
* 自定义错误类型的 Base URL
|
|
29
|
+
* @example "https://api.mysite.com/errors"
|
|
30
|
+
*/
|
|
31
|
+
typeBaseUrl?: string
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 🪝 Transform Hook
|
|
35
|
+
* 将未知错误转换为 HttpError。
|
|
36
|
+
* 返回 undefined/null 表示不处理(走默认逻辑)。
|
|
37
|
+
*/
|
|
38
|
+
transform?: (
|
|
39
|
+
error: unknown,
|
|
40
|
+
context: ErrorContext
|
|
41
|
+
) => ProblemError | undefined | null // 这里直接返回 ProblemError 实例更好,或者用 HttpErrorType 也可以,看你喜好
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 📢 Listen Hook
|
|
45
|
+
* 在响应发送前触发(用于日志)。
|
|
46
|
+
*/
|
|
47
|
+
onBeforeRespond?: (
|
|
48
|
+
problem: ProblemError,
|
|
49
|
+
context: ErrorContext
|
|
50
|
+
) => void | Promise<void>
|
|
51
|
+
}
|
package/src/extensions/banner.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import elysiaPkg from 'elysia/package.json'
|
|
2
|
-
|
|
3
|
-
const centerText = (text: string, width: number): string => {
|
|
4
|
-
if (text.length >= width) {
|
|
5
|
-
return text.slice(0, width)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const left = Math.floor((width - text.length) / 2)
|
|
9
|
-
const right = width - text.length - left
|
|
10
|
-
return `${' '.repeat(left)}${text}${' '.repeat(right)}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const renderBanner = (message: string): string => {
|
|
14
|
-
const versionLine = `Elysia v${elysiaPkg.version}`
|
|
15
|
-
const contentWidth = Math.max(message.length, versionLine.length)
|
|
16
|
-
const innerWidth = contentWidth + 4 // 2 spaces padding on both sides
|
|
17
|
-
|
|
18
|
-
const top = `┌${'─'.repeat(innerWidth)}┐`
|
|
19
|
-
const bot = `└${'─'.repeat(innerWidth)}┘`
|
|
20
|
-
const empty = `│${' '.repeat(innerWidth)}│`
|
|
21
|
-
|
|
22
|
-
const versionRow = `│${centerText(versionLine, innerWidth)}│`
|
|
23
|
-
const messageRow = `│ ${message}${' '.repeat(Math.max(0, innerWidth - message.length - 4))} │`
|
|
24
|
-
|
|
25
|
-
return [top, empty, versionRow, empty, messageRow, empty, bot].join('\n')
|
|
26
|
-
}
|
|
1
|
+
import elysiaPkg from 'elysia/package.json'
|
|
2
|
+
|
|
3
|
+
const centerText = (text: string, width: number): string => {
|
|
4
|
+
if (text.length >= width) {
|
|
5
|
+
return text.slice(0, width)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const left = Math.floor((width - text.length) / 2)
|
|
9
|
+
const right = width - text.length - left
|
|
10
|
+
return `${' '.repeat(left)}${text}${' '.repeat(right)}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const renderBanner = (message: string): string => {
|
|
14
|
+
const versionLine = `Elysia v${elysiaPkg.version}`
|
|
15
|
+
const contentWidth = Math.max(message.length, versionLine.length)
|
|
16
|
+
const innerWidth = contentWidth + 4 // 2 spaces padding on both sides
|
|
17
|
+
|
|
18
|
+
const top = `┌${'─'.repeat(innerWidth)}┐`
|
|
19
|
+
const bot = `└${'─'.repeat(innerWidth)}┘`
|
|
20
|
+
const empty = `│${' '.repeat(innerWidth)}│`
|
|
21
|
+
|
|
22
|
+
const versionRow = `│${centerText(versionLine, innerWidth)}│`
|
|
23
|
+
const messageRow = `│ ${message}${' '.repeat(Math.max(0, innerWidth - message.length - 4))} │`
|
|
24
|
+
|
|
25
|
+
return [top, empty, versionRow, empty, messageRow, empty, bot].join('\n')
|
|
26
|
+
}
|