@fishka/express 0.9.8 → 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/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/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
|
}
|
|
@@ -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
|
}
|
|
@@ -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],
|