hono-ban 0.2.4 → 0.2.6
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/esm/formatters/index.js +1 -0
- package/dist/esm/index.js +1 -311
- package/package.json +9 -24
- package/dist/cjs/formatters/rfc7807/index.js +0 -364
- package/dist/cjs/formatters/rfc7807/index.js.map +0 -16
- package/dist/cjs/index.js +0 -271
- package/dist/cjs/index.js.map +0 -16
- package/dist/esm/formatters/rfc7807/index.js +0 -333
- package/dist/esm/formatters/rfc7807/index.js.map +0 -16
- package/dist/esm/index.js.map +0 -16
- package/src/__tests__/core/convert-error.test.ts +0 -158
- package/src/__tests__/core/create-error.test.ts +0 -113
- package/src/__tests__/core/format-error.test.ts +0 -162
- package/src/__tests__/factories/factories.test.ts +0 -380
- package/src/__tests__/formatters/default-formatter.test.ts +0 -117
- package/src/__tests__/middleware/README.md +0 -49
- package/src/__tests__/middleware/ban-middleware.test.ts.disabled +0 -23
- package/src/__tests__/utils/sanitize.test.ts +0 -117
- package/src/__tests__/utils/validate.test.ts +0 -35
- package/src/constants/index.ts +0 -6
- package/src/constants/status-codes.ts +0 -52
- package/src/core/convert-error.ts +0 -74
- package/src/core/create-error.ts +0 -65
- package/src/core/format-error.ts +0 -76
- package/src/core/index.ts +0 -8
- package/src/factories/client-errors.ts +0 -492
- package/src/factories/index.ts +0 -7
- package/src/factories/server-errors.ts +0 -230
- package/src/formatters/default/index.ts +0 -72
- package/src/formatters/index.ts +0 -13
- package/src/formatters/interfaces.ts +0 -7
- package/src/formatters/rfc7807/formatter.ts +0 -105
- package/src/formatters/rfc7807/hooks.ts +0 -73
- package/src/formatters/rfc7807/index.ts +0 -20
- package/src/formatters/rfc7807/schemas.ts +0 -88
- package/src/index.ts +0 -23
- package/src/middleware/ban-middleware.ts +0 -77
- package/src/middleware/index.ts +0 -6
- package/src/types/common.ts +0 -14
- package/src/types/error.ts +0 -46
- package/src/types/formatter.ts +0 -61
- package/src/types/index.ts +0 -11
- package/src/types/options.ts +0 -71
- package/src/types/rfc7807.ts +0 -93
- package/src/utils/index.ts +0 -7
- package/src/utils/sanitize.ts +0 -34
- package/src/utils/validate.ts +0 -24
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import {
|
|
3
|
-
badRequest,
|
|
4
|
-
notFound,
|
|
5
|
-
unauthorized,
|
|
6
|
-
paymentRequired,
|
|
7
|
-
forbidden,
|
|
8
|
-
methodNotAllowed,
|
|
9
|
-
notAcceptable,
|
|
10
|
-
clientTimeout,
|
|
11
|
-
conflict,
|
|
12
|
-
resourceGone,
|
|
13
|
-
badData,
|
|
14
|
-
tooManyRequests,
|
|
15
|
-
teapot,
|
|
16
|
-
illegal,
|
|
17
|
-
lengthRequired,
|
|
18
|
-
preconditionFailed,
|
|
19
|
-
entityTooLarge,
|
|
20
|
-
uriTooLong,
|
|
21
|
-
unsupportedMediaType,
|
|
22
|
-
rangeNotSatisfiable,
|
|
23
|
-
expectationFailed,
|
|
24
|
-
} from "../../factories/client-errors";
|
|
25
|
-
import {
|
|
26
|
-
internal,
|
|
27
|
-
badImplementation,
|
|
28
|
-
serverUnavailable,
|
|
29
|
-
notImplemented,
|
|
30
|
-
badGateway,
|
|
31
|
-
gatewayTimeout,
|
|
32
|
-
httpVersionNotSupported,
|
|
33
|
-
insufficientStorage,
|
|
34
|
-
loopDetected,
|
|
35
|
-
variantAlsoNegotiates,
|
|
36
|
-
notExtended,
|
|
37
|
-
networkAuthRequired,
|
|
38
|
-
} from "../../factories/server-errors";
|
|
39
|
-
import { STATUS_CODES } from "../../constants";
|
|
40
|
-
|
|
41
|
-
describe("Error factories", () => {
|
|
42
|
-
describe("Client error factories", () => {
|
|
43
|
-
it("creates a 400 Bad Request error", () => {
|
|
44
|
-
const error = badRequest();
|
|
45
|
-
expect(error.status).toBe(400);
|
|
46
|
-
expect(error.message).toBe(STATUS_CODES[400]);
|
|
47
|
-
expect(error.isBan).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("creates a 401 Unauthorized error", () => {
|
|
51
|
-
const error = unauthorized();
|
|
52
|
-
expect(error.status).toBe(401);
|
|
53
|
-
expect(error.message).toBe(STATUS_CODES[401]);
|
|
54
|
-
expect(error.isBan).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("creates a 402 Payment Required error", () => {
|
|
58
|
-
const error = paymentRequired();
|
|
59
|
-
expect(error.status).toBe(402);
|
|
60
|
-
expect(error.message).toBe(STATUS_CODES[402]);
|
|
61
|
-
expect(error.isBan).toBe(true);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("creates a 403 Forbidden error", () => {
|
|
65
|
-
const error = forbidden();
|
|
66
|
-
expect(error.status).toBe(403);
|
|
67
|
-
expect(error.message).toBe(STATUS_CODES[403]);
|
|
68
|
-
expect(error.isBan).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("creates a 404 Not Found error", () => {
|
|
72
|
-
const error = notFound();
|
|
73
|
-
expect(error.status).toBe(404);
|
|
74
|
-
expect(error.message).toBe(STATUS_CODES[404]);
|
|
75
|
-
expect(error.isBan).toBe(true);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("creates a 405 Method Not Allowed error", () => {
|
|
79
|
-
const error = methodNotAllowed();
|
|
80
|
-
expect(error.status).toBe(405);
|
|
81
|
-
expect(error.message).toBe(STATUS_CODES[405]);
|
|
82
|
-
expect(error.isBan).toBe(true);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("creates a 406 Not Acceptable error", () => {
|
|
86
|
-
const error = notAcceptable();
|
|
87
|
-
expect(error.status).toBe(406);
|
|
88
|
-
expect(error.message).toBe(STATUS_CODES[406]);
|
|
89
|
-
expect(error.isBan).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("creates a 408 Request Timeout error", () => {
|
|
93
|
-
const error = clientTimeout();
|
|
94
|
-
expect(error.status).toBe(408);
|
|
95
|
-
expect(error.message).toBe(STATUS_CODES[408]);
|
|
96
|
-
expect(error.isBan).toBe(true);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it("creates a 409 Conflict error", () => {
|
|
100
|
-
const error = conflict();
|
|
101
|
-
expect(error.status).toBe(409);
|
|
102
|
-
expect(error.message).toBe(STATUS_CODES[409]);
|
|
103
|
-
expect(error.isBan).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("creates a 410 Gone error", () => {
|
|
107
|
-
const error = resourceGone();
|
|
108
|
-
expect(error.status).toBe(410);
|
|
109
|
-
expect(error.message).toBe(STATUS_CODES[410]);
|
|
110
|
-
expect(error.isBan).toBe(true);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("creates a 411 Length Required error", () => {
|
|
114
|
-
const error = lengthRequired();
|
|
115
|
-
expect(error.status).toBe(411);
|
|
116
|
-
expect(error.message).toBe(STATUS_CODES[411]);
|
|
117
|
-
expect(error.isBan).toBe(true);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("creates a 412 Precondition Failed error", () => {
|
|
121
|
-
const error = preconditionFailed();
|
|
122
|
-
expect(error.status).toBe(412);
|
|
123
|
-
expect(error.message).toBe(STATUS_CODES[412]);
|
|
124
|
-
expect(error.isBan).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("creates a 413 Payload Too Large error", () => {
|
|
128
|
-
const error = entityTooLarge();
|
|
129
|
-
expect(error.status).toBe(413);
|
|
130
|
-
expect(error.message).toBe(STATUS_CODES[413]);
|
|
131
|
-
expect(error.isBan).toBe(true);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("creates a 414 URI Too Long error", () => {
|
|
135
|
-
const error = uriTooLong();
|
|
136
|
-
expect(error.status).toBe(414);
|
|
137
|
-
expect(error.message).toBe(STATUS_CODES[414]);
|
|
138
|
-
expect(error.isBan).toBe(true);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("creates a 415 Unsupported Media Type error", () => {
|
|
142
|
-
const error = unsupportedMediaType();
|
|
143
|
-
expect(error.status).toBe(415);
|
|
144
|
-
expect(error.message).toBe(STATUS_CODES[415]);
|
|
145
|
-
expect(error.isBan).toBe(true);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("creates a 416 Range Not Satisfiable error", () => {
|
|
149
|
-
const error = rangeNotSatisfiable();
|
|
150
|
-
expect(error.status).toBe(416);
|
|
151
|
-
expect(error.message).toBe(STATUS_CODES[416]);
|
|
152
|
-
expect(error.isBan).toBe(true);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("creates a 417 Expectation Failed error", () => {
|
|
156
|
-
const error = expectationFailed();
|
|
157
|
-
expect(error.status).toBe(417);
|
|
158
|
-
expect(error.message).toBe(STATUS_CODES[417]);
|
|
159
|
-
expect(error.isBan).toBe(true);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it("creates a 418 I'm a Teapot error", () => {
|
|
163
|
-
const error = teapot();
|
|
164
|
-
expect(error.status).toBe(418);
|
|
165
|
-
expect(error.message).toBe(STATUS_CODES[418]);
|
|
166
|
-
expect(error.isBan).toBe(true);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it("creates a 422 Unprocessable Entity error", () => {
|
|
170
|
-
const error = badData();
|
|
171
|
-
expect(error.status).toBe(422);
|
|
172
|
-
expect(error.message).toBe(STATUS_CODES[422]);
|
|
173
|
-
expect(error.isBan).toBe(true);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("creates a 429 Too Many Requests error", () => {
|
|
177
|
-
const error = tooManyRequests();
|
|
178
|
-
expect(error.status).toBe(429);
|
|
179
|
-
expect(error.message).toBe(STATUS_CODES[429]);
|
|
180
|
-
expect(error.isBan).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("creates a 451 Unavailable For Legal Reasons error", () => {
|
|
184
|
-
const error = illegal();
|
|
185
|
-
expect(error.status).toBe(451);
|
|
186
|
-
expect(error.message).toBe(STATUS_CODES[451]);
|
|
187
|
-
expect(error.isBan).toBe(true);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it("accepts a custom message", () => {
|
|
191
|
-
const message = "Custom error message";
|
|
192
|
-
const error = unauthorized(message);
|
|
193
|
-
expect(error.status).toBe(401);
|
|
194
|
-
expect(error.message).toBe(message);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("accepts options object", () => {
|
|
198
|
-
const options = {
|
|
199
|
-
message: "Custom message",
|
|
200
|
-
data: { field: "test" },
|
|
201
|
-
headers: { "X-Custom": "value" },
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
const error = badRequest(options);
|
|
205
|
-
|
|
206
|
-
expect(error.status).toBe(400);
|
|
207
|
-
expect(error.message).toBe(options.message);
|
|
208
|
-
expect(error.data).toEqual(options.data);
|
|
209
|
-
expect(error.headers).toEqual(options.headers);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("accepts message and options separately", () => {
|
|
213
|
-
const message = "Custom message";
|
|
214
|
-
const options = {
|
|
215
|
-
data: { field: "test" },
|
|
216
|
-
headers: { "X-Custom": "value" },
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const error = notFound(message, options);
|
|
220
|
-
|
|
221
|
-
expect(error.status).toBe(404);
|
|
222
|
-
expect(error.message).toBe(message);
|
|
223
|
-
expect(error.data).toEqual(options.data);
|
|
224
|
-
expect(error.headers).toEqual(options.headers);
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe("Server error factories", () => {
|
|
229
|
-
it("creates a 500 Internal Server Error", () => {
|
|
230
|
-
const error = internal();
|
|
231
|
-
expect(error.status).toBe(500);
|
|
232
|
-
expect(error.message).toBe(STATUS_CODES[500]);
|
|
233
|
-
expect(error.isBan).toBe(true);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("creates a 501 Not Implemented error", () => {
|
|
237
|
-
const error = notImplemented();
|
|
238
|
-
expect(error.status).toBe(501);
|
|
239
|
-
expect(error.message).toBe(STATUS_CODES[501]);
|
|
240
|
-
expect(error.isBan).toBe(true);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("creates a 502 Bad Gateway error", () => {
|
|
244
|
-
const error = badGateway();
|
|
245
|
-
expect(error.status).toBe(502);
|
|
246
|
-
expect(error.message).toBe(STATUS_CODES[502]);
|
|
247
|
-
expect(error.isBan).toBe(true);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it("creates a 503 Service Unavailable error", () => {
|
|
251
|
-
const error = serverUnavailable();
|
|
252
|
-
expect(error.status).toBe(503);
|
|
253
|
-
expect(error.message).toBe(STATUS_CODES[503]);
|
|
254
|
-
expect(error.isBan).toBe(true);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it("creates a 504 Gateway Timeout error", () => {
|
|
258
|
-
const error = gatewayTimeout();
|
|
259
|
-
expect(error.status).toBe(504);
|
|
260
|
-
expect(error.message).toBe(STATUS_CODES[504]);
|
|
261
|
-
expect(error.isBan).toBe(true);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("creates a 505 HTTP Version Not Supported error", () => {
|
|
265
|
-
const error = httpVersionNotSupported();
|
|
266
|
-
expect(error.status).toBe(505);
|
|
267
|
-
expect(error.message).toBe(STATUS_CODES[505]);
|
|
268
|
-
expect(error.isBan).toBe(true);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("creates a 507 Insufficient Storage error", () => {
|
|
272
|
-
const error = insufficientStorage();
|
|
273
|
-
expect(error.status).toBe(507);
|
|
274
|
-
expect(error.message).toBe(STATUS_CODES[507]);
|
|
275
|
-
expect(error.isBan).toBe(true);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it("creates a 508 Loop Detected error", () => {
|
|
279
|
-
const error = loopDetected();
|
|
280
|
-
expect(error.status).toBe(508);
|
|
281
|
-
expect(error.message).toBe(STATUS_CODES[508]);
|
|
282
|
-
expect(error.isBan).toBe(true);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it("creates a 506 Variant Also Negotiates error", () => {
|
|
286
|
-
const error = variantAlsoNegotiates();
|
|
287
|
-
expect(error.status).toBe(506);
|
|
288
|
-
expect(error.message).toBe(STATUS_CODES[506]);
|
|
289
|
-
expect(error.isBan).toBe(true);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it("creates a 510 Not Extended error", () => {
|
|
293
|
-
const error = notExtended();
|
|
294
|
-
expect(error.status).toBe(510);
|
|
295
|
-
expect(error.message).toBe(STATUS_CODES[510]);
|
|
296
|
-
expect(error.isBan).toBe(true);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it("creates a 511 Network Authentication Required error", () => {
|
|
300
|
-
const error = networkAuthRequired();
|
|
301
|
-
expect(error.status).toBe(511);
|
|
302
|
-
expect(error.message).toBe(STATUS_CODES[511]);
|
|
303
|
-
expect(error.isBan).toBe(true);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("accepts a custom message", () => {
|
|
307
|
-
const message = "Custom error message";
|
|
308
|
-
const error = internal(message);
|
|
309
|
-
expect(error.status).toBe(500);
|
|
310
|
-
expect(error.message).toBe(message);
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it("accepts options object", () => {
|
|
314
|
-
const options = {
|
|
315
|
-
message: "Custom message",
|
|
316
|
-
data: { field: "test" },
|
|
317
|
-
headers: { "X-Custom": "value" },
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const error = serverUnavailable(options);
|
|
321
|
-
|
|
322
|
-
expect(error.status).toBe(503);
|
|
323
|
-
expect(error.message).toBe(options.message);
|
|
324
|
-
expect(error.data).toEqual(options.data);
|
|
325
|
-
expect(error.headers).toEqual(options.headers);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it("accepts message and options separately", () => {
|
|
329
|
-
const message = "Custom message";
|
|
330
|
-
const options = {
|
|
331
|
-
data: { field: "test" },
|
|
332
|
-
headers: { "X-Custom": "value" },
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
const error = internal(message, options);
|
|
336
|
-
|
|
337
|
-
expect(error.status).toBe(500);
|
|
338
|
-
expect(error.message).toBe(message);
|
|
339
|
-
expect(error.data).toEqual(options.data);
|
|
340
|
-
expect(error.headers).toEqual(options.headers);
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
describe("badImplementation", () => {
|
|
345
|
-
it("creates a developer error", () => {
|
|
346
|
-
const error = badImplementation();
|
|
347
|
-
|
|
348
|
-
expect(error.status).toBe(500);
|
|
349
|
-
expect(error.message).toBe(STATUS_CODES[500]);
|
|
350
|
-
expect(error.data).toEqual({ isDeveloperError: true });
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it("merges custom data with isDeveloperError flag", () => {
|
|
354
|
-
const error = badImplementation({
|
|
355
|
-
data: { field: "test" },
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
// Use type assertion to check the data structure
|
|
359
|
-
const data = error.data as { isDeveloperError: boolean; field: string };
|
|
360
|
-
expect(data.isDeveloperError).toBe(true);
|
|
361
|
-
expect(data.field).toBe("test");
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
it("accepts message and options separately", () => {
|
|
365
|
-
const message = "Developer error";
|
|
366
|
-
const options = {
|
|
367
|
-
data: { field: "test" },
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
const error = badImplementation(message, options);
|
|
371
|
-
|
|
372
|
-
expect(error.status).toBe(500);
|
|
373
|
-
expect(error.message).toBe(message);
|
|
374
|
-
// Use type assertion to check the data structure
|
|
375
|
-
const data = error.data as { isDeveloperError: boolean; field: string };
|
|
376
|
-
expect(data.isDeveloperError).toBe(true);
|
|
377
|
-
expect(data.field).toBe("test");
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
});
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import { defaultFormatter } from "../../formatters/default";
|
|
3
|
-
import { createError } from "../../core/create-error";
|
|
4
|
-
import { STATUS_CODES } from "../../constants";
|
|
5
|
-
|
|
6
|
-
describe("defaultFormatter", () => {
|
|
7
|
-
it("has the correct content type", () => {
|
|
8
|
-
expect(defaultFormatter.contentType).toBe("application/json");
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("formats a basic error", () => {
|
|
12
|
-
const error = createError({ statusCode: 404, message: "Not found" });
|
|
13
|
-
const formatted = defaultFormatter.format(error);
|
|
14
|
-
|
|
15
|
-
expect(formatted).toEqual({
|
|
16
|
-
statusCode: 404,
|
|
17
|
-
payload: {
|
|
18
|
-
statusCode: 404,
|
|
19
|
-
error: STATUS_CODES[404],
|
|
20
|
-
message: "Not found",
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("passes custom headers to the formatter but doesn't include them in output", () => {
|
|
26
|
-
const error = createError({ statusCode: 400 });
|
|
27
|
-
const headers = { "X-Custom": "value" };
|
|
28
|
-
|
|
29
|
-
const formatted = defaultFormatter.format(error, headers);
|
|
30
|
-
|
|
31
|
-
// Headers should not be in the formatted output
|
|
32
|
-
expect((formatted as any).headers).toBeUndefined();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("doesn't add the Allow header to the response body", () => {
|
|
36
|
-
const error = createError({
|
|
37
|
-
statusCode: 405,
|
|
38
|
-
allow: ["GET", "POST"],
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const formatted = defaultFormatter.format(error);
|
|
42
|
-
|
|
43
|
-
// The formatted output should not have headers
|
|
44
|
-
expect((formatted as any).headers).toBeUndefined();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("includes stack trace when includeStackTrace is true", () => {
|
|
48
|
-
const error = createError({ statusCode: 500 });
|
|
49
|
-
const formatted = defaultFormatter.format(error, {}, [], true);
|
|
50
|
-
|
|
51
|
-
expect(formatted.payload.stack).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("includes stack trace for developer errors", () => {
|
|
55
|
-
const error = createError({
|
|
56
|
-
statusCode: 500,
|
|
57
|
-
data: { isDeveloperError: true },
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const formatted = defaultFormatter.format(error);
|
|
61
|
-
|
|
62
|
-
expect(formatted.payload.stack).toBeDefined();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("includes cause stack when available", () => {
|
|
66
|
-
const cause = new Error("Original error");
|
|
67
|
-
const error = createError({
|
|
68
|
-
statusCode: 500,
|
|
69
|
-
cause,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const formatted = defaultFormatter.format(error, {}, [], true);
|
|
73
|
-
|
|
74
|
-
expect(formatted.payload.causeStack).toBeDefined();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("includes error data when provided", () => {
|
|
78
|
-
const data = { field: "email", reason: "invalid format" };
|
|
79
|
-
const error = createError({
|
|
80
|
-
statusCode: 400,
|
|
81
|
-
data,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const formatted = defaultFormatter.format(error);
|
|
85
|
-
|
|
86
|
-
expect(formatted.payload.data).toEqual(data);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("sanitizes specified fields", () => {
|
|
90
|
-
const data = {
|
|
91
|
-
user: {
|
|
92
|
-
id: 123,
|
|
93
|
-
password: "secret",
|
|
94
|
-
email: "user@example.com",
|
|
95
|
-
profile: {
|
|
96
|
-
token: "abc123",
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const error = createError({
|
|
102
|
-
statusCode: 400,
|
|
103
|
-
data,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const formatted = defaultFormatter.format(error, {}, ["password", "token"]);
|
|
107
|
-
|
|
108
|
-
// Data should be sanitized
|
|
109
|
-
expect(formatted.payload.data).toEqual({
|
|
110
|
-
user: {
|
|
111
|
-
id: 123,
|
|
112
|
-
email: "user@example.com",
|
|
113
|
-
profile: {},
|
|
114
|
-
},
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Middleware Tests
|
|
2
|
-
|
|
3
|
-
## Ban Middleware Tests
|
|
4
|
-
|
|
5
|
-
The tests for the `ban-middleware.ts` file are currently disabled (renamed to `ban-middleware.test.ts.disabled`) due to a known issue with Bun's testing framework. There's a bug related to mocking in Bun that causes errors when testing middleware.
|
|
6
|
-
|
|
7
|
-
### Error Details
|
|
8
|
-
|
|
9
|
-
When running the middleware tests, the following error occurs:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
# Unhandled error between tests
|
|
13
|
-
-------------------------------
|
|
14
|
-
1 | (function (entry fetcher)
|
|
15
|
-
^
|
|
16
|
-
SyntaxError: export 'ErrorFormatter' not found in '../types'
|
|
17
|
-
-------------------------------
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Possible Workarounds
|
|
21
|
-
|
|
22
|
-
For future implementation, consider these workarounds:
|
|
23
|
-
|
|
24
|
-
- Using [bun-bagel](https://github.com/DRFR0ST/bun-bagel)
|
|
25
|
-
- Using [bun-mock-fetch](https://github.com/aryzing/bun-mock-fetch)
|
|
26
|
-
- Using `spyOn` for global.fetch:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
const mockFetch = spyOn(globalThis, "fetch");
|
|
30
|
-
|
|
31
|
-
beforeEach(() => {
|
|
32
|
-
mockFetch.mockReset();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
afterAll(() => {
|
|
36
|
-
mockFetch.mockRestore();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("fetches example.com", () => {
|
|
40
|
-
mockFetch.mockImplementation(async (url, opts) => {
|
|
41
|
-
// Test implementation
|
|
42
|
-
return new Response('{"success":true}');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Test code
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
These tests should be re-enabled when the Bun testing framework is more stable.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import { ban } from "../../middleware/ban-middleware";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* NOTE: Full middleware tests are currently disabled due to a known issue with Bun's testing framework.
|
|
6
|
-
* There's a bug related to mocking in Bun that causes errors when testing middleware.
|
|
7
|
-
*
|
|
8
|
-
* Possible workarounds for future implementation include:
|
|
9
|
-
* - Using bun-bagel: https://github.com/DRFR0ST/bun-bagel
|
|
10
|
-
* - Using bun-mock-fetch: https://github.com/aryzing/bun-mock-fetch
|
|
11
|
-
* - Using spyOn for global.fetch
|
|
12
|
-
*
|
|
13
|
-
* These tests should be expanded when the Bun testing framework is more stable.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
describe("ban middleware", () => {
|
|
17
|
-
it("exports a function", () => {
|
|
18
|
-
expect(typeof ban).toBe("function");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// Additional tests are disabled due to Bun testing framework issues
|
|
22
|
-
// See the note above for more information
|
|
23
|
-
});
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import { sanitizeObject } from "../../utils/sanitize";
|
|
3
|
-
|
|
4
|
-
describe("sanitizeObject", () => {
|
|
5
|
-
it("returns the original object if no keys to remove", () => {
|
|
6
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
7
|
-
expect(sanitizeObject(obj, [])).toBe(obj);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it("removes specified keys from a simple object", () => {
|
|
11
|
-
const obj = { a: 1, b: 2, c: 3, password: "secret" };
|
|
12
|
-
const result = sanitizeObject(obj, ["password"]) as Record<string, unknown>;
|
|
13
|
-
|
|
14
|
-
expect(result).toEqual({ a: 1, b: 2, c: 3 });
|
|
15
|
-
expect("password" in result).toBe(false);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("removes multiple specified keys", () => {
|
|
19
|
-
const obj = {
|
|
20
|
-
a: 1,
|
|
21
|
-
password: "secret",
|
|
22
|
-
token: "abc123",
|
|
23
|
-
username: "user",
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const result = sanitizeObject(obj, ["password", "token"]) as Record<
|
|
27
|
-
string,
|
|
28
|
-
unknown
|
|
29
|
-
>;
|
|
30
|
-
|
|
31
|
-
expect(result).toEqual({ a: 1, username: "user" });
|
|
32
|
-
expect("password" in result).toBe(false);
|
|
33
|
-
expect("token" in result).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("handles nested objects", () => {
|
|
37
|
-
const obj = {
|
|
38
|
-
user: {
|
|
39
|
-
name: "John",
|
|
40
|
-
password: "secret",
|
|
41
|
-
profile: {
|
|
42
|
-
bio: "Developer",
|
|
43
|
-
token: "xyz789",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
settings: {
|
|
47
|
-
theme: "dark",
|
|
48
|
-
token: "abc123",
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const result = sanitizeObject(obj, ["password", "token"]);
|
|
53
|
-
|
|
54
|
-
expect(result).toEqual({
|
|
55
|
-
user: {
|
|
56
|
-
name: "John",
|
|
57
|
-
profile: {
|
|
58
|
-
bio: "Developer",
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
settings: {
|
|
62
|
-
theme: "dark",
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("handles arrays", () => {
|
|
68
|
-
const arr = [
|
|
69
|
-
{ id: 1, name: "Item 1", token: "abc" },
|
|
70
|
-
{ id: 2, name: "Item 2", password: "secret" },
|
|
71
|
-
{ id: 3, name: "Item 3" },
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
const result = sanitizeObject(arr, ["token", "password"]);
|
|
75
|
-
|
|
76
|
-
expect(result).toEqual([
|
|
77
|
-
{ id: 1, name: "Item 1" },
|
|
78
|
-
{ id: 2, name: "Item 2" },
|
|
79
|
-
{ id: 3, name: "Item 3" },
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("handles arrays within objects", () => {
|
|
84
|
-
const obj = {
|
|
85
|
-
users: [
|
|
86
|
-
{ id: 1, name: "User 1", password: "pass1" },
|
|
87
|
-
{ id: 2, name: "User 2", password: "pass2" },
|
|
88
|
-
],
|
|
89
|
-
settings: { token: "abc123" },
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const result = sanitizeObject(obj, ["password", "token"]);
|
|
93
|
-
|
|
94
|
-
expect(result).toEqual({
|
|
95
|
-
users: [
|
|
96
|
-
{ id: 1, name: "User 1" },
|
|
97
|
-
{ id: 2, name: "User 2" },
|
|
98
|
-
],
|
|
99
|
-
settings: {},
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("handles primitive values", () => {
|
|
104
|
-
expect(sanitizeObject("string", ["key"])).toBe("string");
|
|
105
|
-
expect(sanitizeObject(123, ["key"])).toBe(123);
|
|
106
|
-
expect(sanitizeObject(true, ["key"])).toBe(true);
|
|
107
|
-
expect(sanitizeObject(null, ["key"])).toBe(null);
|
|
108
|
-
expect(sanitizeObject(undefined, ["key"])).toBe(undefined);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("returns empty object when all keys are removed", () => {
|
|
112
|
-
const obj = { password: "secret", token: "abc123" };
|
|
113
|
-
const result = sanitizeObject(obj, ["password", "token"]);
|
|
114
|
-
|
|
115
|
-
expect(result).toEqual({});
|
|
116
|
-
});
|
|
117
|
-
});
|