@fishka/express 0.9.12 → 0.9.14
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 +23 -1
- package/dist/cjs/error-handling.d.ts +72 -3
- package/dist/cjs/error-handling.js +107 -7
- package/dist/cjs/error-handling.js.map +1 -1
- package/dist/cjs/route-table.d.ts +2 -2
- package/dist/cjs/route-table.js.map +1 -1
- package/dist/cjs/router.d.ts +14 -14
- package/dist/cjs/router.js +7 -7
- package/dist/cjs/router.js.map +1 -1
- package/dist/esm/error-handling.d.ts +72 -3
- package/dist/esm/error-handling.js +106 -7
- package/dist/esm/error-handling.js.map +1 -1
- package/dist/esm/route-table.d.ts +2 -2
- package/dist/esm/route-table.js.map +1 -1
- package/dist/esm/router.d.ts +14 -14
- package/dist/esm/router.js +7 -7
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,12 +134,34 @@ registerUrlParameter('id', {
|
|
|
134
134
|
const routes = createRouteTable(app);
|
|
135
135
|
routes.get('health', async () => ({ status: 'UP' }));
|
|
136
136
|
|
|
137
|
-
// 5.
|
|
137
|
+
// 5. Error handler - catches middleware/parsing errors
|
|
138
|
+
// Can also be mounted per-path: app.use('/api', catchAllMiddleware)
|
|
138
139
|
app.use(catchAllMiddleware);
|
|
139
140
|
|
|
140
141
|
app.listen(3000);
|
|
141
142
|
```
|
|
142
143
|
|
|
144
|
+
## Process Handlers
|
|
145
|
+
|
|
146
|
+
Handle uncaught errors and graceful shutdown in one place:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { installProcessHandlers } from '@fishka/express';
|
|
150
|
+
|
|
151
|
+
installProcessHandlers({
|
|
152
|
+
// Error handlers
|
|
153
|
+
onUncaughtException: err => sendToMonitoring(err),
|
|
154
|
+
onUnhandledRejection: reason => sendToMonitoring(reason),
|
|
155
|
+
|
|
156
|
+
// Graceful shutdown
|
|
157
|
+
onShutdown: async () => {
|
|
158
|
+
await database.close();
|
|
159
|
+
await server.close();
|
|
160
|
+
},
|
|
161
|
+
shutdownTimeout: 15000, // Force exit after 15s (default: 10s)
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
143
165
|
## License
|
|
144
166
|
|
|
145
167
|
MIT
|
|
@@ -1,9 +1,78 @@
|
|
|
1
1
|
import { NextFunction } from 'express';
|
|
2
2
|
import { ExpressFunction, ExpressRequest, ExpressResponse } from './utils/express.utils';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* @Internal
|
|
5
|
+
* Wraps a route handler to catch and convert errors to API responses.
|
|
6
|
+
* Applied automatically to all routes registered via createRouteTable().
|
|
7
|
+
*
|
|
8
|
+
* Catches:
|
|
9
|
+
* - Errors thrown in validators ($path, $query, $body)
|
|
10
|
+
* - Errors thrown in the run() handler
|
|
11
|
+
* - Errors thrown in endpoint middlewares
|
|
12
|
+
*
|
|
13
|
+
* Logs errors to console (error level for 5xx).
|
|
14
|
+
*/
|
|
4
15
|
export declare function catchRouteErrors(fn: ExpressFunction): ExpressFunction;
|
|
5
16
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
17
|
+
* Express error-handling middleware (4 parameters) for catching errors.
|
|
18
|
+
* Can be mounted at any level - global, path-specific, or router-specific.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Global
|
|
22
|
+
* app.use(catchAllMiddleware);
|
|
23
|
+
*
|
|
24
|
+
* // Path-specific
|
|
25
|
+
* app.use('/api', catchAllMiddleware);
|
|
26
|
+
*
|
|
27
|
+
* // Router-specific
|
|
28
|
+
* const router = express.Router();
|
|
29
|
+
* router.use(catchAllMiddleware);
|
|
30
|
+
*
|
|
31
|
+
* Catches:
|
|
32
|
+
* - Errors from Express middleware (passed via next(error))
|
|
33
|
+
* - JSON parsing errors (SyntaxError) - returns 400
|
|
34
|
+
* - Any errors that escape catchRouteErrors
|
|
35
|
+
*
|
|
36
|
+
* Note: Individual routes are already wrapped with catchRouteErrors(),
|
|
37
|
+
* so this middleware primarily catches middleware and parsing errors.
|
|
8
38
|
*/
|
|
9
39
|
export declare function catchAllMiddleware(error: unknown, _: ExpressRequest, res: ExpressResponse, next: NextFunction): Promise<void>;
|
|
40
|
+
/** Options for installProcessHandlers(). */
|
|
41
|
+
export interface ProcessHandlersOptions {
|
|
42
|
+
/** Custom handler for uncaught exceptions. Called before default logging. */
|
|
43
|
+
onUncaughtException?: (error: Error) => void;
|
|
44
|
+
/** Custom handler for unhandled promise rejections. Called before default logging. */
|
|
45
|
+
onUnhandledRejection?: (reason: unknown) => void;
|
|
46
|
+
/** Async cleanup function called on shutdown signals. */
|
|
47
|
+
onShutdown?: () => Promise<void>;
|
|
48
|
+
/** Force exit timeout in ms if shutdown hangs. Default: 10000 */
|
|
49
|
+
shutdownTimeout?: number;
|
|
50
|
+
/** Signals to handle for graceful shutdown. Default: ['SIGTERM', 'SIGINT'] */
|
|
51
|
+
shutdownSignals?: NodeJS.Signals[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Installs process-level handlers for errors and graceful shutdown.
|
|
55
|
+
* Call once at application startup, before app.listen().
|
|
56
|
+
*
|
|
57
|
+
* Error handling:
|
|
58
|
+
* - Uncaught exceptions (sync throws outside Express middleware)
|
|
59
|
+
* - Unhandled promise rejections (forgotten await, missing .catch())
|
|
60
|
+
*
|
|
61
|
+
* Graceful shutdown:
|
|
62
|
+
* - SIGTERM (Docker/K8s/systemd stop)
|
|
63
|
+
* - SIGINT (Ctrl+C)
|
|
64
|
+
* - Timeout protection (force exit if shutdown hangs)
|
|
65
|
+
* - Double-shutdown prevention
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* installProcessHandlers({
|
|
69
|
+
* onUncaughtException: (error) => sendToMonitoring(error),
|
|
70
|
+
* onUnhandledRejection: (reason) => sendToMonitoring(reason),
|
|
71
|
+
* onShutdown: async () => {
|
|
72
|
+
* await database.close();
|
|
73
|
+
* await server.close();
|
|
74
|
+
* },
|
|
75
|
+
* shutdownTimeout: 15000,
|
|
76
|
+
* });
|
|
77
|
+
*/
|
|
78
|
+
export declare function installProcessHandlers(options?: ProcessHandlersOptions): void;
|
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.catchRouteErrors = catchRouteErrors;
|
|
4
4
|
exports.catchAllMiddleware = catchAllMiddleware;
|
|
5
|
+
exports.installProcessHandlers = installProcessHandlers;
|
|
5
6
|
const assertions_1 = require("@fishka/assertions");
|
|
6
7
|
const api_types_1 = require("./api.types");
|
|
7
8
|
const http_status_codes_1 = require("./http-status-codes");
|
|
8
9
|
const thread_local_storage_1 = require("./thread-local/thread-local-storage");
|
|
9
10
|
const conversion_utils_1 = require("./utils/conversion.utils");
|
|
11
|
+
/**
|
|
12
|
+
* Converts any error into a standardized API response format.
|
|
13
|
+
* - HttpError: Uses the error's status code and message
|
|
14
|
+
* - Other errors: Returns 500 with the error message or 'Internal error'
|
|
15
|
+
* Attaches requestId from thread-local storage if available.
|
|
16
|
+
*/
|
|
10
17
|
function buildApiResponse(error) {
|
|
11
18
|
const tls = (0, thread_local_storage_1.getRequestLocalStorage)();
|
|
12
19
|
const requestId = tls?.requestId;
|
|
@@ -32,7 +39,18 @@ function buildApiResponse(error) {
|
|
|
32
39
|
}
|
|
33
40
|
return response;
|
|
34
41
|
}
|
|
35
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* @Internal
|
|
44
|
+
* Wraps a route handler to catch and convert errors to API responses.
|
|
45
|
+
* Applied automatically to all routes registered via createRouteTable().
|
|
46
|
+
*
|
|
47
|
+
* Catches:
|
|
48
|
+
* - Errors thrown in validators ($path, $query, $body)
|
|
49
|
+
* - Errors thrown in the run() handler
|
|
50
|
+
* - Errors thrown in endpoint middlewares
|
|
51
|
+
*
|
|
52
|
+
* Logs errors to console (error level for 5xx).
|
|
53
|
+
*/
|
|
36
54
|
function catchRouteErrors(fn) {
|
|
37
55
|
return async (req, res, next) => {
|
|
38
56
|
try {
|
|
@@ -43,17 +61,33 @@ function catchRouteErrors(fn) {
|
|
|
43
61
|
if (apiResponse.status >= http_status_codes_1.HTTP_INTERNAL_SERVER_ERROR) {
|
|
44
62
|
console.error(`catchRouteErrors: ${req.path}`, error);
|
|
45
63
|
}
|
|
46
|
-
else {
|
|
47
|
-
console.log(`catchRouteErrors: ${req.path}`, error);
|
|
48
|
-
}
|
|
49
64
|
res.status(apiResponse.status);
|
|
50
65
|
res.send(apiResponse);
|
|
51
66
|
}
|
|
52
67
|
};
|
|
53
68
|
}
|
|
54
69
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
70
|
+
* Express error-handling middleware (4 parameters) for catching errors.
|
|
71
|
+
* Can be mounted at any level - global, path-specific, or router-specific.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Global
|
|
75
|
+
* app.use(catchAllMiddleware);
|
|
76
|
+
*
|
|
77
|
+
* // Path-specific
|
|
78
|
+
* app.use('/api', catchAllMiddleware);
|
|
79
|
+
*
|
|
80
|
+
* // Router-specific
|
|
81
|
+
* const router = express.Router();
|
|
82
|
+
* router.use(catchAllMiddleware);
|
|
83
|
+
*
|
|
84
|
+
* Catches:
|
|
85
|
+
* - Errors from Express middleware (passed via next(error))
|
|
86
|
+
* - JSON parsing errors (SyntaxError) - returns 400
|
|
87
|
+
* - Any errors that escape catchRouteErrors
|
|
88
|
+
*
|
|
89
|
+
* Note: Individual routes are already wrapped with catchRouteErrors(),
|
|
90
|
+
* so this middleware primarily catches middleware and parsing errors.
|
|
57
91
|
*/
|
|
58
92
|
async function catchAllMiddleware(error, _, res, next) {
|
|
59
93
|
if (!error) {
|
|
@@ -63,9 +97,75 @@ async function catchAllMiddleware(error, _, res, next) {
|
|
|
63
97
|
// Report as critical. This kind of error should never happen.
|
|
64
98
|
console.error('catchAllMiddleware:', (0, assertions_1.getMessageFromError)(error));
|
|
65
99
|
const apiResponse = error instanceof SyntaxError // JSON body parsing error.
|
|
66
|
-
? buildApiResponse(
|
|
100
|
+
? buildApiResponse(new api_types_1.HttpError(http_status_codes_1.HTTP_BAD_REQUEST, `Failed to parse request: ${error.message}`))
|
|
67
101
|
: buildApiResponse(error);
|
|
68
102
|
res.status(apiResponse.status);
|
|
69
103
|
res.send(apiResponse);
|
|
70
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Installs process-level handlers for errors and graceful shutdown.
|
|
107
|
+
* Call once at application startup, before app.listen().
|
|
108
|
+
*
|
|
109
|
+
* Error handling:
|
|
110
|
+
* - Uncaught exceptions (sync throws outside Express middleware)
|
|
111
|
+
* - Unhandled promise rejections (forgotten await, missing .catch())
|
|
112
|
+
*
|
|
113
|
+
* Graceful shutdown:
|
|
114
|
+
* - SIGTERM (Docker/K8s/systemd stop)
|
|
115
|
+
* - SIGINT (Ctrl+C)
|
|
116
|
+
* - Timeout protection (force exit if shutdown hangs)
|
|
117
|
+
* - Double-shutdown prevention
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* installProcessHandlers({
|
|
121
|
+
* onUncaughtException: (error) => sendToMonitoring(error),
|
|
122
|
+
* onUnhandledRejection: (reason) => sendToMonitoring(reason),
|
|
123
|
+
* onShutdown: async () => {
|
|
124
|
+
* await database.close();
|
|
125
|
+
* await server.close();
|
|
126
|
+
* },
|
|
127
|
+
* shutdownTimeout: 15000,
|
|
128
|
+
* });
|
|
129
|
+
*/
|
|
130
|
+
function installProcessHandlers(options) {
|
|
131
|
+
// Error handlers
|
|
132
|
+
process.on('uncaughtException', (error) => {
|
|
133
|
+
options?.onUncaughtException?.(error);
|
|
134
|
+
console.error('CRITICAL - Uncaught Exception:', error);
|
|
135
|
+
});
|
|
136
|
+
process.on('unhandledRejection', (reason) => {
|
|
137
|
+
options?.onUnhandledRejection?.(reason);
|
|
138
|
+
console.error('CRITICAL - Unhandled Rejection:', reason);
|
|
139
|
+
});
|
|
140
|
+
// Graceful shutdown
|
|
141
|
+
const onShutdown = options?.onShutdown;
|
|
142
|
+
if (onShutdown) {
|
|
143
|
+
let isShuttingDown = false;
|
|
144
|
+
const signals = options?.shutdownSignals ?? ['SIGTERM', 'SIGINT'];
|
|
145
|
+
const timeout = options?.shutdownTimeout ?? 10000;
|
|
146
|
+
const shutdown = async (signal) => {
|
|
147
|
+
if (isShuttingDown)
|
|
148
|
+
return;
|
|
149
|
+
isShuttingDown = true;
|
|
150
|
+
console.log(`${signal} received, shutting down gracefully...`);
|
|
151
|
+
const timer = setTimeout(() => {
|
|
152
|
+
console.error('Shutdown timeout, forcing exit');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}, timeout);
|
|
155
|
+
try {
|
|
156
|
+
await onShutdown();
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
process.exit(0);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
console.error('Shutdown error:', err);
|
|
162
|
+
clearTimeout(timer);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
for (const signal of signals) {
|
|
167
|
+
process.on(signal, () => shutdown(signal));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
71
171
|
//# sourceMappingURL=error-handling.js.map
|
|
@@ -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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"}
|
|
@@ -8,12 +8,12 @@ export declare class RouteTable {
|
|
|
8
8
|
private readonly app;
|
|
9
9
|
constructor(app: ExpressRouter);
|
|
10
10
|
get<T>(path: string, endpoint: GetEndpoint<T> | GetEndpoint<T[]>): this;
|
|
11
|
-
get<T>(path: string, run: (ctx: RequestContext) => Promise<ResponseOrValue<T>>): this;
|
|
11
|
+
get<T>(path: string, run: (ctx: RequestContext) => ResponseOrValue<T> | Promise<ResponseOrValue<T>>): this;
|
|
12
12
|
post<Body, Result>(path: string, endpoint: PostEndpoint<Body, Result>): this;
|
|
13
13
|
patch<Body, Result>(path: string, endpoint: PatchEndpoint<Body, Result>): this;
|
|
14
14
|
put<Body, Result>(path: string, endpoint: PutEndpoint<Body, Result>): this;
|
|
15
15
|
delete(path: string, endpoint: DeleteEndpoint): this;
|
|
16
|
-
delete(path: string, run: (ctx: RequestContext) => Promise<void>): this;
|
|
16
|
+
delete(path: string, run: (ctx: RequestContext) => void | Promise<void>): this;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Factory function to create a new route table.
|
|
@@ -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":";;;AAkEA,4CAEC;AApED,qCAakB;AAGlB;;;GAGG;AACH,MAAa,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAInD,GAAG,CACD,IAAY,EACZ,aAG+E;QAE/E,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA0B,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAe,IAAY,EAAE,QAAoC;QACnE,IAAA,kBAAS,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAe,IAAY,EAAE,QAAqC;QACrE,IAAA,mBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAe,IAAY,EAAE,QAAmC;QACjE,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAID,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,oBAAW,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvCD,gCAuCC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,GAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/cjs/router.d.ts
CHANGED
|
@@ -45,45 +45,45 @@ export interface EndpointBase<Context = RequestContext, Result = unknown> {
|
|
|
45
45
|
$query?: UrlTokensValidator;
|
|
46
46
|
/** Optional middleware to execute before the handler. */
|
|
47
47
|
middlewares?: Array<EndpointMiddleware>;
|
|
48
|
-
/** Handler function. */
|
|
49
|
-
run: (ctx: Context) => Promise<ResponseOrValue<Result>>;
|
|
48
|
+
/** Handler function. Can be sync or async. */
|
|
49
|
+
run: (ctx: Context) => ResponseOrValue<Result> | Promise<ResponseOrValue<Result>>;
|
|
50
50
|
}
|
|
51
51
|
/** Descriptor for GET list routes. */
|
|
52
|
-
export type GetListEndpoint<ResultElementType
|
|
52
|
+
export type GetListEndpoint<ResultElementType> = EndpointBase<RequestContext, Array<ResultElementType>>;
|
|
53
53
|
/** Descriptor for GET routes. */
|
|
54
|
-
export type GetEndpoint<Result
|
|
54
|
+
export type GetEndpoint<Result> = EndpointBase<RequestContext, Result>;
|
|
55
55
|
/** Descriptor for POST routes. */
|
|
56
|
-
export interface PostEndpoint<Body
|
|
56
|
+
export interface PostEndpoint<Body, Result = void> extends EndpointBase<RequestContext<Body>, Result> {
|
|
57
57
|
/** Request body validator. */
|
|
58
58
|
$body: Body extends object ? ObjectAssertion<Body> : Assertion<Body>;
|
|
59
59
|
}
|
|
60
60
|
/** Same as POST. Used for full object updates. */
|
|
61
|
-
export type PutEndpoint<Body
|
|
61
|
+
export type PutEndpoint<Body, Result = void> = PostEndpoint<Body, Result>;
|
|
62
62
|
/** Same as PUT. While PUT is used for the whole object update, PATCH is used for a partial update. */
|
|
63
|
-
export type PatchEndpoint<Body
|
|
63
|
+
export type PatchEndpoint<Body, Result = void> = PutEndpoint<Body, Result>;
|
|
64
64
|
/** Descriptor for DELETE routes. */
|
|
65
65
|
export type DeleteEndpoint = EndpointBase<RequestContext, void>;
|
|
66
66
|
/** Union type for all route registration info objects. */
|
|
67
67
|
export type RouteRegistrationInfo = ({
|
|
68
68
|
method: 'get';
|
|
69
|
-
|
|
69
|
+
endpoint: GetEndpoint<unknown> | GetListEndpoint<unknown>;
|
|
70
70
|
} | {
|
|
71
71
|
method: 'post';
|
|
72
|
-
|
|
72
|
+
endpoint: PostEndpoint<unknown>;
|
|
73
73
|
} | {
|
|
74
74
|
method: 'patch';
|
|
75
|
-
|
|
75
|
+
endpoint: PatchEndpoint<unknown>;
|
|
76
76
|
} | {
|
|
77
77
|
method: 'put';
|
|
78
|
-
|
|
78
|
+
endpoint: PutEndpoint<unknown>;
|
|
79
79
|
} | {
|
|
80
80
|
method: 'delete';
|
|
81
|
-
|
|
81
|
+
endpoint: DeleteEndpoint;
|
|
82
82
|
}) & {
|
|
83
83
|
path: string;
|
|
84
84
|
};
|
|
85
85
|
/** Registers a GET route. */
|
|
86
|
-
export declare const mountGet: (app: ExpressRouter, path: string, endpoint: GetEndpoint | GetListEndpoint) => void;
|
|
86
|
+
export declare const mountGet: (app: ExpressRouter, path: string, endpoint: GetEndpoint<unknown> | GetListEndpoint<unknown>) => void;
|
|
87
87
|
/** Registers a POST route. */
|
|
88
88
|
export declare const mountPost: <Body, Result>(app: ExpressRouter, path: string, endpoint: PostEndpoint<Body, Result>) => void;
|
|
89
89
|
/** Registers a PATCH route. */
|
|
@@ -93,4 +93,4 @@ export declare const mountPut: <Body, Result>(app: ExpressRouter, path: string,
|
|
|
93
93
|
/** Registers a DELETE route. */
|
|
94
94
|
export declare const mountDelete: (app: ExpressRouter, path: string, endpoint: DeleteEndpoint) => void;
|
|
95
95
|
/** Mounts a route with the given method, endpoint, and path. */
|
|
96
|
-
export declare function mount(app: ExpressRouter, { method,
|
|
96
|
+
export declare function mount(app: ExpressRouter, { method, endpoint, path }: RouteRegistrationInfo): void;
|
package/dist/cjs/router.js
CHANGED
|
@@ -46,24 +46,24 @@ const conversion_utils_1 = require("./utils/conversion.utils");
|
|
|
46
46
|
// Internal implementation details
|
|
47
47
|
// ============================================================================
|
|
48
48
|
/** Registers a GET route. */
|
|
49
|
-
const mountGet = (app, path, endpoint) => mount(app, { method: 'get',
|
|
49
|
+
const mountGet = (app, path, endpoint) => mount(app, { method: 'get', endpoint, path });
|
|
50
50
|
exports.mountGet = mountGet;
|
|
51
51
|
/** Registers a POST route. */
|
|
52
|
-
const mountPost = (app, path, endpoint) => mount(app, { method: 'post',
|
|
52
|
+
const mountPost = (app, path, endpoint) => mount(app, { method: 'post', endpoint: endpoint, path });
|
|
53
53
|
exports.mountPost = mountPost;
|
|
54
54
|
/** Registers a PATCH route. */
|
|
55
|
-
const mountPatch = (app, path, endpoint) => mount(app, { method: 'patch',
|
|
55
|
+
const mountPatch = (app, path, endpoint) => mount(app, { method: 'patch', endpoint: endpoint, path });
|
|
56
56
|
exports.mountPatch = mountPatch;
|
|
57
57
|
/** Registers a PUT route. */
|
|
58
|
-
const mountPut = (app, path, endpoint) => mount(app, { method: 'put',
|
|
58
|
+
const mountPut = (app, path, endpoint) => mount(app, { method: 'put', endpoint: endpoint, path });
|
|
59
59
|
exports.mountPut = mountPut;
|
|
60
60
|
/** Registers a DELETE route. */
|
|
61
|
-
const mountDelete = (app, path, endpoint) => mount(app, { method: 'delete',
|
|
61
|
+
const mountDelete = (app, path, endpoint) => mount(app, { method: 'delete', endpoint, path });
|
|
62
62
|
exports.mountDelete = mountDelete;
|
|
63
63
|
/** Mounts a route with the given method, endpoint, and path. */
|
|
64
|
-
function mount(app, { method,
|
|
64
|
+
function mount(app, { method, endpoint, path }) {
|
|
65
65
|
const fullPath = path.startsWith('/') ? path : `/${path}`;
|
|
66
|
-
const handler = createRouteHandler(method,
|
|
66
|
+
const handler = createRouteHandler(method, endpoint);
|
|
67
67
|
app[method](fullPath, (0, error_handling_1.catchRouteErrors)(handler));
|
|
68
68
|
}
|
|
69
69
|
/**
|
package/dist/cjs/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,78 @@
|
|
|
1
1
|
import { NextFunction } from 'express';
|
|
2
2
|
import { ExpressFunction, ExpressRequest, ExpressResponse } from './utils/express.utils';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* @Internal
|
|
5
|
+
* Wraps a route handler to catch and convert errors to API responses.
|
|
6
|
+
* Applied automatically to all routes registered via createRouteTable().
|
|
7
|
+
*
|
|
8
|
+
* Catches:
|
|
9
|
+
* - Errors thrown in validators ($path, $query, $body)
|
|
10
|
+
* - Errors thrown in the run() handler
|
|
11
|
+
* - Errors thrown in endpoint middlewares
|
|
12
|
+
*
|
|
13
|
+
* Logs errors to console (error level for 5xx).
|
|
14
|
+
*/
|
|
4
15
|
export declare function catchRouteErrors(fn: ExpressFunction): ExpressFunction;
|
|
5
16
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
17
|
+
* Express error-handling middleware (4 parameters) for catching errors.
|
|
18
|
+
* Can be mounted at any level - global, path-specific, or router-specific.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Global
|
|
22
|
+
* app.use(catchAllMiddleware);
|
|
23
|
+
*
|
|
24
|
+
* // Path-specific
|
|
25
|
+
* app.use('/api', catchAllMiddleware);
|
|
26
|
+
*
|
|
27
|
+
* // Router-specific
|
|
28
|
+
* const router = express.Router();
|
|
29
|
+
* router.use(catchAllMiddleware);
|
|
30
|
+
*
|
|
31
|
+
* Catches:
|
|
32
|
+
* - Errors from Express middleware (passed via next(error))
|
|
33
|
+
* - JSON parsing errors (SyntaxError) - returns 400
|
|
34
|
+
* - Any errors that escape catchRouteErrors
|
|
35
|
+
*
|
|
36
|
+
* Note: Individual routes are already wrapped with catchRouteErrors(),
|
|
37
|
+
* so this middleware primarily catches middleware and parsing errors.
|
|
8
38
|
*/
|
|
9
39
|
export declare function catchAllMiddleware(error: unknown, _: ExpressRequest, res: ExpressResponse, next: NextFunction): Promise<void>;
|
|
40
|
+
/** Options for installProcessHandlers(). */
|
|
41
|
+
export interface ProcessHandlersOptions {
|
|
42
|
+
/** Custom handler for uncaught exceptions. Called before default logging. */
|
|
43
|
+
onUncaughtException?: (error: Error) => void;
|
|
44
|
+
/** Custom handler for unhandled promise rejections. Called before default logging. */
|
|
45
|
+
onUnhandledRejection?: (reason: unknown) => void;
|
|
46
|
+
/** Async cleanup function called on shutdown signals. */
|
|
47
|
+
onShutdown?: () => Promise<void>;
|
|
48
|
+
/** Force exit timeout in ms if shutdown hangs. Default: 10000 */
|
|
49
|
+
shutdownTimeout?: number;
|
|
50
|
+
/** Signals to handle for graceful shutdown. Default: ['SIGTERM', 'SIGINT'] */
|
|
51
|
+
shutdownSignals?: NodeJS.Signals[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Installs process-level handlers for errors and graceful shutdown.
|
|
55
|
+
* Call once at application startup, before app.listen().
|
|
56
|
+
*
|
|
57
|
+
* Error handling:
|
|
58
|
+
* - Uncaught exceptions (sync throws outside Express middleware)
|
|
59
|
+
* - Unhandled promise rejections (forgotten await, missing .catch())
|
|
60
|
+
*
|
|
61
|
+
* Graceful shutdown:
|
|
62
|
+
* - SIGTERM (Docker/K8s/systemd stop)
|
|
63
|
+
* - SIGINT (Ctrl+C)
|
|
64
|
+
* - Timeout protection (force exit if shutdown hangs)
|
|
65
|
+
* - Double-shutdown prevention
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* installProcessHandlers({
|
|
69
|
+
* onUncaughtException: (error) => sendToMonitoring(error),
|
|
70
|
+
* onUnhandledRejection: (reason) => sendToMonitoring(reason),
|
|
71
|
+
* onShutdown: async () => {
|
|
72
|
+
* await database.close();
|
|
73
|
+
* await server.close();
|
|
74
|
+
* },
|
|
75
|
+
* shutdownTimeout: 15000,
|
|
76
|
+
* });
|
|
77
|
+
*/
|
|
78
|
+
export declare function installProcessHandlers(options?: ProcessHandlersOptions): void;
|
|
@@ -3,6 +3,12 @@ import { HttpError } from './api.types';
|
|
|
3
3
|
import { HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR } from './http-status-codes';
|
|
4
4
|
import { getRequestLocalStorage } from './thread-local/thread-local-storage';
|
|
5
5
|
import { wrapAsApiResponse } from './utils/conversion.utils';
|
|
6
|
+
/**
|
|
7
|
+
* Converts any error into a standardized API response format.
|
|
8
|
+
* - HttpError: Uses the error's status code and message
|
|
9
|
+
* - Other errors: Returns 500 with the error message or 'Internal error'
|
|
10
|
+
* Attaches requestId from thread-local storage if available.
|
|
11
|
+
*/
|
|
6
12
|
function buildApiResponse(error) {
|
|
7
13
|
const tls = getRequestLocalStorage();
|
|
8
14
|
const requestId = tls?.requestId;
|
|
@@ -28,7 +34,18 @@ function buildApiResponse(error) {
|
|
|
28
34
|
}
|
|
29
35
|
return response;
|
|
30
36
|
}
|
|
31
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* @Internal
|
|
39
|
+
* Wraps a route handler to catch and convert errors to API responses.
|
|
40
|
+
* Applied automatically to all routes registered via createRouteTable().
|
|
41
|
+
*
|
|
42
|
+
* Catches:
|
|
43
|
+
* - Errors thrown in validators ($path, $query, $body)
|
|
44
|
+
* - Errors thrown in the run() handler
|
|
45
|
+
* - Errors thrown in endpoint middlewares
|
|
46
|
+
*
|
|
47
|
+
* Logs errors to console (error level for 5xx).
|
|
48
|
+
*/
|
|
32
49
|
export function catchRouteErrors(fn) {
|
|
33
50
|
return async (req, res, next) => {
|
|
34
51
|
try {
|
|
@@ -39,17 +56,33 @@ export function catchRouteErrors(fn) {
|
|
|
39
56
|
if (apiResponse.status >= HTTP_INTERNAL_SERVER_ERROR) {
|
|
40
57
|
console.error(`catchRouteErrors: ${req.path}`, error);
|
|
41
58
|
}
|
|
42
|
-
else {
|
|
43
|
-
console.log(`catchRouteErrors: ${req.path}`, error);
|
|
44
|
-
}
|
|
45
59
|
res.status(apiResponse.status);
|
|
46
60
|
res.send(apiResponse);
|
|
47
61
|
}
|
|
48
62
|
};
|
|
49
63
|
}
|
|
50
64
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
65
|
+
* Express error-handling middleware (4 parameters) for catching errors.
|
|
66
|
+
* Can be mounted at any level - global, path-specific, or router-specific.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Global
|
|
70
|
+
* app.use(catchAllMiddleware);
|
|
71
|
+
*
|
|
72
|
+
* // Path-specific
|
|
73
|
+
* app.use('/api', catchAllMiddleware);
|
|
74
|
+
*
|
|
75
|
+
* // Router-specific
|
|
76
|
+
* const router = express.Router();
|
|
77
|
+
* router.use(catchAllMiddleware);
|
|
78
|
+
*
|
|
79
|
+
* Catches:
|
|
80
|
+
* - Errors from Express middleware (passed via next(error))
|
|
81
|
+
* - JSON parsing errors (SyntaxError) - returns 400
|
|
82
|
+
* - Any errors that escape catchRouteErrors
|
|
83
|
+
*
|
|
84
|
+
* Note: Individual routes are already wrapped with catchRouteErrors(),
|
|
85
|
+
* so this middleware primarily catches middleware and parsing errors.
|
|
53
86
|
*/
|
|
54
87
|
export async function catchAllMiddleware(error, _, res, next) {
|
|
55
88
|
if (!error) {
|
|
@@ -59,9 +92,75 @@ export async function catchAllMiddleware(error, _, res, next) {
|
|
|
59
92
|
// Report as critical. This kind of error should never happen.
|
|
60
93
|
console.error('catchAllMiddleware:', getMessageFromError(error));
|
|
61
94
|
const apiResponse = error instanceof SyntaxError // JSON body parsing error.
|
|
62
|
-
? buildApiResponse(
|
|
95
|
+
? buildApiResponse(new HttpError(HTTP_BAD_REQUEST, `Failed to parse request: ${error.message}`))
|
|
63
96
|
: buildApiResponse(error);
|
|
64
97
|
res.status(apiResponse.status);
|
|
65
98
|
res.send(apiResponse);
|
|
66
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Installs process-level handlers for errors and graceful shutdown.
|
|
102
|
+
* Call once at application startup, before app.listen().
|
|
103
|
+
*
|
|
104
|
+
* Error handling:
|
|
105
|
+
* - Uncaught exceptions (sync throws outside Express middleware)
|
|
106
|
+
* - Unhandled promise rejections (forgotten await, missing .catch())
|
|
107
|
+
*
|
|
108
|
+
* Graceful shutdown:
|
|
109
|
+
* - SIGTERM (Docker/K8s/systemd stop)
|
|
110
|
+
* - SIGINT (Ctrl+C)
|
|
111
|
+
* - Timeout protection (force exit if shutdown hangs)
|
|
112
|
+
* - Double-shutdown prevention
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* installProcessHandlers({
|
|
116
|
+
* onUncaughtException: (error) => sendToMonitoring(error),
|
|
117
|
+
* onUnhandledRejection: (reason) => sendToMonitoring(reason),
|
|
118
|
+
* onShutdown: async () => {
|
|
119
|
+
* await database.close();
|
|
120
|
+
* await server.close();
|
|
121
|
+
* },
|
|
122
|
+
* shutdownTimeout: 15000,
|
|
123
|
+
* });
|
|
124
|
+
*/
|
|
125
|
+
export function installProcessHandlers(options) {
|
|
126
|
+
// Error handlers
|
|
127
|
+
process.on('uncaughtException', (error) => {
|
|
128
|
+
options?.onUncaughtException?.(error);
|
|
129
|
+
console.error('CRITICAL - Uncaught Exception:', error);
|
|
130
|
+
});
|
|
131
|
+
process.on('unhandledRejection', (reason) => {
|
|
132
|
+
options?.onUnhandledRejection?.(reason);
|
|
133
|
+
console.error('CRITICAL - Unhandled Rejection:', reason);
|
|
134
|
+
});
|
|
135
|
+
// Graceful shutdown
|
|
136
|
+
const onShutdown = options?.onShutdown;
|
|
137
|
+
if (onShutdown) {
|
|
138
|
+
let isShuttingDown = false;
|
|
139
|
+
const signals = options?.shutdownSignals ?? ['SIGTERM', 'SIGINT'];
|
|
140
|
+
const timeout = options?.shutdownTimeout ?? 10000;
|
|
141
|
+
const shutdown = async (signal) => {
|
|
142
|
+
if (isShuttingDown)
|
|
143
|
+
return;
|
|
144
|
+
isShuttingDown = true;
|
|
145
|
+
console.log(`${signal} received, shutting down gracefully...`);
|
|
146
|
+
const timer = setTimeout(() => {
|
|
147
|
+
console.error('Shutdown timeout, forcing exit');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}, timeout);
|
|
150
|
+
try {
|
|
151
|
+
await onShutdown();
|
|
152
|
+
clearTimeout(timer);
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
console.error('Shutdown error:', err);
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
for (const signal of signals) {
|
|
162
|
+
process.on(signal, () => shutdown(signal));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
67
166
|
//# sourceMappingURL=error-handling.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAe,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,SAAS,gBAAgB,CAAC,KAAc;IACtC,MAAM,GAAG,GAAG,sBAAsB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,GAAG,EAAE,SAAS,CAAC;IACjC,IAAI,QAA0C,CAAC;IAE/C,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,QAAQ,GAAG;YACT,GAAG,iBAAiB,CAAC,SAAS,CAAC;YAC/B,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpD,QAAQ,GAAG;YACT,GAAG,iBAAiB,CAAC,SAAS,CAAC;YAC/B,KAAK,EAAE,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB;YAChF,MAAM,EAAE,0BAA0B;SACnC,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;IACjC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/error-handling.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,12 @@ export declare class RouteTable {
|
|
|
8
8
|
private readonly app;
|
|
9
9
|
constructor(app: ExpressRouter);
|
|
10
10
|
get<T>(path: string, endpoint: GetEndpoint<T> | GetEndpoint<T[]>): this;
|
|
11
|
-
get<T>(path: string, run: (ctx: RequestContext) => Promise<ResponseOrValue<T>>): this;
|
|
11
|
+
get<T>(path: string, run: (ctx: RequestContext) => ResponseOrValue<T> | Promise<ResponseOrValue<T>>): this;
|
|
12
12
|
post<Body, Result>(path: string, endpoint: PostEndpoint<Body, Result>): this;
|
|
13
13
|
patch<Body, Result>(path: string, endpoint: PatchEndpoint<Body, Result>): this;
|
|
14
14
|
put<Body, Result>(path: string, endpoint: PutEndpoint<Body, Result>): this;
|
|
15
15
|
delete(path: string, endpoint: DeleteEndpoint): this;
|
|
16
|
-
delete(path: string, run: (ctx: RequestContext) => Promise<void>): this;
|
|
16
|
+
delete(path: string, run: (ctx: RequestContext) => void | Promise<void>): this;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Factory function to create a new route table.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAQ,GAMT,MAAM,UAAU,CAAC;AAGlB;;;GAGG;AACH,MAAM,OAAO,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAInD,GAAG,CACD,IAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAQ,GAMT,MAAM,UAAU,CAAC;AAGlB;;;GAGG;AACH,MAAM,OAAO,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAInD,GAAG,CACD,IAAY,EACZ,aAG+E;QAE/E,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA0B,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAe,IAAY,EAAE,QAAoC;QACnE,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAe,IAAY,EAAE,QAAqC;QACrE,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAe,IAAY,EAAE,QAAmC;QACjE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAID,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,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/esm/router.d.ts
CHANGED
|
@@ -45,45 +45,45 @@ export interface EndpointBase<Context = RequestContext, Result = unknown> {
|
|
|
45
45
|
$query?: UrlTokensValidator;
|
|
46
46
|
/** Optional middleware to execute before the handler. */
|
|
47
47
|
middlewares?: Array<EndpointMiddleware>;
|
|
48
|
-
/** Handler function. */
|
|
49
|
-
run: (ctx: Context) => Promise<ResponseOrValue<Result>>;
|
|
48
|
+
/** Handler function. Can be sync or async. */
|
|
49
|
+
run: (ctx: Context) => ResponseOrValue<Result> | Promise<ResponseOrValue<Result>>;
|
|
50
50
|
}
|
|
51
51
|
/** Descriptor for GET list routes. */
|
|
52
|
-
export type GetListEndpoint<ResultElementType
|
|
52
|
+
export type GetListEndpoint<ResultElementType> = EndpointBase<RequestContext, Array<ResultElementType>>;
|
|
53
53
|
/** Descriptor for GET routes. */
|
|
54
|
-
export type GetEndpoint<Result
|
|
54
|
+
export type GetEndpoint<Result> = EndpointBase<RequestContext, Result>;
|
|
55
55
|
/** Descriptor for POST routes. */
|
|
56
|
-
export interface PostEndpoint<Body
|
|
56
|
+
export interface PostEndpoint<Body, Result = void> extends EndpointBase<RequestContext<Body>, Result> {
|
|
57
57
|
/** Request body validator. */
|
|
58
58
|
$body: Body extends object ? ObjectAssertion<Body> : Assertion<Body>;
|
|
59
59
|
}
|
|
60
60
|
/** Same as POST. Used for full object updates. */
|
|
61
|
-
export type PutEndpoint<Body
|
|
61
|
+
export type PutEndpoint<Body, Result = void> = PostEndpoint<Body, Result>;
|
|
62
62
|
/** Same as PUT. While PUT is used for the whole object update, PATCH is used for a partial update. */
|
|
63
|
-
export type PatchEndpoint<Body
|
|
63
|
+
export type PatchEndpoint<Body, Result = void> = PutEndpoint<Body, Result>;
|
|
64
64
|
/** Descriptor for DELETE routes. */
|
|
65
65
|
export type DeleteEndpoint = EndpointBase<RequestContext, void>;
|
|
66
66
|
/** Union type for all route registration info objects. */
|
|
67
67
|
export type RouteRegistrationInfo = ({
|
|
68
68
|
method: 'get';
|
|
69
|
-
|
|
69
|
+
endpoint: GetEndpoint<unknown> | GetListEndpoint<unknown>;
|
|
70
70
|
} | {
|
|
71
71
|
method: 'post';
|
|
72
|
-
|
|
72
|
+
endpoint: PostEndpoint<unknown>;
|
|
73
73
|
} | {
|
|
74
74
|
method: 'patch';
|
|
75
|
-
|
|
75
|
+
endpoint: PatchEndpoint<unknown>;
|
|
76
76
|
} | {
|
|
77
77
|
method: 'put';
|
|
78
|
-
|
|
78
|
+
endpoint: PutEndpoint<unknown>;
|
|
79
79
|
} | {
|
|
80
80
|
method: 'delete';
|
|
81
|
-
|
|
81
|
+
endpoint: DeleteEndpoint;
|
|
82
82
|
}) & {
|
|
83
83
|
path: string;
|
|
84
84
|
};
|
|
85
85
|
/** Registers a GET route. */
|
|
86
|
-
export declare const mountGet: (app: ExpressRouter, path: string, endpoint: GetEndpoint | GetListEndpoint) => void;
|
|
86
|
+
export declare const mountGet: (app: ExpressRouter, path: string, endpoint: GetEndpoint<unknown> | GetListEndpoint<unknown>) => void;
|
|
87
87
|
/** Registers a POST route. */
|
|
88
88
|
export declare const mountPost: <Body, Result>(app: ExpressRouter, path: string, endpoint: PostEndpoint<Body, Result>) => void;
|
|
89
89
|
/** Registers a PATCH route. */
|
|
@@ -93,4 +93,4 @@ export declare const mountPut: <Body, Result>(app: ExpressRouter, path: string,
|
|
|
93
93
|
/** Registers a DELETE route. */
|
|
94
94
|
export declare const mountDelete: (app: ExpressRouter, path: string, endpoint: DeleteEndpoint) => void;
|
|
95
95
|
/** Mounts a route with the given method, endpoint, and path. */
|
|
96
|
-
export declare function mount(app: ExpressRouter, { method,
|
|
96
|
+
export declare function mount(app: ExpressRouter, { method, endpoint, path }: RouteRegistrationInfo): void;
|
package/dist/esm/router.js
CHANGED
|
@@ -9,19 +9,19 @@ import { wrapAsApiResponse } from './utils/conversion.utils';
|
|
|
9
9
|
// Internal implementation details
|
|
10
10
|
// ============================================================================
|
|
11
11
|
/** Registers a GET route. */
|
|
12
|
-
export const mountGet = (app, path, endpoint) => mount(app, { method: 'get',
|
|
12
|
+
export const mountGet = (app, path, endpoint) => mount(app, { method: 'get', endpoint, path });
|
|
13
13
|
/** Registers a POST route. */
|
|
14
|
-
export const mountPost = (app, path, endpoint) => mount(app, { method: 'post',
|
|
14
|
+
export const mountPost = (app, path, endpoint) => mount(app, { method: 'post', endpoint: endpoint, path });
|
|
15
15
|
/** Registers a PATCH route. */
|
|
16
|
-
export const mountPatch = (app, path, endpoint) => mount(app, { method: 'patch',
|
|
16
|
+
export const mountPatch = (app, path, endpoint) => mount(app, { method: 'patch', endpoint: endpoint, path });
|
|
17
17
|
/** Registers a PUT route. */
|
|
18
|
-
export const mountPut = (app, path, endpoint) => mount(app, { method: 'put',
|
|
18
|
+
export const mountPut = (app, path, endpoint) => mount(app, { method: 'put', endpoint: endpoint, path });
|
|
19
19
|
/** Registers a DELETE route. */
|
|
20
|
-
export const mountDelete = (app, path, endpoint) => mount(app, { method: 'delete',
|
|
20
|
+
export const mountDelete = (app, path, endpoint) => mount(app, { method: 'delete', endpoint, path });
|
|
21
21
|
/** Mounts a route with the given method, endpoint, and path. */
|
|
22
|
-
export function mount(app, { method,
|
|
22
|
+
export function mount(app, { method, endpoint, path }) {
|
|
23
23
|
const fullPath = path.startsWith('/') ? path : `/${path}`;
|
|
24
|
-
const handler = createRouteHandler(method,
|
|
24
|
+
const handler = createRouteHandler(method, endpoint);
|
|
25
25
|
app[method](fullPath, catchRouteErrors(handler));
|
|
26
26
|
}
|
|
27
27
|
/**
|
package/dist/esm/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAClB,mBAAmB,EAEnB,cAAc,GAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAe,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAsB,MAAM,aAAa,CAAC;AAEzG,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AA0F7D,+EAA+E;AAC/E,kCAAkC;AAClC,+EAA+E;AAE/E,6BAA6B;AAC7B,MAAM,CAAC,MAAM,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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"}
|