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.
Files changed (47) hide show
  1. package/dist/esm/formatters/index.js +1 -0
  2. package/dist/esm/index.js +1 -311
  3. package/package.json +9 -24
  4. package/dist/cjs/formatters/rfc7807/index.js +0 -364
  5. package/dist/cjs/formatters/rfc7807/index.js.map +0 -16
  6. package/dist/cjs/index.js +0 -271
  7. package/dist/cjs/index.js.map +0 -16
  8. package/dist/esm/formatters/rfc7807/index.js +0 -333
  9. package/dist/esm/formatters/rfc7807/index.js.map +0 -16
  10. package/dist/esm/index.js.map +0 -16
  11. package/src/__tests__/core/convert-error.test.ts +0 -158
  12. package/src/__tests__/core/create-error.test.ts +0 -113
  13. package/src/__tests__/core/format-error.test.ts +0 -162
  14. package/src/__tests__/factories/factories.test.ts +0 -380
  15. package/src/__tests__/formatters/default-formatter.test.ts +0 -117
  16. package/src/__tests__/middleware/README.md +0 -49
  17. package/src/__tests__/middleware/ban-middleware.test.ts.disabled +0 -23
  18. package/src/__tests__/utils/sanitize.test.ts +0 -117
  19. package/src/__tests__/utils/validate.test.ts +0 -35
  20. package/src/constants/index.ts +0 -6
  21. package/src/constants/status-codes.ts +0 -52
  22. package/src/core/convert-error.ts +0 -74
  23. package/src/core/create-error.ts +0 -65
  24. package/src/core/format-error.ts +0 -76
  25. package/src/core/index.ts +0 -8
  26. package/src/factories/client-errors.ts +0 -492
  27. package/src/factories/index.ts +0 -7
  28. package/src/factories/server-errors.ts +0 -230
  29. package/src/formatters/default/index.ts +0 -72
  30. package/src/formatters/index.ts +0 -13
  31. package/src/formatters/interfaces.ts +0 -7
  32. package/src/formatters/rfc7807/formatter.ts +0 -105
  33. package/src/formatters/rfc7807/hooks.ts +0 -73
  34. package/src/formatters/rfc7807/index.ts +0 -20
  35. package/src/formatters/rfc7807/schemas.ts +0 -88
  36. package/src/index.ts +0 -23
  37. package/src/middleware/ban-middleware.ts +0 -77
  38. package/src/middleware/index.ts +0 -6
  39. package/src/types/common.ts +0 -14
  40. package/src/types/error.ts +0 -46
  41. package/src/types/formatter.ts +0 -61
  42. package/src/types/index.ts +0 -11
  43. package/src/types/options.ts +0 -71
  44. package/src/types/rfc7807.ts +0 -93
  45. package/src/utils/index.ts +0 -7
  46. package/src/utils/sanitize.ts +0 -34
  47. package/src/utils/validate.ts +0 -24
