@fishka/express 0.9.16 → 0.9.18
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 +67 -48
- package/dist/cjs/api.types.d.ts +2 -14
- package/dist/cjs/api.types.js.map +1 -1
- package/dist/cjs/config.d.ts +8 -1
- package/dist/cjs/config.js +1 -0
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/error-handling.d.ts +1 -1
- package/dist/cjs/error-handling.js +8 -10
- package/dist/cjs/error-handling.js.map +1 -1
- package/dist/cjs/route-table.d.ts +20 -21
- package/dist/cjs/route-table.js +11 -20
- package/dist/cjs/route-table.js.map +1 -1
- package/dist/cjs/router.d.ts +34 -36
- package/dist/cjs/router.js +109 -106
- package/dist/cjs/router.js.map +1 -1
- package/dist/cjs/thread-local/thread-local-storage-middleware.js +7 -1
- package/dist/cjs/thread-local/thread-local-storage-middleware.js.map +1 -1
- package/dist/cjs/utils/conversion.utils.d.ts +0 -8
- package/dist/cjs/utils/conversion.utils.js +0 -14
- package/dist/cjs/utils/conversion.utils.js.map +1 -1
- package/dist/cjs/utils/type-validators.d.ts +22 -15
- package/dist/cjs/utils/type-validators.js +25 -14
- package/dist/cjs/utils/type-validators.js.map +1 -1
- package/dist/esm/api.types.d.ts +2 -14
- package/dist/esm/api.types.js.map +1 -1
- package/dist/esm/config.d.ts +8 -1
- package/dist/esm/config.js +1 -0
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/error-handling.d.ts +1 -1
- package/dist/esm/error-handling.js +8 -10
- package/dist/esm/error-handling.js.map +1 -1
- package/dist/esm/route-table.d.ts +20 -21
- package/dist/esm/route-table.js +12 -20
- package/dist/esm/route-table.js.map +1 -1
- package/dist/esm/router.d.ts +34 -36
- package/dist/esm/router.js +109 -100
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/thread-local/thread-local-storage-middleware.js +7 -1
- package/dist/esm/thread-local/thread-local-storage-middleware.js.map +1 -1
- package/dist/esm/utils/conversion.utils.d.ts +0 -8
- package/dist/esm/utils/conversion.utils.js +0 -13
- package/dist/esm/utils/conversion.utils.js.map +1 -1
- package/dist/esm/utils/type-validators.d.ts +22 -15
- package/dist/esm/utils/type-validators.js +21 -11
- package/dist/esm/utils/type-validators.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,22 +12,19 @@ npm install @fishka/express
|
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import express from 'express';
|
|
15
|
-
import {
|
|
15
|
+
import { RouteTable, transform, toInt } from '@fishka/express';
|
|
16
16
|
import { assertString } from '@fishka/assertions';
|
|
17
17
|
|
|
18
18
|
const app = express();
|
|
19
19
|
app.use(express.json());
|
|
20
20
|
|
|
21
|
-
const routes =
|
|
21
|
+
const routes = new RouteTable(app);
|
|
22
22
|
|
|
23
23
|
// GET /users/:id - with typed path params
|
|
24
|
-
routes.get('users/:id', {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
name: 'John',
|
|
29
|
-
}),
|
|
30
|
-
});
|
|
24
|
+
routes.get('users/:id', async ctx => ({
|
|
25
|
+
id: ctx.path('id', transform(toInt())), // number - validated inline
|
|
26
|
+
name: 'John',
|
|
27
|
+
}));
|
|
31
28
|
|
|
32
29
|
// GET /users - list all users
|
|
33
30
|
routes.get('users', async () => [
|
|
@@ -36,10 +33,10 @@ routes.get('users', async () => [
|
|
|
36
33
|
]);
|
|
37
34
|
|
|
38
35
|
// POST /users - with body validation
|
|
39
|
-
routes.post
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
36
|
+
routes.post('users', async ctx => ({
|
|
37
|
+
id: 1,
|
|
38
|
+
name: ctx.body({ name: v => assertString(v, 'name required') }).name,
|
|
39
|
+
}));
|
|
43
40
|
|
|
44
41
|
// DELETE /users/:id
|
|
45
42
|
routes.delete('users/:id', async () => {});
|
|
@@ -49,38 +46,37 @@ app.listen(3000);
|
|
|
49
46
|
|
|
50
47
|
## URL Parameter Validation
|
|
51
48
|
|
|
52
|
-
Use `
|
|
49
|
+
Use `transform()` to validate and transform path/query parameters. All operators are composable:
|
|
53
50
|
|
|
54
51
|
```typescript
|
|
55
|
-
import {
|
|
56
|
-
|
|
57
|
-
routes.get('users/:id', {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
sort: param(oneOf('asc', 'desc')), // enum
|
|
65
|
-
search: param(minLength(3)), // string min 3 chars
|
|
66
|
-
},
|
|
67
|
-
run: async ctx => ({
|
|
68
|
-
id: ctx.path.id, // number
|
|
69
|
-
page: ctx.query.page, // number
|
|
70
|
-
sort: ctx.query.sort, // 'asc' | 'desc'
|
|
71
|
-
}),
|
|
72
|
-
});
|
|
52
|
+
import { transform, toInt, minLength, matches, min, range, oneOf } from '@fishka/express';
|
|
53
|
+
|
|
54
|
+
routes.get('users/:id', async ctx => ({
|
|
55
|
+
id: ctx.path('id', transform(toInt())), // string → number (required)
|
|
56
|
+
page: ctx.query('page', transform(toInt(), min(1))), // number >= 1, optional
|
|
57
|
+
limit: ctx.query('limit', transform(toInt(), range(1, 100))), // number 1-100, optional
|
|
58
|
+
sort: ctx.query('sort', transform(oneOf('asc', 'desc'))), // enum, optional
|
|
59
|
+
search: ctx.query('search', transform(minLength(3))), // string min 3 chars, optional
|
|
60
|
+
}));
|
|
73
61
|
```
|
|
74
62
|
|
|
63
|
+
### Without Validators
|
|
64
|
+
|
|
65
|
+
- `ctx.path('name')` - returns string (throws 400 if missing)
|
|
66
|
+
- `ctx.query('name')` - returns string | undefined (returns undefined if missing/empty)
|
|
67
|
+
- Validators receive raw values (including undefined/null/empty) and can enforce requiredness
|
|
68
|
+
|
|
75
69
|
### Available Operators
|
|
76
70
|
|
|
77
71
|
**Transformations (string → T):**
|
|
72
|
+
|
|
78
73
|
- `toInt()` - parse to integer
|
|
79
74
|
- `toNumber()` - parse to number
|
|
80
75
|
- `toBool()` - parse 'true'/'false' to boolean
|
|
81
76
|
- `oneOf('a', 'b')` - enum values
|
|
82
77
|
|
|
83
78
|
**String validators:**
|
|
79
|
+
|
|
84
80
|
- `minLength(n)` - minimum length
|
|
85
81
|
- `maxLength(n)` - maximum length
|
|
86
82
|
- `matches(/regex/)` - regex match
|
|
@@ -88,28 +84,30 @@ routes.get('users/:id', {
|
|
|
88
84
|
- `lowercase` / `uppercase` - case transform
|
|
89
85
|
|
|
90
86
|
**Number validators:**
|
|
87
|
+
|
|
91
88
|
- `min(n)` - minimum value
|
|
92
89
|
- `max(n)` - maximum value
|
|
93
90
|
- `range(min, max)` - value range
|
|
94
91
|
|
|
95
92
|
**Generic:**
|
|
96
|
-
|
|
93
|
+
|
|
94
|
+
- `transform(...ops)` - chain of validators/transformers
|
|
95
|
+
- `assert(predicate, msg)` - custom validation with predicate
|
|
96
|
+
- `validator(fn)` - custom validator returning string|undefined
|
|
97
97
|
- `map(fn)` - transform value
|
|
98
98
|
|
|
99
99
|
### Optional Parameters
|
|
100
100
|
|
|
101
|
-
Use `
|
|
101
|
+
Query parameters are optional by default. Use `ctx.query()` without a validator to get optional string values:
|
|
102
102
|
|
|
103
103
|
```typescript
|
|
104
|
-
import {
|
|
104
|
+
import { transform, toInt } from '@fishka/express';
|
|
105
105
|
|
|
106
|
-
routes.get('users', {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const page = ctx.query.page ?? 1;
|
|
112
|
-
},
|
|
106
|
+
routes.get('users', async ctx => {
|
|
107
|
+
const page = ctx.query('page', transform(toInt())) ?? 1; // number | undefined
|
|
108
|
+
const search = ctx.query('search'); // string | undefined
|
|
109
|
+
|
|
110
|
+
return { page, search };
|
|
113
111
|
});
|
|
114
112
|
```
|
|
115
113
|
|
|
@@ -163,7 +161,7 @@ Full initialization with TLS context, validation, and error handling:
|
|
|
163
161
|
|
|
164
162
|
```typescript
|
|
165
163
|
import express from 'express';
|
|
166
|
-
import {
|
|
164
|
+
import { RouteTable, createTlsMiddleware, catchAllMiddleware, transform, toInt } from '@fishka/express';
|
|
167
165
|
|
|
168
166
|
const app = express();
|
|
169
167
|
|
|
@@ -171,17 +169,18 @@ const app = express();
|
|
|
171
169
|
app.use(express.json());
|
|
172
170
|
|
|
173
171
|
// 2. Initialize TLS context (Request IDs, etc.)
|
|
172
|
+
// Note: Request ID functionality is disabled by default.
|
|
173
|
+
// To enable it, call configureExpressApi({ requestIdHeader: 'x-request-id' }) first.
|
|
174
174
|
app.use(createTlsMiddleware());
|
|
175
175
|
|
|
176
176
|
// 3. Define routes with typed parameters
|
|
177
|
-
const routes =
|
|
177
|
+
const routes = new RouteTable(app);
|
|
178
178
|
|
|
179
179
|
routes.get('health', async () => ({ status: 'UP' }));
|
|
180
180
|
|
|
181
|
-
routes.get('users/:id', {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
});
|
|
181
|
+
routes.get('users/:id', async ctx => ({
|
|
182
|
+
id: ctx.path('id', transform(toInt())),
|
|
183
|
+
}));
|
|
185
184
|
|
|
186
185
|
// 4. Error handler - catches middleware/parsing errors
|
|
187
186
|
app.use(catchAllMiddleware);
|
|
@@ -189,6 +188,26 @@ app.use(catchAllMiddleware);
|
|
|
189
188
|
app.listen(3000);
|
|
190
189
|
```
|
|
191
190
|
|
|
191
|
+
## Configuration
|
|
192
|
+
|
|
193
|
+
You can configure global settings using `configureExpressApi`:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { configureExpressApi } from '@fishka/express';
|
|
197
|
+
|
|
198
|
+
// Request ID configuration (disabled by default)
|
|
199
|
+
configureExpressApi({
|
|
200
|
+
// Enable request ID with custom header name
|
|
201
|
+
requestIdHeader: 'x-request-id', // or 'x-correlation-id', 'trace-id', etc.
|
|
202
|
+
|
|
203
|
+
// Whether to trust request ID from client headers
|
|
204
|
+
trustRequestIdHeader: true, // default: true
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// By default, request ID functionality is disabled.
|
|
208
|
+
// To enable it, you must set requestIdHeader.
|
|
209
|
+
```
|
|
210
|
+
|
|
192
211
|
## Process Handlers
|
|
193
212
|
|
|
194
213
|
Handle uncaught errors and graceful shutdown in one place:
|
package/dist/cjs/api.types.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
/** Validator function that validates and returns typed value */
|
|
2
|
-
export type
|
|
3
|
-
/** Map of param name to type validator */
|
|
4
|
-
export type TypedValidatorMap = Record<string, TypeValidator<unknown>>;
|
|
5
|
-
/** Infer validated types from validator map */
|
|
6
|
-
export type InferValidated<T extends TypedValidatorMap | undefined> = T extends TypedValidatorMap ? {
|
|
7
|
-
[K in keyof T]: ReturnType<T[K]>;
|
|
8
|
-
} : Record<string, string>;
|
|
1
|
+
/** Validator function that validates and returns a typed value */
|
|
2
|
+
export type ParamValidator<T> = (value: unknown) => T;
|
|
9
3
|
export declare class HttpError extends Error {
|
|
10
4
|
readonly status: number;
|
|
11
5
|
readonly details?: Record<string, unknown> | undefined;
|
|
@@ -46,12 +40,6 @@ export declare function assertHttp(value: unknown, status: number, message: stri
|
|
|
46
40
|
export interface ApiResponse<ResponseEntity = unknown> {
|
|
47
41
|
/** Result of the call. A single entity for non-paginated ${by-id} requests or an array for list queries. */
|
|
48
42
|
result: ResponseEntity;
|
|
49
|
-
/**
|
|
50
|
-
* Unique ID of the request.
|
|
51
|
-
* Automatically added to every API response.
|
|
52
|
-
* May be passed via 'x-request-id' header from client.
|
|
53
|
-
*/
|
|
54
|
-
requestId?: string;
|
|
55
43
|
/**
|
|
56
44
|
* Response status code. Same as HTTP response status.
|
|
57
45
|
* Default: 200 for successful responses or 500 for internal server errors.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.types.js","sourceRoot":"","sources":["../../src/api.types.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"api.types.js","sourceRoot":"","sources":["../../src/api.types.ts"],"names":[],"mappings":";;;AAgDA,gCAEC;AAqBD,4BAEC;AAzED,mDAAkD;AAKlD,MAAa,SAAU,SAAQ,KAAK;IAClC,YACkB,MAAc,EAC9B,OAAe,EACC,OAAiC;QAEjD,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,WAAM,GAAN,MAAM,CAAQ;QAEd,YAAO,GAAP,OAAO,CAA0B;QAGjD,qDAAqD;QACrD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;CACF;AAVD,8BAUC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAgB,UAAU,CAAC,KAAc,EAAE,MAAc,EAAE,OAAe;IACxE,IAAA,yBAAY,EAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAoBD,gFAAgF;AAChF,SAAgB,QAAQ,CAAc,MAAS;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
package/dist/cjs/config.d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export interface GlobalExpressApiConfig {
|
|
2
|
+
/**
|
|
3
|
+
* Header name for request ID. If not set, request ID functionality is disabled.
|
|
4
|
+
* When set, enables request ID generation and propagation.
|
|
5
|
+
* Default: undefined (disabled)
|
|
6
|
+
*/
|
|
7
|
+
requestIdHeader?: string;
|
|
2
8
|
/**
|
|
3
9
|
* Whether to trust and use the request ID from the request header.
|
|
4
|
-
* If true, the middleware will look for
|
|
10
|
+
* If true, the middleware will look for the request ID header and use it.
|
|
5
11
|
* If false, a new UUID will always be generated.
|
|
12
|
+
* Only applies when requestIdHeader is set.
|
|
6
13
|
* Default: true
|
|
7
14
|
*/
|
|
8
15
|
trustRequestIdHeader: boolean;
|
package/dist/cjs/config.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.configureExpressApi = configureExpressApi;
|
|
|
4
4
|
exports.getExpressApiConfig = getExpressApiConfig;
|
|
5
5
|
exports.resetExpressApiConfig = resetExpressApiConfig;
|
|
6
6
|
const defaultConfig = {
|
|
7
|
+
requestIdHeader: undefined,
|
|
7
8
|
trustRequestIdHeader: true,
|
|
8
9
|
};
|
|
9
10
|
let currentConfig = { ...defaultConfig };
|
package/dist/cjs/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";;AA6BA,kDAEC;AAKD,kDAEC;AAMD,sDAEC;AA5BD,MAAM,aAAa,GAA2B;IAC5C,eAAe,EAAE,SAAS;IAC1B,oBAAoB,EAAE,IAAI;CAC3B,CAAC;AAEF,IAAI,aAAa,GAA2B,EAAE,GAAG,aAAa,EAAE,CAAC;AAEjE;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,MAAuC;IACzE,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAA4B,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB;IACjC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB;IACnC,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { ExpressFunction, ExpressRequest, ExpressResponse } from './utils/expres
|
|
|
3
3
|
/**
|
|
4
4
|
* @Internal
|
|
5
5
|
* Wraps a route handler to catch and convert errors to API responses.
|
|
6
|
-
* Applied automatically to all routes registered via
|
|
6
|
+
* Applied automatically to all routes registered via RouteTable.
|
|
7
7
|
*
|
|
8
8
|
* Catches:
|
|
9
9
|
* - Errors thrown in validators ($path, $query, $body)
|
|
@@ -5,22 +5,18 @@ exports.catchAllMiddleware = catchAllMiddleware;
|
|
|
5
5
|
exports.installProcessHandlers = installProcessHandlers;
|
|
6
6
|
const assertions_1 = require("@fishka/assertions");
|
|
7
7
|
const api_types_1 = require("./api.types");
|
|
8
|
+
const config_1 = require("./config");
|
|
8
9
|
const http_status_codes_1 = require("./http-status-codes");
|
|
9
10
|
const thread_local_storage_1 = require("./thread-local/thread-local-storage");
|
|
10
|
-
const conversion_utils_1 = require("./utils/conversion.utils");
|
|
11
11
|
/**
|
|
12
12
|
* Converts any error into a standardized API response format.
|
|
13
13
|
* - HttpError: Uses the error's status code and message
|
|
14
14
|
* - Other errors: Returns 500 with the error message or 'Internal error'
|
|
15
|
-
* Attaches requestId from thread-local storage if available.
|
|
16
15
|
*/
|
|
17
16
|
function buildApiResponse(error) {
|
|
18
|
-
const tls = (0, thread_local_storage_1.getRequestLocalStorage)();
|
|
19
|
-
const requestId = tls?.requestId;
|
|
20
17
|
let response;
|
|
21
18
|
if (error instanceof api_types_1.HttpError) {
|
|
22
19
|
response = {
|
|
23
|
-
...(0, conversion_utils_1.wrapAsApiResponse)(undefined),
|
|
24
20
|
error: error.message,
|
|
25
21
|
status: error.status,
|
|
26
22
|
details: error.details,
|
|
@@ -29,20 +25,16 @@ function buildApiResponse(error) {
|
|
|
29
25
|
else {
|
|
30
26
|
const errorMessage = (0, assertions_1.getMessageFromError)(error, '');
|
|
31
27
|
response = {
|
|
32
|
-
...(0, conversion_utils_1.wrapAsApiResponse)(undefined),
|
|
33
28
|
error: errorMessage && errorMessage.length > 0 ? errorMessage : 'Internal error',
|
|
34
29
|
status: http_status_codes_1.HTTP_INTERNAL_SERVER_ERROR,
|
|
35
30
|
};
|
|
36
31
|
}
|
|
37
|
-
if (requestId) {
|
|
38
|
-
response.requestId = requestId;
|
|
39
|
-
}
|
|
40
32
|
return response;
|
|
41
33
|
}
|
|
42
34
|
/**
|
|
43
35
|
* @Internal
|
|
44
36
|
* Wraps a route handler to catch and convert errors to API responses.
|
|
45
|
-
* Applied automatically to all routes registered via
|
|
37
|
+
* Applied automatically to all routes registered via RouteTable.
|
|
46
38
|
*
|
|
47
39
|
* Catches:
|
|
48
40
|
* - Errors thrown in validators ($path, $query, $body)
|
|
@@ -61,6 +53,12 @@ function catchRouteErrors(fn) {
|
|
|
61
53
|
if (apiResponse.status >= http_status_codes_1.HTTP_INTERNAL_SERVER_ERROR) {
|
|
62
54
|
console.error(`catchRouteErrors: ${req.path}`, error);
|
|
63
55
|
}
|
|
56
|
+
// Добавляем requestId в заголовки, если он есть и функция включена
|
|
57
|
+
const tls = (0, thread_local_storage_1.getRequestLocalStorage)();
|
|
58
|
+
const headerName = (0, config_1.getExpressApiConfig)().requestIdHeader;
|
|
59
|
+
if (tls?.requestId && headerName) {
|
|
60
|
+
res.setHeader(headerName, tls.requestId);
|
|
61
|
+
}
|
|
64
62
|
res.status(apiResponse.status);
|
|
65
63
|
res.send(apiResponse);
|
|
66
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/error-handling.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/error-handling.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DeleteEndpoint, GetEndpoint, PatchEndpoint, PostEndpoint, PutEndpoint, RequestContext, ResponseOrValue } from './router';
|
|
1
|
+
import { DeleteEndpoint, GetEndpoint, PatchEndpoint, PostEndpoint, PutEndpoint, RequestContext } from './router';
|
|
3
2
|
import { ExpressRouter } from './utils/express.utils';
|
|
4
3
|
/**
|
|
5
4
|
* Helper utility for organizing and mounting routes.
|
|
@@ -8,24 +7,24 @@ import { ExpressRouter } from './utils/express.utils';
|
|
|
8
7
|
export declare class RouteTable {
|
|
9
8
|
private readonly app;
|
|
10
9
|
constructor(app: ExpressRouter);
|
|
11
|
-
/** Register GET endpoint
|
|
12
|
-
get<Result
|
|
13
|
-
/** Register GET endpoint with function shorthand. */
|
|
14
|
-
get<Result>(path: string, run: (ctx: RequestContext) =>
|
|
15
|
-
/** Register POST endpoint
|
|
16
|
-
post<
|
|
17
|
-
/** Register
|
|
18
|
-
|
|
19
|
-
/** Register
|
|
20
|
-
|
|
21
|
-
/** Register
|
|
22
|
-
|
|
23
|
-
/** Register
|
|
10
|
+
/** Register a GET endpoint. */
|
|
11
|
+
get<Result>(path: string, endpoint: GetEndpoint<Result>): this;
|
|
12
|
+
/** Register a GET endpoint with function shorthand. */
|
|
13
|
+
get<Result>(path: string, run: (ctx: RequestContext) => Result | Promise<Result>): this;
|
|
14
|
+
/** Register a POST endpoint. */
|
|
15
|
+
post<Result = void>(path: string, endpoint: PostEndpoint<Result>): this;
|
|
16
|
+
/** Register a POST endpoint with function shorthand. */
|
|
17
|
+
post<Result = void>(path: string, run: (ctx: RequestContext) => Result | Promise<Result>): this;
|
|
18
|
+
/** Register a PATCH endpoint. */
|
|
19
|
+
patch<Result = void>(path: string, endpoint: PatchEndpoint<Result>): this;
|
|
20
|
+
/** Register a PATCH endpoint with function shorthand. */
|
|
21
|
+
patch<Result = void>(path: string, run: (ctx: RequestContext) => Result | Promise<Result>): this;
|
|
22
|
+
/** Register a PUT endpoint. */
|
|
23
|
+
put<Result = void>(path: string, endpoint: PutEndpoint<Result>): this;
|
|
24
|
+
/** Register a PUT endpoint with function shorthand. */
|
|
25
|
+
put<Result = void>(path: string, run: (ctx: RequestContext) => Result | Promise<Result>): this;
|
|
26
|
+
/** Register a DELETE endpoint with a full endpoint object. */
|
|
27
|
+
delete(path: string, endpoint: DeleteEndpoint): this;
|
|
28
|
+
/** Register a DELETE endpoint with function shorthand. */
|
|
24
29
|
delete(path: string, run: (ctx: RequestContext) => void | Promise<void>): this;
|
|
25
30
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Factory function to create a new route table.
|
|
28
|
-
* @param app Express application instance
|
|
29
|
-
* @returns RouteTable instance with fluent API
|
|
30
|
-
*/
|
|
31
|
-
export declare function createRouteTable(app: ExpressRouter): RouteTable;
|
package/dist/cjs/route-table.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RouteTable = void 0;
|
|
4
|
-
exports.createRouteTable = createRouteTable;
|
|
5
4
|
const router_1 = require("./router");
|
|
6
5
|
/**
|
|
7
6
|
* Helper utility for organizing and mounting routes.
|
|
@@ -13,37 +12,29 @@ class RouteTable {
|
|
|
13
12
|
}
|
|
14
13
|
get(path, endpointOrRun) {
|
|
15
14
|
const endpoint = typeof endpointOrRun === 'function' ? { run: endpointOrRun } : endpointOrRun;
|
|
16
|
-
(0, router_1.
|
|
15
|
+
(0, router_1.mount)(this.app, { method: 'get', endpoint: endpoint, path });
|
|
17
16
|
return this;
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
(0, router_1.
|
|
18
|
+
post(path, endpointOrRun) {
|
|
19
|
+
const endpoint = typeof endpointOrRun === 'function' ? { run: endpointOrRun } : endpointOrRun;
|
|
20
|
+
(0, router_1.mount)(this.app, { method: 'post', endpoint: endpoint, path });
|
|
22
21
|
return this;
|
|
23
22
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
(0, router_1.
|
|
23
|
+
patch(path, endpointOrRun) {
|
|
24
|
+
const endpoint = typeof endpointOrRun === 'function' ? { run: endpointOrRun } : endpointOrRun;
|
|
25
|
+
(0, router_1.mount)(this.app, { method: 'patch', endpoint: endpoint, path });
|
|
27
26
|
return this;
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
(0, router_1.
|
|
28
|
+
put(path, endpointOrRun) {
|
|
29
|
+
const endpoint = typeof endpointOrRun === 'function' ? { run: endpointOrRun } : endpointOrRun;
|
|
30
|
+
(0, router_1.mount)(this.app, { method: 'put', endpoint: endpoint, path });
|
|
32
31
|
return this;
|
|
33
32
|
}
|
|
34
33
|
delete(path, endpointOrRun) {
|
|
35
34
|
const endpoint = typeof endpointOrRun === 'function' ? { run: endpointOrRun } : endpointOrRun;
|
|
36
|
-
(0, router_1.
|
|
35
|
+
(0, router_1.mount)(this.app, { method: 'delete', endpoint: endpoint, path });
|
|
37
36
|
return this;
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
exports.RouteTable = RouteTable;
|
|
41
|
-
/**
|
|
42
|
-
* Factory function to create a new route table.
|
|
43
|
-
* @param app Express application instance
|
|
44
|
-
* @returns RouteTable instance with fluent API
|
|
45
|
-
*/
|
|
46
|
-
function createRouteTable(app) {
|
|
47
|
-
return new RouteTable(app);
|
|
48
|
-
}
|
|
49
40
|
//# sourceMappingURL=route-table.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":";;;AAAA,qCAAwH;AAGxH;;;GAGG;AACH,MAAa,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAQnD,GAAG,CACD,IAAY,EACZ,aAAwF;QAExF,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,cAAK,EAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAgC,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;IACd,CAAC;IAQD,IAAI,CACF,IAAY,EACZ,aAAyF;QAEzF,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,cAAK,EAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAiC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvF,OAAO,IAAI,CAAC;IACd,CAAC;IAQD,KAAK,CACH,IAAY,EACZ,aAA0F;QAE1F,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,cAAK,EAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAkC,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,OAAO,IAAI,CAAC;IACd,CAAC;IAQD,GAAG,CACD,IAAY,EACZ,aAAwF;QAExF,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,cAAK,EAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAgC,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;IACd,CAAC;IAQD,MAAM,CAAC,IAAY,EAAE,aAA+E;QAClG,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,cAAK,EAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAA0B,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA1ED,gCA0EC"}
|
package/dist/cjs/router.d.ts
CHANGED
|
@@ -1,28 +1,43 @@
|
|
|
1
|
-
import { Assertion
|
|
2
|
-
import {
|
|
1
|
+
import { Assertion } from '@fishka/assertions';
|
|
2
|
+
import { ParamValidator } from './api.types';
|
|
3
3
|
import { AuthUser } from './auth/auth.types';
|
|
4
4
|
import { ExpressRequest, ExpressResponse, ExpressRouter } from './utils/express.utils';
|
|
5
|
-
/** Express API allows handlers to return a response in the raw form. */
|
|
6
|
-
export type ResponseOrValue<ResponseEntity> = ApiResponse<ResponseEntity> | ResponseEntity;
|
|
7
5
|
/**
|
|
8
6
|
* Generic middleware hook for endpoint execution.
|
|
9
7
|
* Allows custom logic like transaction management, authorization checks, etc.
|
|
10
8
|
*/
|
|
11
9
|
export type EndpointMiddleware<Context = RequestContext> = (run: () => Promise<unknown>, context: Context) => Promise<unknown>;
|
|
12
10
|
/** Generic request context passed to all handlers. Database-agnostic and extensible. */
|
|
13
|
-
export interface RequestContext
|
|
14
|
-
/** Parsed and validated request body (for POST/PATCH/PUT handlers). */
|
|
15
|
-
body: Body;
|
|
11
|
+
export interface RequestContext {
|
|
16
12
|
/** Express Request object. */
|
|
17
13
|
req: ExpressRequest;
|
|
18
14
|
/** Express Response object. */
|
|
19
15
|
res: ExpressResponse;
|
|
20
16
|
/** Authenticated user (if any). Populated by auth middleware. */
|
|
21
17
|
authUser?: AuthUser;
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Get and validate a path parameter.
|
|
20
|
+
* @param name - Name of the path parameter
|
|
21
|
+
* @param validator - Optional validator. If not provided, returns the raw string value.
|
|
22
|
+
* @returns Validated value of type T (or string if no validator)
|
|
23
|
+
* @throws {HttpError} 400 Bad Request if validation fails
|
|
24
|
+
*/
|
|
25
|
+
path<T = string>(name: string, validator?: ParamValidator<T>): T;
|
|
26
|
+
/**
|
|
27
|
+
* Get and validate a query parameter.
|
|
28
|
+
* @param name - Name of the query parameter
|
|
29
|
+
* @param validator - Optional validator. If not provided, returns the raw string value or undefined.
|
|
30
|
+
* @returns Validated value of type T, or undefined if parameter is not present
|
|
31
|
+
* @throws {HttpError} 400 Bad Request if validation fails
|
|
32
|
+
*/
|
|
33
|
+
query<T = string>(name: string, validator?: ParamValidator<T>): T | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Get and validate the request body.
|
|
36
|
+
* @param validator - Validator function or object assertion
|
|
37
|
+
* @returns Validated body of type T
|
|
38
|
+
* @throws {HttpError} 400 Bad Request if validation fails
|
|
39
|
+
*/
|
|
40
|
+
body<T>(validator: Assertion<T>): T;
|
|
26
41
|
/**
|
|
27
42
|
* Generic state storage for middleware to attach data.
|
|
28
43
|
* Allows middleware to pass information to handlers and other middleware.
|
|
@@ -30,31 +45,24 @@ export interface RequestContext<Body = void, PathParams extends TypedValidatorMa
|
|
|
30
45
|
state: Map<string, unknown>;
|
|
31
46
|
}
|
|
32
47
|
/** Base interface with common endpoint properties. */
|
|
33
|
-
export interface EndpointBase<
|
|
34
|
-
/** Path parameter validators (typed). */
|
|
35
|
-
$path?: PathParams;
|
|
36
|
-
/** Query parameter validators (typed). */
|
|
37
|
-
$query?: QueryParams;
|
|
48
|
+
export interface EndpointBase<Result = unknown> {
|
|
38
49
|
/** Optional middleware to execute before the handler. */
|
|
39
50
|
middlewares?: Array<EndpointMiddleware>;
|
|
40
51
|
/** Handler function. Can be sync or async. */
|
|
41
|
-
run: (ctx: RequestContext
|
|
52
|
+
run: (ctx: RequestContext) => Result | Promise<Result>;
|
|
42
53
|
}
|
|
43
54
|
/** Descriptor for GET list routes. */
|
|
44
|
-
export type GetListEndpoint<ResultElementType
|
|
55
|
+
export type GetListEndpoint<ResultElementType> = EndpointBase<Array<ResultElementType>>;
|
|
45
56
|
/** Descriptor for GET routes. */
|
|
46
|
-
export type GetEndpoint<Result
|
|
57
|
+
export type GetEndpoint<Result> = EndpointBase<Result>;
|
|
47
58
|
/** Descriptor for POST routes. */
|
|
48
|
-
export
|
|
49
|
-
/** Request body validator. */
|
|
50
|
-
$body: Body extends object ? ObjectAssertion<Body> : Assertion<Body>;
|
|
51
|
-
}
|
|
59
|
+
export type PostEndpoint<Result = void> = EndpointBase<Result>;
|
|
52
60
|
/** Same as POST. Used for full object updates. */
|
|
53
|
-
export type PutEndpoint<
|
|
61
|
+
export type PutEndpoint<Result = void> = EndpointBase<Result>;
|
|
54
62
|
/** Same as PUT. While PUT is used for the whole object update, PATCH is used for a partial update. */
|
|
55
|
-
export type PatchEndpoint<
|
|
63
|
+
export type PatchEndpoint<Result = void> = EndpointBase<Result>;
|
|
56
64
|
/** Descriptor for DELETE routes. */
|
|
57
|
-
export type DeleteEndpoint
|
|
65
|
+
export type DeleteEndpoint = EndpointBase<void>;
|
|
58
66
|
/** Union type for all route registration info objects. */
|
|
59
67
|
export type RouteRegistrationInfo = ({
|
|
60
68
|
method: 'get';
|
|
@@ -74,15 +82,5 @@ export type RouteRegistrationInfo = ({
|
|
|
74
82
|
}) & {
|
|
75
83
|
path: string;
|
|
76
84
|
};
|
|
77
|
-
/** Registers a GET route. */
|
|
78
|
-
export declare const mountGet: (app: ExpressRouter, path: string, endpoint: GetEndpoint<unknown> | GetListEndpoint<unknown>) => void;
|
|
79
|
-
/** Registers a POST route. */
|
|
80
|
-
export declare const mountPost: <Body, Result>(app: ExpressRouter, path: string, endpoint: PostEndpoint<Body, Result>) => void;
|
|
81
|
-
/** Registers a PATCH route. */
|
|
82
|
-
export declare const mountPatch: <Body, Result>(app: ExpressRouter, path: string, endpoint: PatchEndpoint<Body, Result>) => void;
|
|
83
|
-
/** Registers a PUT route. */
|
|
84
|
-
export declare const mountPut: <Body, Result>(app: ExpressRouter, path: string, endpoint: PutEndpoint<Body, Result>) => void;
|
|
85
|
-
/** Registers a DELETE route. */
|
|
86
|
-
export declare const mountDelete: (app: ExpressRouter, path: string, endpoint: DeleteEndpoint) => void;
|
|
87
85
|
/** Mounts a route with the given method, endpoint, and path. */
|
|
88
86
|
export declare function mount(app: ExpressRouter, { method, endpoint, path }: RouteRegistrationInfo): void;
|