@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 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, '400: name required') },
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: (val) => {
58
+ validator: val => {
59
59
  assertString(val);
60
- if (!val.startsWith('org-')) throw new Error('400: Invalid Organization ID');
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
- createRouteTable,
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: (val) => assertString(val)
130
+ validator: val => assertString(val),
123
131
  });
124
132
 
125
133
  // 4. Define routes
@@ -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 a condition is true, throwing an HttpError with the specified status code if false.
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 condition - The condition to check. If false, an HttpError will be thrown.
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 !== null, HTTP_NOT_FOUND, 'User not found');
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(condition: boolean, status: number, message: string): asserts condition;
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;
@@ -18,10 +18,10 @@ class HttpError extends Error {
18
18
  }
19
19
  exports.HttpError = HttpError;
20
20
  /**
21
- * Asserts that a condition is true, throwing an HttpError with the specified status code if false.
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 condition - The condition to check. If false, an HttpError will be thrown.
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 !== null, HTTP_NOT_FOUND, 'User not found');
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(condition, status, message) {
52
- (0, assertions_1.assertTruthy)(condition, () => new HttpError(status, message));
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
- (0, assertions_1.assertString)(name, 'Url parameter name must be a string');
73
- assertHttp(exports.URL_PARAMETER_INFO[name] !== undefined, http_status_codes_1.HTTP_BAD_REQUEST, `Invalid URL parameter: '${name}'. Please register it using 'registerUrlParameter('${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.
@@ -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, assertions_1.assertTruthy)(value, `Path parameter '${key}' not found`);
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],
@@ -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 a condition is true, throwing an HttpError with the specified status code if false.
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 condition - The condition to check. If false, an HttpError will be thrown.
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 !== null, HTTP_NOT_FOUND, 'User not found');
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(condition: boolean, status: number, message: string): asserts condition;
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;
@@ -1,4 +1,4 @@
1
- import { assertString, assertTruthy } from '@fishka/assertions';
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 a condition is true, throwing an HttpError with the specified status code if false.
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 condition - The condition to check. If false, an HttpError will be thrown.
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 !== null, HTTP_NOT_FOUND, 'User not found');
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(condition, status, message) {
44
- assertTruthy(condition, () => new HttpError(status, message));
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
- assertString(name, 'Url parameter name must be a string');
65
- assertHttp(URL_PARAMETER_INFO[name] !== undefined, HTTP_BAD_REQUEST, `Invalid URL parameter: '${name}'. Please register it using 'registerUrlParameter('${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.
@@ -1,8 +1,8 @@
1
- import { assertTruthy, callValueAssertion, getMessageFromError, validateObject, } from '@fishka/assertions';
1
+ import { callValueAssertion, getMessageFromError, validateObject, } from '@fishka/assertions';
2
2
  import * as url from 'url';
3
- import { HttpError, URL_PARAMETER_INFO, assertHttp } from './api.types';
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
- assertTruthy(value, `Path parameter '${key}' not found`);
189
+ assertHttp(value, HTTP_BAD_REQUEST, `Path parameter '${key}' not found`);
190
190
  return value;
191
191
  },
192
192
  tryGet: (key) => req.params[key],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishka/express",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Express.js extension with built-in validation, and type safety",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",