@@ -1,230 +0,0 @@
1
- /**
2
- * Server error factory functions (5xx)
3
- * @module hono-ban/factories/server-errors
4
- */
5
-
6
- import type { BanError, BanOptions, ErrorStatusCode } from "../types";
7
- import { createError } from "../core";
8
-
9
- /**
10
- * Helper function to reduce duplication
11
- * @param statusCode - HTTP status code
12
- * @param messageOrOptions - Error message or options
13
- * @param options - Additional options
14
- */
15
- function createErrorWithStatus<T>(
16
- statusCode: ErrorStatusCode,
17
- messageOrOptions?: string | Partial<BanOptions<T>>,
18
- options?: Partial<BanOptions<T>>
19
- ): BanError<T> {
20
- if (typeof messageOrOptions === "string") {
21
- return createError<T>({
22
- ...options,
23
- statusCode,
24
- message: messageOrOptions,
25
- });
26
- }
27
- return createError<T>({ ...messageOrOptions, ...options, statusCode });
28
- }
29
-
30
- /**
31
- * Create a 500 Internal Server Error
32
- * @param messageOrOptions - Error message or options
33
- * @param options - Additional options
34
- */
35
- export function internal<T = unknown>(
36
- messageOrOptions?: string | Partial<BanOptions<T>>,
37
- options?: Partial<BanOptions<T>>
38
- ): BanError<T> {
39
- return createErrorWithStatus(
40
- 500 as ErrorStatusCode,
41
- messageOrOptions,
42
- options
43
- );
44
- }
45
-
46
- /**
47
- * Create a 501 Not Implemented error
48
- * @param messageOrOptions - Error message or options
49
- * @param options - Additional options
50
- */
51
- export function notImplemented<T = unknown>(
52
- messageOrOptions?: string | Partial<BanOptions<T>>,
53
- options?: Partial<BanOptions<T>>
54
- ): BanError<T> {
55
- return createErrorWithStatus(
56
- 501 as ErrorStatusCode,
57
- messageOrOptions,
58
- options
59
- );
60
- }
61
-
62
- /**
63
- * Create a 502 Bad Gateway error
64
- * @param messageOrOptions - Error message or options
65
- * @param options - Additional options
66
- */
67
- export function badGateway<T = unknown>(
68
- messageOrOptions?: string | Partial<BanOptions<T>>,
69
- options?: Partial<BanOptions<T>>
70
- ): BanError<T> {
71
- return createErrorWithStatus(
72
- 502 as ErrorStatusCode,
73
- messageOrOptions,
74
- options
75
- );
76
- }
77
-
78
- /**
79
- * Create a 503 Service Unavailable error
80
- * @param messageOrOptions - Error message or options
81
- * @param options - Additional options
82
- */
83
- export function serverUnavailable<T = unknown>(
84
- messageOrOptions?: string | Partial<BanOptions<T>>,
85
- options?: Partial<BanOptions<T>>
86
- ): BanError<T> {
87
- return createErrorWithStatus(
88
- 503 as ErrorStatusCode,
89
- messageOrOptions,
90
- options
91
- );
92
- }
93
-
94
- /**
95
- * Create a 504 Gateway Timeout error
96
- * @param messageOrOptions - Error message or options
97
- * @param options - Additional options
98
- */
99
- export function gatewayTimeout<T = unknown>(
100
- messageOrOptions?: string | Partial<BanOptions<T>>,
101
- options?: Partial<BanOptions<T>>
102
- ): BanError<T> {
103
- return createErrorWithStatus(
104
- 504 as ErrorStatusCode,
105
- messageOrOptions,
106
- options
107
- );
108
- }
109
-
110
- /**
111
- * Create a 505 HTTP Version Not Supported error
112
- * @param messageOrOptions - Error message or options
113
- * @param options - Additional options
114
- */
115
- export function httpVersionNotSupported<T = unknown>(
116
- messageOrOptions?: string | Partial<BanOptions<T>>,
117
- options?: Partial<BanOptions<T>>
118
- ): BanError<T> {
119
- return createErrorWithStatus(
120
- 505 as ErrorStatusCode,
121
- messageOrOptions,
122
- options
123
- );
124
- }
125
-
126
- /**
127
- * Create a 506 Variant Also Negotiates error
128
- * @param messageOrOptions - Error message or options
129
- * @param options - Additional options
130
- */
131
- export function variantAlsoNegotiates<T = unknown>(
132
- messageOrOptions?: string | Partial<BanOptions<T>>,
133
- options?: Partial<BanOptions<T>>
134
- ): BanError<T> {
135
- return createErrorWithStatus(
136
- 506 as ErrorStatusCode,
137
- messageOrOptions,
138
- options
139
- );
140
- }
141
-
142
- /**
143
- * Create a 507 Insufficient Storage error
144
- * @param messageOrOptions - Error message or options
145
- * @param options - Additional options
146
- */
147
- export function insufficientStorage<T = unknown>(
148
- messageOrOptions?: string | Partial<BanOptions<T>>,
149
- options?: Partial<BanOptions<T>>
150
- ): BanError<T> {
151
- return createErrorWithStatus(
152
- 507 as ErrorStatusCode,
153
- messageOrOptions,
154
- options
155
- );
156
- }
157
-
158
- /**
159
- * Create a 508 Loop Detected error
160
- * @param messageOrOptions - Error message or options
161
- * @param options - Additional options
162
- */
163
- export function loopDetected<T = unknown>(
164
- messageOrOptions?: string | Partial<BanOptions<T>>,
165
- options?: Partial<BanOptions<T>>
166
- ): BanError<T> {
167
- return createErrorWithStatus(
168
- 508 as ErrorStatusCode,
169
- messageOrOptions,
170
- options
171
- );
172
- }
173
-
174
- /**
175
- * Create a 510 Not Extended error
176
- * @param messageOrOptions - Error message or options
177
- * @param options - Additional options
178
- */
179
- export function notExtended<T = unknown>(
180
- messageOrOptions?: string | Partial<BanOptions<T>>,
181
- options?: Partial<BanOptions<T>>
182
- ): BanError<T> {
183
- return createErrorWithStatus(
184
- 510 as ErrorStatusCode,
185
- messageOrOptions,
186
- options
187
- );
188
- }
189
-
190
- /**
191
- * Create a 511 Network Authentication Required error
192
- * @param messageOrOptions - Error message or options
193
- * @param options - Additional options
194
- */
195
- export function networkAuthRequired<T = unknown>(
196
- messageOrOptions?: string | Partial<BanOptions<T>>,
197
- options?: Partial<BanOptions<T>>
198
- ): BanError<T> {
199
- return createErrorWithStatus(
200
- 511 as ErrorStatusCode,
201
- messageOrOptions,
202
- options
203
- );
204
- }
205
-
206
- /**
207
- * Create a 500 Internal Server Error marked as a developer error
208
- * @param messageOrOptions - Error message or options
209
- * @param options - Additional options
210
- */
211
- export function badImplementation<T = unknown>(
212
- messageOrOptions?: string | Partial<BanOptions<T>>,
213
- options?: Partial<BanOptions<T>>
214
- ): BanError<T> {
215
- const mergedOptions =
216
- typeof messageOrOptions === "string"
217
- ? { ...options, message: messageOrOptions }
218
- : { ...messageOrOptions, ...options };
219
-
220
- const mergedData = {
221
- isDeveloperError: true,
222
- ...((mergedOptions.data as Record<string, unknown>) || {}),
223
- } as unknown as T;
224
-
225
- return createError<T>({
226
- ...mergedOptions,
227
- statusCode: 500 as ErrorStatusCode,
228
- data: mergedData,
229
- });
230
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * Default error formatter implementation
3
- * @module hono-ban/formatters/default
4
- */
5
-
6
- import { STATUS_CODES } from "../../constants";
7
- import type { BanError, DefaultErrorOutput, Headers } from "../../types";
8
- import { sanitizeObject } from "../../utils";
9
-
10
- /**
11
- * Default JSON formatter maintaining backward compatibility
12
- */
13
- export const defaultFormatter = {
14
- contentType: "application/json",
15
-
16
- /**
17
- * Format an error into a standardized output structure
18
- * @param error - Error to format
19
- * @param headers - Headers for HTTP response (not included in response body)
20
- * @param sanitize - Fields to remove from output
21
- * @param includeStackTrace - Whether to include stack traces
22
- */
23
- format(
24
- error: BanError,
25
- headers: Headers = {}, // Headers are used for HTTP headers, not included in response body
26
- sanitize: readonly string[] = [],
27
- includeStackTrace = false
28
- ): DefaultErrorOutput {
29
- const { status, message, data } = error;
30
-
31
- // Build base payload
32
- const payload: DefaultErrorOutput["payload"] = {
33
- statusCode: status,
34
- error: STATUS_CODES[status] || "Unknown Error",
35
- };
36
-
37
- // Add optional fields
38
- if (typeof message === "string") {
39
- payload.message = message;
40
- }
41
-
42
- const isDeveloperError =
43
- data &&
44
- typeof data === "object" &&
45
- "isDeveloperError" in data &&
46
- data.isDeveloperError === true;
47
-
48
- if (includeStackTrace || isDeveloperError) {
49
- if (error.stack) {
50
- payload.stack = error.stack;
51
- }
52
- if (error.causeStack) {
53
- payload.causeStack = error.causeStack;
54
- }
55
- }
56
-
57
- if (data !== undefined) {
58
- payload.data = data;
59
- }
60
-
61
- // Create output structure
62
- const output: DefaultErrorOutput = {
63
- statusCode: status,
64
- payload: sanitizeObject(
65
- payload,
66
- sanitize
67
- ) as DefaultErrorOutput["payload"],
68
- };
69
-
70
- return output;
71
- },
72
- };
@@ -1,13 +0,0 @@
1
- /**
2
- * Formatters exports
3
- * @module hono-ban/formatters
4
- */
5
-
6
- // Export formatter interfaces
7
- export * from "./interfaces";
8
-
9
- // Export default formatter
10
- export * from "./default";
11
-
12
- // Export RFC7807 formatter
13
- export * from "./rfc7807";
@@ -1,7 +0,0 @@
1
- /**
2
- * Formatter interfaces
3
- * @module hono-ban/formatters/interfaces
4
- */
5
-
6
- // Re-export formatter interfaces from types
7
- export { ErrorFormatter, DefaultErrorOutput } from "../types";
@@ -1,105 +0,0 @@
1
- /**
2
- * RFC 7807 Problem Details formatter implementation
3
- * @module hono-ban/formatters/rfc7807/formatter
4
- */
5
-
6
- import { z } from "@hono/zod-openapi";
7
- import { STATUS_CODES } from "../../constants";
8
- import type { BanError, ErrorFormatter } from "../../types";
9
- import type {
10
- RFC7807Details,
11
- RFC7807ErrorData,
12
- RFC7807ValidationParam,
13
- RFC7807FormatterOptions as RFC7807Options,
14
- } from "../../types";
15
- import {
16
- RFC7807ConstraintViolationSchema,
17
- RFC7807DetailsSchema,
18
- RFC7807ValidationParamSchema,
19
- } from "./schemas";
20
-
21
- /**
22
- * Create an RFC 7807 Problem Details formatter
23
- */
24
- export function createRFC7807Formatter(
25
- options: RFC7807Options = {}
26
- ): ErrorFormatter {
27
- const baseUrl = options.baseUrl || "https://api.example.com/problems";
28
-
29
- return {
30
- contentType: "application/problem+json",
31
-
32
- format<T extends RFC7807ErrorData>(error: BanError<T>): RFC7807Details {
33
- const base = {
34
- type: `${baseUrl}/${error.status}`,
35
- title: STATUS_CODES[error.status] || "Unknown Error",
36
- status: error.status,
37
- detail: error.message,
38
- instance: `urn:uuid:${crypto.randomUUID()}`,
39
- timestamp: new Date().toISOString(),
40
- };
41
-
42
- // Handle validation errors
43
- if (error.data?.["invalid-params"]) {
44
- return RFC7807DetailsSchema.parse({
45
- ...base,
46
- "invalid-params": error.data["invalid-params"],
47
- });
48
- }
49
-
50
- // Handle constraint violations
51
- if (error.data?.violations) {
52
- return RFC7807DetailsSchema.parse({
53
- ...base,
54
- violations: error.data.violations,
55
- });
56
- }
57
-
58
- return RFC7807DetailsSchema.parse(base);
59
- },
60
- };
61
- }
62
-
63
- /**
64
- * Create validation error data in RFC 7807 format
65
- */
66
- export function createRFC7807ValidationError(params: RFC7807ValidationParam[]) {
67
- return {
68
- "invalid-params": RFC7807ValidationParamSchema.array().parse(params),
69
- };
70
- }
71
-
72
- /**
73
- * Convert Zod validation errors to RFC 7807 format
74
- */
75
- export function createRFC7807ZodValidationError(error: z.ZodError) {
76
- return {
77
- "invalid-params": RFC7807ValidationParamSchema.array().parse(
78
- error.errors.map((e) => ({
79
- name: e.path.join("."),
80
- reason: e.message,
81
- }))
82
- ),
83
- };
84
- }
85
-
86
- /**
87
- * Create constraint violation data in RFC 7807 format
88
- */
89
- export function createRFC7807ConstraintViolation(
90
- name: string,
91
- reason: string,
92
- resource: string,
93
- constraint: string = "unique"
94
- ) {
95
- return {
96
- violations: RFC7807ConstraintViolationSchema.array().parse([
97
- {
98
- name,
99
- reason,
100
- resource,
101
- constraint,
102
- },
103
- ]),
104
- };
105
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * RFC 7807 Problem Details hooks for Hono applications
3
- * @module hono-ban/formatters/rfc7807/hooks
4
- */
5
-
6
- import { ZodError } from "zod";
7
- import { Hook } from "@hono/zod-openapi";
8
- import { Env } from "hono";
9
- import { badRequest } from "../../factories";
10
- import type {
11
- RFC7807FormatterOptions as RFC7807Options,
12
- BanOptions,
13
- } from "../../types";
14
- import { createRFC7807ZodValidationError } from "./formatter";
15
-
16
- /**
17
- * Create a Hono hook that formats validation errors using RFC 7807
18
- *
19
- * This hook throws a badRequest error that will be caught and processed by the ban middleware.
20
- * You can provide options to override the default behavior of the middleware.
21
- *
22
- * @example
23
- * // Basic usage - inherits all settings from middleware
24
- * app.openapi(route, handler, { onError: createRFC7807Hook() });
25
- *
26
- * @example
27
- * // With custom message
28
- * app.openapi(route, handler, {
29
- * onError: createRFC7807Hook({ message: "Custom validation error" })
30
- * });
31
- *
32
- * @example
33
- * // With custom formatter and sanitization
34
- * app.openapi(route, handler, {
35
- * onError: createRFC7807Hook({
36
- * formatter: customFormatter,
37
- * sanitize: ['password', 'token']
38
- * })
39
- * });
40
- */
41
- export function createRFC7807Hook<E extends Env = Env>(
42
- options?: RFC7807Options & Partial<BanOptions>
43
- ): Hook<any, E, any, any> {
44
- return (result, c) => {
45
- if (
46
- !result.success &&
47
- "error" in result &&
48
- result.error instanceof ZodError
49
- ) {
50
- // Create the validation error data
51
- const validationData = createRFC7807ZodValidationError(result.error);
52
-
53
- // Throw badRequest with both the validation data and any override options
54
- throw badRequest({
55
- message: options?.message || "Validation Error",
56
- data: validationData,
57
- // Pass through any override options
58
- formatter: options?.formatter,
59
- headers: options?.headers,
60
- sanitize: options?.sanitize,
61
- includeStackTrace: options?.includeStackTrace,
62
- });
63
- }
64
- };
65
- }
66
-
67
- /**
68
- * Pre-configured RFC 7807 hook with default options
69
- *
70
- * This is a convenience export that uses the default options.
71
- * It will throw a badRequest error that will be caught and processed by the ban middleware.
72
- */
73
- export const rfc7807Hook = createRFC7807Hook<Env>();
@@ -1,20 +0,0 @@
1
- /**
2
- * RFC 7807 Problem Details implementation for Hono Ban
3
- * @module hono-ban/formatters/rfc7807
4
- */
5
-
6
- export {
7
- createRFC7807Formatter,
8
- createRFC7807ValidationError,
9
- createRFC7807ZodValidationError,
10
- createRFC7807ConstraintViolation,
11
- } from "./formatter";
12
-
13
- export { createRFC7807Hook, rfc7807Hook } from "./hooks";
14
-
15
- export {
16
- RFC7807ValidationParamSchema,
17
- RFC7807ConstraintViolationSchema,
18
- RFC7807ErrorDataSchema,
19
- RFC7807DetailsSchema,
20
- } from "./schemas";
@@ -1,88 +0,0 @@
1
- /**
2
- * Zod schemas for RFC 7807 Problem Details
3
- * @module hono-ban/formatters/rfc7807/schemas
4
- */
5
-
6
- import { z } from "@hono/zod-openapi";
7
-
8
- /**
9
- * Schema for RFC 7807 validation error parameters
10
- */
11
- export const RFC7807ValidationParamSchema = z.object({
12
- name: z.string().openapi({
13
- example: "username",
14
- description: "The field name that failed validation",
15
- }),
16
- reason: z.string().openapi({
17
- example: "String must contain at least 3 character(s)",
18
- description: "The reason for validation failure",
19
- }),
20
- });
21
-
22
- /**
23
- * Schema for RFC 7807 constraint violations
24
- */
25
- export const RFC7807ConstraintViolationSchema = z.object({
26
- name: z.string().openapi({
27
- example: "email",
28
- description: "The field name that violated a constraint",
29
- }),
30
- reason: z.string().openapi({
31
- example: "Email already exists",
32
- description: "The reason for the constraint violation",
33
- }),
34
- resource: z.string().openapi({
35
- example: "user",
36
- description: "The resource type that contains the constraint",
37
- }),
38
- constraint: z.string().openapi({
39
- example: "unique",
40
- description: "The type of constraint that was violated",
41
- }),
42
- });
43
-
44
- /**
45
- * Schema for additional error data in RFC 7807 problem details
46
- */
47
- export const RFC7807ErrorDataSchema = z.object({
48
- "invalid-params": z.array(RFC7807ValidationParamSchema).optional(),
49
- violations: z.array(RFC7807ConstraintViolationSchema).optional(),
50
- });
51
-
52
- /**
53
- * Schema for complete RFC 7807 problem details
54
- */
55
- export const RFC7807DetailsSchema = z
56
- .object({
57
- type: z.string().url().openapi({
58
- example: "https://api.example.com/problems/validation-error",
59
- description: "A URI reference that identifies the problem type",
60
- }),
61
- title: z.string().openapi({
62
- example: "Validation Failed",
63
- description: "A short, human-readable summary of the problem type",
64
- }),
65
- status: z.number().int().min(400).max(599).openapi({
66
- example: 400,
67
- description: "The HTTP status code",
68
- }),
69
-
70
- // Optional fields per RFC7807
71
- detail: z.string().optional().openapi({
72
- example: "The request contains invalid fields",
73
- description:
74
- "A human-readable explanation specific to this occurrence of the problem",
75
- }),
76
- instance: z.string().url().optional().openapi({
77
- example: "urn:uuid:6b56944d-5e89-4b4d-9ca7-c1be3d1f0e3f",
78
- description:
79
- "A URI reference that identifies the specific occurrence of the problem",
80
- }),
81
-
82
- // Extensions for validation errors
83
- timestamp: z.string().datetime().optional().openapi({
84
- example: "2025-02-26T12:34:56.789Z",
85
- description: "When the error occurred",
86
- }),
87
- })
88
- .merge(RFC7807ErrorDataSchema);
package/src/index.ts DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * Main entry point for hono-ban
3
- * @module hono-ban
4
- */
5
-
6
- // Export core functionality
7
- export * from "./core";
8
-
9
- // Export formatters
10
- export * from "./formatters";
11
-
12
- // Export error factories
13
- export * from "./factories";
14
-
15
- // Export constants
16
- export * from "./constants";
17
-
18
- // Export types
19
- export * from "./types";
20
-
21
- // Export middleware as default
22
- import { ban } from "./middleware";
23
- export default ban;