@fishka/express 0.9.7 → 0.9.9
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/README.md +21 -13
- package/dist/cjs/api.types.d.ts +4 -4
- package/dist/cjs/api.types.js +7 -7
- package/dist/cjs/http-status-codes.d.ts +0 -89
- package/dist/cjs/http-status-codes.js +2 -90
- package/dist/cjs/route-table.d.ts +1 -1
- package/dist/cjs/router.js +2 -2
- package/dist/esm/api.types.d.ts +4 -4
- package/dist/esm/api.types.js +8 -8
- package/dist/esm/http-status-codes.d.ts +0 -89
- package/dist/esm/http-status-codes.js +1 -89
- package/dist/esm/route-table.d.ts +1 -1
- package/dist/esm/router.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ routes.get<Array<{ id: string; name: string }>>('users', async () => [
|
|
|
33
33
|
|
|
34
34
|
// POST /users
|
|
35
35
|
routes.post<{ name: string }, { id: string }>('users', {
|
|
36
|
-
$body: { name: v => assertString(v, '
|
|
36
|
+
$body: { name: v => assertString(v, 'name required') },
|
|
37
37
|
run: async ctx => ({ id: '1' }),
|
|
38
38
|
});
|
|
39
39
|
|
|
@@ -51,14 +51,14 @@ Global validation can be enforced for specific URL parameters (e.g., `:id`, `:or
|
|
|
51
51
|
|
|
52
52
|
```typescript
|
|
53
53
|
import { registerUrlParameter } from '@fishka/express';
|
|
54
|
-
import { assertString } from '@fishka/assertions';
|
|
54
|
+
import { assertString, assertTruthy } from '@fishka/assertions';
|
|
55
55
|
|
|
56
56
|
// Register parameters with optional validation
|
|
57
57
|
registerUrlParameter('orgId', {
|
|
58
|
-
validator:
|
|
58
|
+
validator: val => {
|
|
59
59
|
assertString(val);
|
|
60
|
-
|
|
61
|
-
}
|
|
60
|
+
assertTruthy(val.startsWith('org-'), 'Invalid Organization ID');
|
|
61
|
+
},
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
// Now /orgs/:orgId will automatically validate that orgId starts with 'org-'
|
|
@@ -95,19 +95,27 @@ app.use(
|
|
|
95
95
|
);
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
## HTTP Status Code in Validation
|
|
99
|
+
|
|
100
|
+
For cases where you need specific HTTP status codes (like 401 for authentication, 404 for not found), use `assertHttp`:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { assertHttp, HTTP_UNAUTHORIZED, HTTP_NOT_FOUND } from '@fishka/express';
|
|
104
|
+
|
|
105
|
+
// In a validator or route handler
|
|
106
|
+
assertHttp(req.headers.authorization, HTTP_UNAUTHORIZED, 'Authorization required');
|
|
107
|
+
assertHttp(user, HTTP_NOT_FOUND, 'User not found');
|
|
108
|
+
assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
|
|
109
|
+
```
|
|
110
|
+
|
|
98
111
|
## Complete Example
|
|
99
112
|
|
|
100
113
|
Here is a full initialization including TLS context, global validation, and proper error handling.
|
|
101
114
|
|
|
102
115
|
```typescript
|
|
103
116
|
import express from 'express';
|
|
104
|
-
import {
|
|
105
|
-
|
|
106
|
-
createTlsMiddleware,
|
|
107
|
-
catchAllMiddleware,
|
|
108
|
-
registerUrlParameter
|
|
109
|
-
} from '@fishka/express';
|
|
110
|
-
import { assertString } from '@fishka/assertions';
|
|
117
|
+
import { createRouteTable, createTlsMiddleware, catchAllMiddleware, registerUrlParameter } from '@fishka/express';
|
|
118
|
+
import { assertString, assertTruthy } from '@fishka/assertions';
|
|
111
119
|
|
|
112
120
|
const app = express();
|
|
113
121
|
|
|
@@ -119,7 +127,7 @@ app.use(createTlsMiddleware());
|
|
|
119
127
|
|
|
120
128
|
// 3. Register global URL parameters
|
|
121
129
|
registerUrlParameter('id', {
|
|
122
|
-
validator:
|
|
130
|
+
validator: val => assertString(val),
|
|
123
131
|
});
|
|
124
132
|
|
|
125
133
|
// 4. Define routes
|
package/dist/cjs/api.types.d.ts
CHANGED
|
@@ -6,10 +6,10 @@ export declare class HttpError extends Error {
|
|
|
6
6
|
constructor(status: number, message: string, details?: Record<string, unknown> | undefined);
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Asserts that
|
|
9
|
+
* Asserts that the value is truthy, throwing an HttpError with the specified status code if false.
|
|
10
10
|
* This function is designed for HTTP-specific validation where you want to throw appropriate HTTP status codes.
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
12
|
+
* @param value - The condition to check. If falsy, an HttpError will be thrown.
|
|
13
13
|
* @param status - The HTTP status code to use in the HttpError (e.g., 400 for Bad Request, 404 for Not Found).
|
|
14
14
|
* @param message - The error message to include in the HttpError.
|
|
15
15
|
*
|
|
@@ -21,7 +21,7 @@ export declare class HttpError extends Error {
|
|
|
21
21
|
* assertHttp(typeof userId === 'string', HTTP_BAD_REQUEST, 'User ID must be a string');
|
|
22
22
|
*
|
|
23
23
|
* // Validate resource existence
|
|
24
|
-
* assertHttp(user
|
|
24
|
+
* assertHttp(user, HTTP_NOT_FOUND, 'User not found');
|
|
25
25
|
*
|
|
26
26
|
* // Validate authorization
|
|
27
27
|
* assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
|
|
@@ -36,7 +36,7 @@ export declare class HttpError extends Error {
|
|
|
36
36
|
* @see {@link HTTP_FORBIDDEN}
|
|
37
37
|
* @see {@link HTTP_UNAUTHORIZED}
|
|
38
38
|
*/
|
|
39
|
-
export declare function assertHttp(
|
|
39
|
+
export declare function assertHttp(value: unknown, status: number, message: string): asserts value;
|
|
40
40
|
export interface ApiResponse<ResponseEntity = unknown> {
|
|
41
41
|
/** Result of the call. A single entity for non-paginated ${by-id} requests or an array for list queries. */
|
|
42
42
|
result: ResponseEntity;
|
package/dist/cjs/api.types.js
CHANGED
|
@@ -18,10 +18,10 @@ class HttpError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
exports.HttpError = HttpError;
|
|
20
20
|
/**
|
|
21
|
-
* Asserts that
|
|
21
|
+
* Asserts that the value is truthy, throwing an HttpError with the specified status code if false.
|
|
22
22
|
* This function is designed for HTTP-specific validation where you want to throw appropriate HTTP status codes.
|
|
23
23
|
*
|
|
24
|
-
* @param
|
|
24
|
+
* @param value - The condition to check. If falsy, an HttpError will be thrown.
|
|
25
25
|
* @param status - The HTTP status code to use in the HttpError (e.g., 400 for Bad Request, 404 for Not Found).
|
|
26
26
|
* @param message - The error message to include in the HttpError.
|
|
27
27
|
*
|
|
@@ -33,7 +33,7 @@ exports.HttpError = HttpError;
|
|
|
33
33
|
* assertHttp(typeof userId === 'string', HTTP_BAD_REQUEST, 'User ID must be a string');
|
|
34
34
|
*
|
|
35
35
|
* // Validate resource existence
|
|
36
|
-
* assertHttp(user
|
|
36
|
+
* assertHttp(user, HTTP_NOT_FOUND, 'User not found');
|
|
37
37
|
*
|
|
38
38
|
* // Validate authorization
|
|
39
39
|
* assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
|
|
@@ -48,8 +48,8 @@ exports.HttpError = HttpError;
|
|
|
48
48
|
* @see {@link HTTP_FORBIDDEN}
|
|
49
49
|
* @see {@link HTTP_UNAUTHORIZED}
|
|
50
50
|
*/
|
|
51
|
-
function assertHttp(
|
|
52
|
-
(0, assertions_1.assertTruthy)(
|
|
51
|
+
function assertHttp(value, status, message) {
|
|
52
|
+
(0, assertions_1.assertTruthy)(value, () => new HttpError(status, message));
|
|
53
53
|
}
|
|
54
54
|
/** Converts an API response value into a standardized ApiResponse structure. */
|
|
55
55
|
function response(result) {
|
|
@@ -69,6 +69,6 @@ function registerUrlParameter(name, info) {
|
|
|
69
69
|
* @Internal
|
|
70
70
|
*/
|
|
71
71
|
function assertUrlParameter(name) {
|
|
72
|
-
(
|
|
73
|
-
assertHttp(exports.URL_PARAMETER_INFO[name]
|
|
72
|
+
assertHttp(typeof name === 'string', http_status_codes_1.HTTP_BAD_REQUEST, 'Url parameter name must be a string');
|
|
73
|
+
assertHttp(exports.URL_PARAMETER_INFO[name], http_status_codes_1.HTTP_BAD_REQUEST, `Invalid URL parameter: '${name}'. Please register it using 'registerUrlParameter('${name}', ...)'`);
|
|
74
74
|
}
|
|
@@ -80,95 +80,6 @@ export declare const HTTP_BAD_GATEWAY = 502;
|
|
|
80
80
|
export declare const HTTP_SERVICE_UNAVAILABLE = 503;
|
|
81
81
|
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
82
82
|
export declare const HTTP_GATEWAY_TIMEOUT = 504;
|
|
83
|
-
/**
|
|
84
|
-
* An object containing common HTTP status codes.
|
|
85
|
-
* These constants can be used to improve code readability and maintainability.
|
|
86
|
-
* @deprecated Use individual HTTP_* constants for better tree-shaking
|
|
87
|
-
*/
|
|
88
|
-
export declare const HttpStatusCode: {
|
|
89
|
-
/** The request has succeeded (200) */
|
|
90
|
-
OK: number;
|
|
91
|
-
/** The request has been fulfilled, and a new resource is created (201) */
|
|
92
|
-
CREATED: number;
|
|
93
|
-
/** The request has been accepted for processing, but the processing is not yet complete (202) */
|
|
94
|
-
ACCEPTED: number;
|
|
95
|
-
/** The server successfully processed the request, and is not returning any content (204) */
|
|
96
|
-
NO_CONTENT: number;
|
|
97
|
-
/** The request has been successfully processed, but is returning no content (205) */
|
|
98
|
-
RESET_CONTENT: number;
|
|
99
|
-
/** The server is delivering only part of the resource due to a range header sent by the client (206) */
|
|
100
|
-
PARTIAL_CONTENT: number;
|
|
101
|
-
/** The IM used the server processed a request successfully, but the response is transformed (226) */
|
|
102
|
-
IM_USED: number;
|
|
103
|
-
/** The resource has been moved permanently to a new URL (301) */
|
|
104
|
-
MOVED_PERMANENTLY: number;
|
|
105
|
-
/** The resource is available at a different URL (302) */
|
|
106
|
-
FOUND: number;
|
|
107
|
-
/** The resource has not been modified since the last request (304) */
|
|
108
|
-
NOT_MODIFIED: number;
|
|
109
|
-
/** The server could not understand the request due to invalid syntax (400) */
|
|
110
|
-
BAD_REQUEST: number;
|
|
111
|
-
/** The client must authenticate itself to get the requested response (401) */
|
|
112
|
-
UNAUTHORIZED: number;
|
|
113
|
-
/** The client does not have access rights to the content (403) */
|
|
114
|
-
FORBIDDEN: number;
|
|
115
|
-
/** The server cannot find the requested resource (404) */
|
|
116
|
-
NOT_FOUND: number;
|
|
117
|
-
/** The request method is known by the server but is not supported by the target resource (405) */
|
|
118
|
-
METHOD_NOT_ALLOWED: number;
|
|
119
|
-
/** The client must authenticate using a proxy (407) */
|
|
120
|
-
PROXY_AUTHENTICATION_REQUIRED: number;
|
|
121
|
-
/** The server timed out waiting for the request (408) */
|
|
122
|
-
REQUEST_TIMEOUT: number;
|
|
123
|
-
/** The request conflicts with the current state of the server (409) */
|
|
124
|
-
CONFLICT: number;
|
|
125
|
-
/** The resource requested is no longer available and will not be available again (410) */
|
|
126
|
-
GONE: number;
|
|
127
|
-
/** The request does not meet the preconditions that the server requires (412) */
|
|
128
|
-
PRECONDITION_FAILED: number;
|
|
129
|
-
/** The client sent a request that is too large for the server to process (413) */
|
|
130
|
-
PAYLOAD_TOO_LARGE: number;
|
|
131
|
-
/** The URI requested by the client is too long for the server to process (414) */
|
|
132
|
-
URI_TOO_LONG: number;
|
|
133
|
-
/** The media format of the requested data is not supported by the server (415) */
|
|
134
|
-
UNSUPPORTED_MEDIA_TYPE: number;
|
|
135
|
-
/** The range specified by the client cannot be fulfilled (416) */
|
|
136
|
-
RANGE_NOT_SATISFIABLE: number;
|
|
137
|
-
/** The expectation given in the request header could not be met by the server (417) */
|
|
138
|
-
EXPECTATION_FAILED: number;
|
|
139
|
-
/** The server refuses to brew coffee because it is a teapot (418) - an Easter egg from RFC 2324 */
|
|
140
|
-
IM_A_TEAPOT: number;
|
|
141
|
-
/** The request was well-formed but was unable to be followed due to semantic errors (422) */
|
|
142
|
-
UNPROCESSABLE_ENTITY: number;
|
|
143
|
-
/** The resource that is being accessed is locked (423) */
|
|
144
|
-
LOCKED: number;
|
|
145
|
-
/** The resource requested is dependent on another resource that has failed (424) */
|
|
146
|
-
FAILED_DEPENDENCY: number;
|
|
147
|
-
/** The server is unwilling to risk processing a request that might be replayed (425) */
|
|
148
|
-
TOO_EARLY: number;
|
|
149
|
-
/** The client needs to upgrade its protocol (426) */
|
|
150
|
-
UPGRADE_REQUIRED: number;
|
|
151
|
-
/** The server requires the request to be conditional (428) */
|
|
152
|
-
PRECONDITION_REQUIRED: number;
|
|
153
|
-
/** The client has sent too many requests in a given amount of time (429) */
|
|
154
|
-
TOO_MANY_REQUESTS: number;
|
|
155
|
-
/** The request header fields are too large (431) */
|
|
156
|
-
REQUEST_HEADER_FIELDS_TOO_LARGE: number;
|
|
157
|
-
/** The client closed the connection with the server before the request was completed (444) */
|
|
158
|
-
CONNECTION_CLOSED_WITHOUT_RESPONSE: number;
|
|
159
|
-
/** The client requested an unavailable legal action (451) */
|
|
160
|
-
UNAVAILABLE_FOR_LEGAL_REASONS: number;
|
|
161
|
-
/** The server encountered an internal error and was unable to complete the request (500) */
|
|
162
|
-
INTERNAL_SERVER_ERROR: number;
|
|
163
|
-
/** The request method is not supported by the server and cannot be handled (501) */
|
|
164
|
-
NOT_IMPLEMENTED: number;
|
|
165
|
-
/** The server, while acting as a gateway or proxy, received an invalid response from the upstream server (502) */
|
|
166
|
-
BAD_GATEWAY: number;
|
|
167
|
-
/** The server is not ready to handle the request, typically due to temporary overload or maintenance (503) */
|
|
168
|
-
SERVICE_UNAVAILABLE: number;
|
|
169
|
-
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
170
|
-
GATEWAY_TIMEOUT: number;
|
|
171
|
-
};
|
|
172
83
|
/**
|
|
173
84
|
* Returns the reason phrase corresponding to the given HTTP status code.
|
|
174
85
|
* This is useful for converting status codes into human-readable messages.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// noinspection JSUnusedGlobalSymbols
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getHttpStatusCodeReasonPhrase = exports.
|
|
4
|
+
exports.getHttpStatusCodeReasonPhrase = exports.HTTP_GATEWAY_TIMEOUT = exports.HTTP_SERVICE_UNAVAILABLE = exports.HTTP_BAD_GATEWAY = exports.HTTP_NOT_IMPLEMENTED = exports.HTTP_INTERNAL_SERVER_ERROR = exports.HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = exports.HTTP_CONNECTION_CLOSED_WITHOUT_RESPONSE = exports.HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_PRECONDITION_REQUIRED = exports.HTTP_UPGRADE_REQUIRED = exports.HTTP_TOO_EARLY = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_LOCKED = exports.HTTP_UNPROCESSABLE_ENTITY = exports.HTTP_IM_A_TEAPOT = exports.HTTP_EXPECTATION_FAILED = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_UNSUPPORTED_MEDIA_TYPE = exports.HTTP_URI_TOO_LONG = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = exports.HTTP_GONE = exports.HTTP_CONFLICT = exports.HTTP_REQUEST_TIMEOUT = exports.HTTP_PROXY_AUTHENTICATION_REQUIRED = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_FOUND = exports.HTTP_MOVED_PERMANENTLY = exports.HTTP_IM_USED = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_RESET_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_ACCEPTED = exports.HTTP_CREATED = exports.HTTP_OK = void 0;
|
|
4
5
|
/** The request has succeeded (200) */
|
|
5
6
|
exports.HTTP_OK = 200;
|
|
6
7
|
/** The request has been fulfilled, and a new resource is created (201) */
|
|
@@ -83,95 +84,6 @@ exports.HTTP_BAD_GATEWAY = 502;
|
|
|
83
84
|
exports.HTTP_SERVICE_UNAVAILABLE = 503;
|
|
84
85
|
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
85
86
|
exports.HTTP_GATEWAY_TIMEOUT = 504;
|
|
86
|
-
/**
|
|
87
|
-
* An object containing common HTTP status codes.
|
|
88
|
-
* These constants can be used to improve code readability and maintainability.
|
|
89
|
-
* @deprecated Use individual HTTP_* constants for better tree-shaking
|
|
90
|
-
*/
|
|
91
|
-
exports.HttpStatusCode = {
|
|
92
|
-
/** The request has succeeded (200) */
|
|
93
|
-
OK: exports.HTTP_OK,
|
|
94
|
-
/** The request has been fulfilled, and a new resource is created (201) */
|
|
95
|
-
CREATED: exports.HTTP_CREATED,
|
|
96
|
-
/** The request has been accepted for processing, but the processing is not yet complete (202) */
|
|
97
|
-
ACCEPTED: exports.HTTP_ACCEPTED,
|
|
98
|
-
/** The server successfully processed the request, and is not returning any content (204) */
|
|
99
|
-
NO_CONTENT: exports.HTTP_NO_CONTENT,
|
|
100
|
-
/** The request has been successfully processed, but is returning no content (205) */
|
|
101
|
-
RESET_CONTENT: exports.HTTP_RESET_CONTENT,
|
|
102
|
-
/** The server is delivering only part of the resource due to a range header sent by the client (206) */
|
|
103
|
-
PARTIAL_CONTENT: exports.HTTP_PARTIAL_CONTENT,
|
|
104
|
-
/** The IM used the server processed a request successfully, but the response is transformed (226) */
|
|
105
|
-
IM_USED: exports.HTTP_IM_USED,
|
|
106
|
-
/** The resource has been moved permanently to a new URL (301) */
|
|
107
|
-
MOVED_PERMANENTLY: exports.HTTP_MOVED_PERMANENTLY,
|
|
108
|
-
/** The resource is available at a different URL (302) */
|
|
109
|
-
FOUND: exports.HTTP_FOUND,
|
|
110
|
-
/** The resource has not been modified since the last request (304) */
|
|
111
|
-
NOT_MODIFIED: exports.HTTP_NOT_MODIFIED,
|
|
112
|
-
/** The server could not understand the request due to invalid syntax (400) */
|
|
113
|
-
BAD_REQUEST: exports.HTTP_BAD_REQUEST,
|
|
114
|
-
/** The client must authenticate itself to get the requested response (401) */
|
|
115
|
-
UNAUTHORIZED: exports.HTTP_UNAUTHORIZED,
|
|
116
|
-
/** The client does not have access rights to the content (403) */
|
|
117
|
-
FORBIDDEN: exports.HTTP_FORBIDDEN,
|
|
118
|
-
/** The server cannot find the requested resource (404) */
|
|
119
|
-
NOT_FOUND: exports.HTTP_NOT_FOUND,
|
|
120
|
-
/** The request method is known by the server but is not supported by the target resource (405) */
|
|
121
|
-
METHOD_NOT_ALLOWED: exports.HTTP_METHOD_NOT_ALLOWED,
|
|
122
|
-
/** The client must authenticate using a proxy (407) */
|
|
123
|
-
PROXY_AUTHENTICATION_REQUIRED: exports.HTTP_PROXY_AUTHENTICATION_REQUIRED,
|
|
124
|
-
/** The server timed out waiting for the request (408) */
|
|
125
|
-
REQUEST_TIMEOUT: exports.HTTP_REQUEST_TIMEOUT,
|
|
126
|
-
/** The request conflicts with the current state of the server (409) */
|
|
127
|
-
CONFLICT: exports.HTTP_CONFLICT,
|
|
128
|
-
/** The resource requested is no longer available and will not be available again (410) */
|
|
129
|
-
GONE: exports.HTTP_GONE,
|
|
130
|
-
/** The request does not meet the preconditions that the server requires (412) */
|
|
131
|
-
PRECONDITION_FAILED: exports.HTTP_PRECONDITION_FAILED,
|
|
132
|
-
/** The client sent a request that is too large for the server to process (413) */
|
|
133
|
-
PAYLOAD_TOO_LARGE: exports.HTTP_PAYLOAD_TOO_LARGE,
|
|
134
|
-
/** The URI requested by the client is too long for the server to process (414) */
|
|
135
|
-
URI_TOO_LONG: exports.HTTP_URI_TOO_LONG,
|
|
136
|
-
/** The media format of the requested data is not supported by the server (415) */
|
|
137
|
-
UNSUPPORTED_MEDIA_TYPE: exports.HTTP_UNSUPPORTED_MEDIA_TYPE,
|
|
138
|
-
/** The range specified by the client cannot be fulfilled (416) */
|
|
139
|
-
RANGE_NOT_SATISFIABLE: exports.HTTP_RANGE_NOT_SATISFIABLE,
|
|
140
|
-
/** The expectation given in the request header could not be met by the server (417) */
|
|
141
|
-
EXPECTATION_FAILED: exports.HTTP_EXPECTATION_FAILED,
|
|
142
|
-
/** The server refuses to brew coffee because it is a teapot (418) - an Easter egg from RFC 2324 */
|
|
143
|
-
IM_A_TEAPOT: exports.HTTP_IM_A_TEAPOT,
|
|
144
|
-
/** The request was well-formed but was unable to be followed due to semantic errors (422) */
|
|
145
|
-
UNPROCESSABLE_ENTITY: exports.HTTP_UNPROCESSABLE_ENTITY,
|
|
146
|
-
/** The resource that is being accessed is locked (423) */
|
|
147
|
-
LOCKED: exports.HTTP_LOCKED,
|
|
148
|
-
/** The resource requested is dependent on another resource that has failed (424) */
|
|
149
|
-
FAILED_DEPENDENCY: exports.HTTP_FAILED_DEPENDENCY,
|
|
150
|
-
/** The server is unwilling to risk processing a request that might be replayed (425) */
|
|
151
|
-
TOO_EARLY: exports.HTTP_TOO_EARLY,
|
|
152
|
-
/** The client needs to upgrade its protocol (426) */
|
|
153
|
-
UPGRADE_REQUIRED: exports.HTTP_UPGRADE_REQUIRED,
|
|
154
|
-
/** The server requires the request to be conditional (428) */
|
|
155
|
-
PRECONDITION_REQUIRED: exports.HTTP_PRECONDITION_REQUIRED,
|
|
156
|
-
/** The client has sent too many requests in a given amount of time (429) */
|
|
157
|
-
TOO_MANY_REQUESTS: exports.HTTP_TOO_MANY_REQUESTS,
|
|
158
|
-
/** The request header fields are too large (431) */
|
|
159
|
-
REQUEST_HEADER_FIELDS_TOO_LARGE: exports.HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
|
160
|
-
/** The client closed the connection with the server before the request was completed (444) */
|
|
161
|
-
CONNECTION_CLOSED_WITHOUT_RESPONSE: exports.HTTP_CONNECTION_CLOSED_WITHOUT_RESPONSE,
|
|
162
|
-
/** The client requested an unavailable legal action (451) */
|
|
163
|
-
UNAVAILABLE_FOR_LEGAL_REASONS: exports.HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
|
|
164
|
-
/** The server encountered an internal error and was unable to complete the request (500) */
|
|
165
|
-
INTERNAL_SERVER_ERROR: exports.HTTP_INTERNAL_SERVER_ERROR,
|
|
166
|
-
/** The request method is not supported by the server and cannot be handled (501) */
|
|
167
|
-
NOT_IMPLEMENTED: exports.HTTP_NOT_IMPLEMENTED,
|
|
168
|
-
/** The server, while acting as a gateway or proxy, received an invalid response from the upstream server (502) */
|
|
169
|
-
BAD_GATEWAY: exports.HTTP_BAD_GATEWAY,
|
|
170
|
-
/** The server is not ready to handle the request, typically due to temporary overload or maintenance (503) */
|
|
171
|
-
SERVICE_UNAVAILABLE: exports.HTTP_SERVICE_UNAVAILABLE,
|
|
172
|
-
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
173
|
-
GATEWAY_TIMEOUT: exports.HTTP_GATEWAY_TIMEOUT,
|
|
174
|
-
};
|
|
175
87
|
/**
|
|
176
88
|
* Returns the reason phrase corresponding to the given HTTP status code.
|
|
177
89
|
* This is useful for converting status codes into human-readable messages.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ExpressApplication } from './utils/express.utils';
|
|
2
1
|
import { DeleteEndpoint, GetEndpoint, PatchEndpoint, PostEndpoint, PutEndpoint, RequestContext, ResponseOrValue } from './router';
|
|
2
|
+
import { ExpressApplication } from './utils/express.utils';
|
|
3
3
|
/**
|
|
4
4
|
* Helper utility for organizing and mounting routes.
|
|
5
5
|
* Provides a fluent interface for registering multiple handlers.
|
package/dist/cjs/router.js
CHANGED
|
@@ -38,8 +38,8 @@ exports.mount = mount;
|
|
|
38
38
|
const assertions_1 = require("@fishka/assertions");
|
|
39
39
|
const url = __importStar(require("url"));
|
|
40
40
|
const api_types_1 = require("./api.types");
|
|
41
|
-
const http_status_codes_1 = require("./http-status-codes");
|
|
42
41
|
const error_handling_1 = require("./error-handling");
|
|
42
|
+
const http_status_codes_1 = require("./http-status-codes");
|
|
43
43
|
const thread_local_storage_1 = require("./thread-local/thread-local-storage");
|
|
44
44
|
const conversion_utils_1 = require("./utils/conversion.utils");
|
|
45
45
|
// ============================================================================
|
|
@@ -228,7 +228,7 @@ function newRequestContext(requestBody, req, res) {
|
|
|
228
228
|
params: {
|
|
229
229
|
get: (key) => {
|
|
230
230
|
const value = req.params[key];
|
|
231
|
-
(0,
|
|
231
|
+
(0, api_types_1.assertHttp)(value, http_status_codes_1.HTTP_BAD_REQUEST, `Path parameter '${key}' not found`);
|
|
232
232
|
return value;
|
|
233
233
|
},
|
|
234
234
|
tryGet: (key) => req.params[key],
|
package/dist/esm/api.types.d.ts
CHANGED
|
@@ -6,10 +6,10 @@ export declare class HttpError extends Error {
|
|
|
6
6
|
constructor(status: number, message: string, details?: Record<string, unknown> | undefined);
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Asserts that
|
|
9
|
+
* Asserts that the value is truthy, throwing an HttpError with the specified status code if false.
|
|
10
10
|
* This function is designed for HTTP-specific validation where you want to throw appropriate HTTP status codes.
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
12
|
+
* @param value - The condition to check. If falsy, an HttpError will be thrown.
|
|
13
13
|
* @param status - The HTTP status code to use in the HttpError (e.g., 400 for Bad Request, 404 for Not Found).
|
|
14
14
|
* @param message - The error message to include in the HttpError.
|
|
15
15
|
*
|
|
@@ -21,7 +21,7 @@ export declare class HttpError extends Error {
|
|
|
21
21
|
* assertHttp(typeof userId === 'string', HTTP_BAD_REQUEST, 'User ID must be a string');
|
|
22
22
|
*
|
|
23
23
|
* // Validate resource existence
|
|
24
|
-
* assertHttp(user
|
|
24
|
+
* assertHttp(user, HTTP_NOT_FOUND, 'User not found');
|
|
25
25
|
*
|
|
26
26
|
* // Validate authorization
|
|
27
27
|
* assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
|
|
@@ -36,7 +36,7 @@ export declare class HttpError extends Error {
|
|
|
36
36
|
* @see {@link HTTP_FORBIDDEN}
|
|
37
37
|
* @see {@link HTTP_UNAUTHORIZED}
|
|
38
38
|
*/
|
|
39
|
-
export declare function assertHttp(
|
|
39
|
+
export declare function assertHttp(value: unknown, status: number, message: string): asserts value;
|
|
40
40
|
export interface ApiResponse<ResponseEntity = unknown> {
|
|
41
41
|
/** Result of the call. A single entity for non-paginated ${by-id} requests or an array for list queries. */
|
|
42
42
|
result: ResponseEntity;
|
package/dist/esm/api.types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assertTruthy } from '@fishka/assertions';
|
|
2
2
|
import { HTTP_BAD_REQUEST } from './http-status-codes';
|
|
3
3
|
export class HttpError extends Error {
|
|
4
4
|
constructor(status, message, details) {
|
|
@@ -10,10 +10,10 @@ export class HttpError extends Error {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Asserts that
|
|
13
|
+
* Asserts that the value is truthy, throwing an HttpError with the specified status code if false.
|
|
14
14
|
* This function is designed for HTTP-specific validation where you want to throw appropriate HTTP status codes.
|
|
15
15
|
*
|
|
16
|
-
* @param
|
|
16
|
+
* @param value - The condition to check. If falsy, an HttpError will be thrown.
|
|
17
17
|
* @param status - The HTTP status code to use in the HttpError (e.g., 400 for Bad Request, 404 for Not Found).
|
|
18
18
|
* @param message - The error message to include in the HttpError.
|
|
19
19
|
*
|
|
@@ -25,7 +25,7 @@ export class HttpError extends Error {
|
|
|
25
25
|
* assertHttp(typeof userId === 'string', HTTP_BAD_REQUEST, 'User ID must be a string');
|
|
26
26
|
*
|
|
27
27
|
* // Validate resource existence
|
|
28
|
-
* assertHttp(user
|
|
28
|
+
* assertHttp(user, HTTP_NOT_FOUND, 'User not found');
|
|
29
29
|
*
|
|
30
30
|
* // Validate authorization
|
|
31
31
|
* assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
|
|
@@ -40,8 +40,8 @@ export class HttpError extends Error {
|
|
|
40
40
|
* @see {@link HTTP_FORBIDDEN}
|
|
41
41
|
* @see {@link HTTP_UNAUTHORIZED}
|
|
42
42
|
*/
|
|
43
|
-
export function assertHttp(
|
|
44
|
-
assertTruthy(
|
|
43
|
+
export function assertHttp(value, status, message) {
|
|
44
|
+
assertTruthy(value, () => new HttpError(status, message));
|
|
45
45
|
}
|
|
46
46
|
/** Converts an API response value into a standardized ApiResponse structure. */
|
|
47
47
|
export function response(result) {
|
|
@@ -61,6 +61,6 @@ export function registerUrlParameter(name, info) {
|
|
|
61
61
|
* @Internal
|
|
62
62
|
*/
|
|
63
63
|
export function assertUrlParameter(name) {
|
|
64
|
-
|
|
65
|
-
assertHttp(URL_PARAMETER_INFO[name]
|
|
64
|
+
assertHttp(typeof name === 'string', HTTP_BAD_REQUEST, 'Url parameter name must be a string');
|
|
65
|
+
assertHttp(URL_PARAMETER_INFO[name], HTTP_BAD_REQUEST, `Invalid URL parameter: '${name}'. Please register it using 'registerUrlParameter('${name}', ...)'`);
|
|
66
66
|
}
|
|
@@ -80,95 +80,6 @@ export declare const HTTP_BAD_GATEWAY = 502;
|
|
|
80
80
|
export declare const HTTP_SERVICE_UNAVAILABLE = 503;
|
|
81
81
|
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
82
82
|
export declare const HTTP_GATEWAY_TIMEOUT = 504;
|
|
83
|
-
/**
|
|
84
|
-
* An object containing common HTTP status codes.
|
|
85
|
-
* These constants can be used to improve code readability and maintainability.
|
|
86
|
-
* @deprecated Use individual HTTP_* constants for better tree-shaking
|
|
87
|
-
*/
|
|
88
|
-
export declare const HttpStatusCode: {
|
|
89
|
-
/** The request has succeeded (200) */
|
|
90
|
-
OK: number;
|
|
91
|
-
/** The request has been fulfilled, and a new resource is created (201) */
|
|
92
|
-
CREATED: number;
|
|
93
|
-
/** The request has been accepted for processing, but the processing is not yet complete (202) */
|
|
94
|
-
ACCEPTED: number;
|
|
95
|
-
/** The server successfully processed the request, and is not returning any content (204) */
|
|
96
|
-
NO_CONTENT: number;
|
|
97
|
-
/** The request has been successfully processed, but is returning no content (205) */
|
|
98
|
-
RESET_CONTENT: number;
|
|
99
|
-
/** The server is delivering only part of the resource due to a range header sent by the client (206) */
|
|
100
|
-
PARTIAL_CONTENT: number;
|
|
101
|
-
/** The IM used the server processed a request successfully, but the response is transformed (226) */
|
|
102
|
-
IM_USED: number;
|
|
103
|
-
/** The resource has been moved permanently to a new URL (301) */
|
|
104
|
-
MOVED_PERMANENTLY: number;
|
|
105
|
-
/** The resource is available at a different URL (302) */
|
|
106
|
-
FOUND: number;
|
|
107
|
-
/** The resource has not been modified since the last request (304) */
|
|
108
|
-
NOT_MODIFIED: number;
|
|
109
|
-
/** The server could not understand the request due to invalid syntax (400) */
|
|
110
|
-
BAD_REQUEST: number;
|
|
111
|
-
/** The client must authenticate itself to get the requested response (401) */
|
|
112
|
-
UNAUTHORIZED: number;
|
|
113
|
-
/** The client does not have access rights to the content (403) */
|
|
114
|
-
FORBIDDEN: number;
|
|
115
|
-
/** The server cannot find the requested resource (404) */
|
|
116
|
-
NOT_FOUND: number;
|
|
117
|
-
/** The request method is known by the server but is not supported by the target resource (405) */
|
|
118
|
-
METHOD_NOT_ALLOWED: number;
|
|
119
|
-
/** The client must authenticate using a proxy (407) */
|
|
120
|
-
PROXY_AUTHENTICATION_REQUIRED: number;
|
|
121
|
-
/** The server timed out waiting for the request (408) */
|
|
122
|
-
REQUEST_TIMEOUT: number;
|
|
123
|
-
/** The request conflicts with the current state of the server (409) */
|
|
124
|
-
CONFLICT: number;
|
|
125
|
-
/** The resource requested is no longer available and will not be available again (410) */
|
|
126
|
-
GONE: number;
|
|
127
|
-
/** The request does not meet the preconditions that the server requires (412) */
|
|
128
|
-
PRECONDITION_FAILED: number;
|
|
129
|
-
/** The client sent a request that is too large for the server to process (413) */
|
|
130
|
-
PAYLOAD_TOO_LARGE: number;
|
|
131
|
-
/** The URI requested by the client is too long for the server to process (414) */
|
|
132
|
-
URI_TOO_LONG: number;
|
|
133
|
-
/** The media format of the requested data is not supported by the server (415) */
|
|
134
|
-
UNSUPPORTED_MEDIA_TYPE: number;
|
|
135
|
-
/** The range specified by the client cannot be fulfilled (416) */
|
|
136
|
-
RANGE_NOT_SATISFIABLE: number;
|
|
137
|
-
/** The expectation given in the request header could not be met by the server (417) */
|
|
138
|
-
EXPECTATION_FAILED: number;
|
|
139
|
-
/** The server refuses to brew coffee because it is a teapot (418) - an Easter egg from RFC 2324 */
|
|
140
|
-
IM_A_TEAPOT: number;
|
|
141
|
-
/** The request was well-formed but was unable to be followed due to semantic errors (422) */
|
|
142
|
-
UNPROCESSABLE_ENTITY: number;
|
|
143
|
-
/** The resource that is being accessed is locked (423) */
|
|
144
|
-
LOCKED: number;
|
|
145
|
-
/** The resource requested is dependent on another resource that has failed (424) */
|
|
146
|
-
FAILED_DEPENDENCY: number;
|
|
147
|
-
/** The server is unwilling to risk processing a request that might be replayed (425) */
|
|
148
|
-
TOO_EARLY: number;
|
|
149
|
-
/** The client needs to upgrade its protocol (426) */
|
|
150
|
-
UPGRADE_REQUIRED: number;
|
|
151
|
-
/** The server requires the request to be conditional (428) */
|
|
152
|
-
PRECONDITION_REQUIRED: number;
|
|
153
|
-
/** The client has sent too many requests in a given amount of time (429) */
|
|
154
|
-
TOO_MANY_REQUESTS: number;
|
|
155
|
-
/** The request header fields are too large (431) */
|
|
156
|
-
REQUEST_HEADER_FIELDS_TOO_LARGE: number;
|
|
157
|
-
/** The client closed the connection with the server before the request was completed (444) */
|
|
158
|
-
CONNECTION_CLOSED_WITHOUT_RESPONSE: number;
|
|
159
|
-
/** The client requested an unavailable legal action (451) */
|
|
160
|
-
UNAVAILABLE_FOR_LEGAL_REASONS: number;
|
|
161
|
-
/** The server encountered an internal error and was unable to complete the request (500) */
|
|
162
|
-
INTERNAL_SERVER_ERROR: number;
|
|
163
|
-
/** The request method is not supported by the server and cannot be handled (501) */
|
|
164
|
-
NOT_IMPLEMENTED: number;
|
|
165
|
-
/** The server, while acting as a gateway or proxy, received an invalid response from the upstream server (502) */
|
|
166
|
-
BAD_GATEWAY: number;
|
|
167
|
-
/** The server is not ready to handle the request, typically due to temporary overload or maintenance (503) */
|
|
168
|
-
SERVICE_UNAVAILABLE: number;
|
|
169
|
-
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
170
|
-
GATEWAY_TIMEOUT: number;
|
|
171
|
-
};
|
|
172
83
|
/**
|
|
173
84
|
* Returns the reason phrase corresponding to the given HTTP status code.
|
|
174
85
|
* This is useful for converting status codes into human-readable messages.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// noinspection JSUnusedGlobalSymbols
|
|
1
2
|
/** The request has succeeded (200) */
|
|
2
3
|
export const HTTP_OK = 200;
|
|
3
4
|
/** The request has been fulfilled, and a new resource is created (201) */
|
|
@@ -80,95 +81,6 @@ export const HTTP_BAD_GATEWAY = 502;
|
|
|
80
81
|
export const HTTP_SERVICE_UNAVAILABLE = 503;
|
|
81
82
|
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
82
83
|
export const HTTP_GATEWAY_TIMEOUT = 504;
|
|
83
|
-
/**
|
|
84
|
-
* An object containing common HTTP status codes.
|
|
85
|
-
* These constants can be used to improve code readability and maintainability.
|
|
86
|
-
* @deprecated Use individual HTTP_* constants for better tree-shaking
|
|
87
|
-
*/
|
|
88
|
-
export const HttpStatusCode = {
|
|
89
|
-
/** The request has succeeded (200) */
|
|
90
|
-
OK: HTTP_OK,
|
|
91
|
-
/** The request has been fulfilled, and a new resource is created (201) */
|
|
92
|
-
CREATED: HTTP_CREATED,
|
|
93
|
-
/** The request has been accepted for processing, but the processing is not yet complete (202) */
|
|
94
|
-
ACCEPTED: HTTP_ACCEPTED,
|
|
95
|
-
/** The server successfully processed the request, and is not returning any content (204) */
|
|
96
|
-
NO_CONTENT: HTTP_NO_CONTENT,
|
|
97
|
-
/** The request has been successfully processed, but is returning no content (205) */
|
|
98
|
-
RESET_CONTENT: HTTP_RESET_CONTENT,
|
|
99
|
-
/** The server is delivering only part of the resource due to a range header sent by the client (206) */
|
|
100
|
-
PARTIAL_CONTENT: HTTP_PARTIAL_CONTENT,
|
|
101
|
-
/** The IM used the server processed a request successfully, but the response is transformed (226) */
|
|
102
|
-
IM_USED: HTTP_IM_USED,
|
|
103
|
-
/** The resource has been moved permanently to a new URL (301) */
|
|
104
|
-
MOVED_PERMANENTLY: HTTP_MOVED_PERMANENTLY,
|
|
105
|
-
/** The resource is available at a different URL (302) */
|
|
106
|
-
FOUND: HTTP_FOUND,
|
|
107
|
-
/** The resource has not been modified since the last request (304) */
|
|
108
|
-
NOT_MODIFIED: HTTP_NOT_MODIFIED,
|
|
109
|
-
/** The server could not understand the request due to invalid syntax (400) */
|
|
110
|
-
BAD_REQUEST: HTTP_BAD_REQUEST,
|
|
111
|
-
/** The client must authenticate itself to get the requested response (401) */
|
|
112
|
-
UNAUTHORIZED: HTTP_UNAUTHORIZED,
|
|
113
|
-
/** The client does not have access rights to the content (403) */
|
|
114
|
-
FORBIDDEN: HTTP_FORBIDDEN,
|
|
115
|
-
/** The server cannot find the requested resource (404) */
|
|
116
|
-
NOT_FOUND: HTTP_NOT_FOUND,
|
|
117
|
-
/** The request method is known by the server but is not supported by the target resource (405) */
|
|
118
|
-
METHOD_NOT_ALLOWED: HTTP_METHOD_NOT_ALLOWED,
|
|
119
|
-
/** The client must authenticate using a proxy (407) */
|
|
120
|
-
PROXY_AUTHENTICATION_REQUIRED: HTTP_PROXY_AUTHENTICATION_REQUIRED,
|
|
121
|
-
/** The server timed out waiting for the request (408) */
|
|
122
|
-
REQUEST_TIMEOUT: HTTP_REQUEST_TIMEOUT,
|
|
123
|
-
/** The request conflicts with the current state of the server (409) */
|
|
124
|
-
CONFLICT: HTTP_CONFLICT,
|
|
125
|
-
/** The resource requested is no longer available and will not be available again (410) */
|
|
126
|
-
GONE: HTTP_GONE,
|
|
127
|
-
/** The request does not meet the preconditions that the server requires (412) */
|
|
128
|
-
PRECONDITION_FAILED: HTTP_PRECONDITION_FAILED,
|
|
129
|
-
/** The client sent a request that is too large for the server to process (413) */
|
|
130
|
-
PAYLOAD_TOO_LARGE: HTTP_PAYLOAD_TOO_LARGE,
|
|
131
|
-
/** The URI requested by the client is too long for the server to process (414) */
|
|
132
|
-
URI_TOO_LONG: HTTP_URI_TOO_LONG,
|
|
133
|
-
/** The media format of the requested data is not supported by the server (415) */
|
|
134
|
-
UNSUPPORTED_MEDIA_TYPE: HTTP_UNSUPPORTED_MEDIA_TYPE,
|
|
135
|
-
/** The range specified by the client cannot be fulfilled (416) */
|
|
136
|
-
RANGE_NOT_SATISFIABLE: HTTP_RANGE_NOT_SATISFIABLE,
|
|
137
|
-
/** The expectation given in the request header could not be met by the server (417) */
|
|
138
|
-
EXPECTATION_FAILED: HTTP_EXPECTATION_FAILED,
|
|
139
|
-
/** The server refuses to brew coffee because it is a teapot (418) - an Easter egg from RFC 2324 */
|
|
140
|
-
IM_A_TEAPOT: HTTP_IM_A_TEAPOT,
|
|
141
|
-
/** The request was well-formed but was unable to be followed due to semantic errors (422) */
|
|
142
|
-
UNPROCESSABLE_ENTITY: HTTP_UNPROCESSABLE_ENTITY,
|
|
143
|
-
/** The resource that is being accessed is locked (423) */
|
|
144
|
-
LOCKED: HTTP_LOCKED,
|
|
145
|
-
/** The resource requested is dependent on another resource that has failed (424) */
|
|
146
|
-
FAILED_DEPENDENCY: HTTP_FAILED_DEPENDENCY,
|
|
147
|
-
/** The server is unwilling to risk processing a request that might be replayed (425) */
|
|
148
|
-
TOO_EARLY: HTTP_TOO_EARLY,
|
|
149
|
-
/** The client needs to upgrade its protocol (426) */
|
|
150
|
-
UPGRADE_REQUIRED: HTTP_UPGRADE_REQUIRED,
|
|
151
|
-
/** The server requires the request to be conditional (428) */
|
|
152
|
-
PRECONDITION_REQUIRED: HTTP_PRECONDITION_REQUIRED,
|
|
153
|
-
/** The client has sent too many requests in a given amount of time (429) */
|
|
154
|
-
TOO_MANY_REQUESTS: HTTP_TOO_MANY_REQUESTS,
|
|
155
|
-
/** The request header fields are too large (431) */
|
|
156
|
-
REQUEST_HEADER_FIELDS_TOO_LARGE: HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
|
|
157
|
-
/** The client closed the connection with the server before the request was completed (444) */
|
|
158
|
-
CONNECTION_CLOSED_WITHOUT_RESPONSE: HTTP_CONNECTION_CLOSED_WITHOUT_RESPONSE,
|
|
159
|
-
/** The client requested an unavailable legal action (451) */
|
|
160
|
-
UNAVAILABLE_FOR_LEGAL_REASONS: HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
|
|
161
|
-
/** The server encountered an internal error and was unable to complete the request (500) */
|
|
162
|
-
INTERNAL_SERVER_ERROR: HTTP_INTERNAL_SERVER_ERROR,
|
|
163
|
-
/** The request method is not supported by the server and cannot be handled (501) */
|
|
164
|
-
NOT_IMPLEMENTED: HTTP_NOT_IMPLEMENTED,
|
|
165
|
-
/** The server, while acting as a gateway or proxy, received an invalid response from the upstream server (502) */
|
|
166
|
-
BAD_GATEWAY: HTTP_BAD_GATEWAY,
|
|
167
|
-
/** The server is not ready to handle the request, typically due to temporary overload or maintenance (503) */
|
|
168
|
-
SERVICE_UNAVAILABLE: HTTP_SERVICE_UNAVAILABLE,
|
|
169
|
-
/** The server, while acting as a gateway or proxy, did not get a response in time from the upstream server (504) */
|
|
170
|
-
GATEWAY_TIMEOUT: HTTP_GATEWAY_TIMEOUT,
|
|
171
|
-
};
|
|
172
84
|
/**
|
|
173
85
|
* Returns the reason phrase corresponding to the given HTTP status code.
|
|
174
86
|
* This is useful for converting status codes into human-readable messages.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ExpressApplication } from './utils/express.utils';
|
|
2
1
|
import { DeleteEndpoint, GetEndpoint, PatchEndpoint, PostEndpoint, PutEndpoint, RequestContext, ResponseOrValue } from './router';
|
|
2
|
+
import { ExpressApplication } from './utils/express.utils';
|
|
3
3
|
/**
|
|
4
4
|
* Helper utility for organizing and mounting routes.
|
|
5
5
|
* Provides a fluent interface for registering multiple handlers.
|
package/dist/esm/router.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { callValueAssertion, getMessageFromError, validateObject, } from '@fishka/assertions';
|
|
2
2
|
import * as url from 'url';
|
|
3
|
-
import { HttpError, URL_PARAMETER_INFO
|
|
4
|
-
import { HTTP_BAD_REQUEST, HTTP_OK } from './http-status-codes';
|
|
3
|
+
import { assertHttp, HttpError, URL_PARAMETER_INFO } from './api.types';
|
|
5
4
|
import { catchRouteErrors } from './error-handling';
|
|
5
|
+
import { HTTP_BAD_REQUEST, HTTP_OK } from './http-status-codes';
|
|
6
6
|
import { getRequestLocalStorage } from './thread-local/thread-local-storage';
|
|
7
7
|
import { wrapAsApiResponse } from './utils/conversion.utils';
|
|
8
8
|
// ============================================================================
|
|
@@ -186,7 +186,7 @@ function newRequestContext(requestBody, req, res) {
|
|
|
186
186
|
params: {
|
|
187
187
|
get: (key) => {
|
|
188
188
|
const value = req.params[key];
|
|
189
|
-
|
|
189
|
+
assertHttp(value, HTTP_BAD_REQUEST, `Path parameter '${key}' not found`);
|
|
190
190
|
return value;
|
|
191
191
|
},
|
|
192
192
|
tryGet: (key) => req.params[key],
|