adorn-api 1.0.1 → 1.0.2
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 +4 -1
- package/dist/adapters/express/createApp.d.ts +149 -11
- package/dist/adapters/express/createApp.d.ts.map +1 -1
- package/dist/adapters/express/createApp.js +112 -6
- package/dist/adapters/express/createApp.js.map +1 -1
- package/dist/adapters/express/middleware/errorHandler.d.ts +193 -2
- package/dist/adapters/express/middleware/errorHandler.d.ts.map +1 -1
- package/dist/adapters/express/middleware/errorHandler.js +164 -3
- package/dist/adapters/express/middleware/errorHandler.js.map +1 -1
- package/dist/adapters/express/router.d.ts +1 -1
- package/dist/adapters/express/router.d.ts.map +1 -1
- package/dist/adapters/express/router.js +6 -4
- package/dist/adapters/express/router.js.map +1 -1
- package/dist/adapters/express/transport/request.js.map +1 -1
- package/dist/adapters/express/transport/response.d.ts +1 -1
- package/dist/adapters/express/transport/response.d.ts.map +1 -1
- package/dist/adapters/express/transport/response.js.map +1 -1
- package/dist/contracts/openapi-v3.d.ts +461 -0
- package/dist/contracts/openapi-v3.d.ts.map +1 -1
- package/dist/contracts/reply.d.ts +109 -1
- package/dist/contracts/reply.d.ts.map +1 -1
- package/dist/contracts/reply.js +40 -1
- package/dist/contracts/reply.js.map +1 -1
- package/dist/contracts/response-types.d.ts +5 -5
- package/dist/contracts/response-types.d.ts.map +1 -1
- package/dist/contracts/responses.d.ts +84 -4
- package/dist/contracts/responses.d.ts.map +1 -1
- package/dist/contracts/route-options.d.ts +134 -3
- package/dist/contracts/route-options.d.ts.map +1 -1
- package/dist/contracts/validator.d.ts +121 -0
- package/dist/contracts/validator.d.ts.map +1 -1
- package/dist/core/binding/binder.d.ts +56 -1
- package/dist/core/binding/binder.d.ts.map +1 -1
- package/dist/core/binding/binder.js +33 -0
- package/dist/core/binding/binder.js.map +1 -1
- package/dist/core/binding/coerce/primitives.d.ts +68 -1
- package/dist/core/binding/coerce/primitives.d.ts.map +1 -1
- package/dist/core/binding/coerce/primitives.js +82 -12
- package/dist/core/binding/coerce/primitives.js.map +1 -1
- package/dist/core/errors/http-error.d.ts +54 -0
- package/dist/core/errors/http-error.d.ts.map +1 -1
- package/dist/core/errors/http-error.js +54 -0
- package/dist/core/errors/http-error.js.map +1 -1
- package/dist/core/errors/validation-error.d.ts +65 -0
- package/dist/core/errors/validation-error.d.ts.map +1 -1
- package/dist/core/errors/validation-error.js +65 -0
- package/dist/core/errors/validation-error.js.map +1 -1
- package/dist/core/openapi/buildOpenApi.d.ts +65 -0
- package/dist/core/openapi/buildOpenApi.d.ts.map +1 -1
- package/dist/core/openapi/buildOpenApi.js +66 -4
- package/dist/core/openapi/buildOpenApi.js.map +1 -1
- package/dist/core/openapi/schema/registry.d.ts +1 -1
- package/dist/core/openapi/schema/registry.d.ts.map +1 -1
- package/dist/core/openapi/schema/registry.js.map +1 -1
- package/dist/core/registry/buildRegistry.d.ts.map +1 -1
- package/dist/core/registry/buildRegistry.js +49 -5
- package/dist/core/registry/buildRegistry.js.map +1 -1
- package/dist/core/registry/types.d.ts +194 -1
- package/dist/core/registry/types.d.ts.map +1 -1
- package/dist/core/reply/reply.d.ts +94 -0
- package/dist/core/reply/reply.d.ts.map +1 -1
- package/dist/core/reply/reply.js +87 -0
- package/dist/core/reply/reply.js.map +1 -1
- package/dist/core/reply/typed.d.ts +137 -3
- package/dist/core/reply/typed.d.ts.map +1 -1
- package/dist/core/reply/typed.js +137 -2
- package/dist/core/reply/typed.js.map +1 -1
- package/dist/core/responses/helpers.d.ts +1 -1
- package/dist/core/responses/helpers.d.ts.map +1 -1
- package/dist/core/responses/normalize.d.ts.map +1 -1
- package/dist/core/responses/normalize.js +2 -1
- package/dist/core/responses/normalize.js.map +1 -1
- package/dist/core/route/defineRoute.d.ts +48 -1
- package/dist/core/route/defineRoute.d.ts.map +1 -1
- package/dist/core/route/defineRoute.js +42 -1
- package/dist/core/route/defineRoute.js.map +1 -1
- package/dist/decorators/binding.d.ts +1 -1
- package/dist/decorators/binding.d.ts.map +1 -1
- package/dist/decorators/binding.js.map +1 -1
- package/dist/decorators/controller.d.ts +1 -1
- package/dist/decorators/controller.d.ts.map +1 -1
- package/dist/decorators/controller.js.map +1 -1
- package/dist/decorators/docs.d.ts +6 -0
- package/dist/decorators/docs.d.ts.map +1 -1
- package/dist/decorators/docs.js +45 -2
- package/dist/decorators/docs.js.map +1 -1
- package/dist/decorators/index.d.ts +3 -0
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +3 -0
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/methods.d.ts +128 -6
- package/dist/decorators/methods.d.ts.map +1 -1
- package/dist/decorators/methods.js +124 -0
- package/dist/decorators/methods.js.map +1 -1
- package/dist/decorators/responses.d.ts +5 -0
- package/dist/decorators/responses.d.ts.map +1 -1
- package/dist/decorators/responses.js +43 -2
- package/dist/decorators/responses.js.map +1 -1
- package/dist/decorators/security.d.ts +6 -0
- package/dist/decorators/security.d.ts.map +1 -1
- package/dist/decorators/security.js +38 -2
- package/dist/decorators/security.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/metal-orm/schema/column-map.d.ts +91 -0
- package/dist/integrations/metal-orm/schema/column-map.d.ts.map +1 -1
- package/dist/integrations/metal-orm/schema/column-map.js +129 -2
- package/dist/integrations/metal-orm/schema/column-map.js.map +1 -1
- package/dist/integrations/metal-orm/schema/dto.d.ts +2 -2
- package/dist/integrations/metal-orm/schema/dto.d.ts.map +1 -1
- package/dist/integrations/metal-orm/schema/dto.js.map +1 -1
- package/dist/integrations/metal-orm/schema/entity.d.ts +90 -8
- package/dist/integrations/metal-orm/schema/entity.d.ts.map +1 -1
- package/dist/integrations/metal-orm/schema/entity.js +78 -6
- package/dist/integrations/metal-orm/schema/entity.js.map +1 -1
- package/dist/integrations/metal-orm/schema/filters.d.ts +1 -1
- package/dist/integrations/metal-orm/schema/filters.d.ts.map +1 -1
- package/dist/integrations/metal-orm/schema/filters.js +2 -1
- package/dist/integrations/metal-orm/schema/filters.js.map +1 -1
- package/dist/integrations/metal-orm/schema/tabledef.d.ts +1 -1
- package/dist/integrations/metal-orm/schema/tabledef.d.ts.map +1 -1
- package/dist/metadata/bag.d.ts +2 -1
- package/dist/metadata/bag.d.ts.map +1 -1
- package/dist/metadata/bag.js +2 -1
- package/dist/metadata/bag.js.map +1 -1
- package/dist/metadata/keys.d.ts +203 -1
- package/dist/metadata/keys.d.ts.map +1 -1
- package/dist/metadata/keys.js +3 -9
- package/dist/metadata/keys.js.map +1 -1
- package/dist/metadata/merge.d.ts.map +1 -1
- package/dist/metadata/merge.js +4 -1
- package/dist/metadata/merge.js.map +1 -1
- package/dist/validation/native/schema.d.ts +2 -2
- package/dist/validation/native/schema.d.ts.map +1 -1
- package/dist/validation/native/validator.d.ts +1 -1
- package/dist/validation/native/validator.d.ts.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -9,15 +9,18 @@ Adorn API turns TypeScript classes into HTTP controllers with Stage-3 decorators
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
- Controller decorators (`@Controller`, `@Get`, `@Post`, etc.) backed by a registry/router that mounts on Express.
|
|
12
|
+
- `createAdornExpressRouter` and `buildRegistry` for mounting Adorn into existing Express stacks.
|
|
13
|
+
- Problem Details error handling with an `onError` hook for custom shapes/logging.
|
|
12
14
|
- Built-in OpenAPI generator with optional Swagger UI serving through the Express adapter.
|
|
13
15
|
- MetalORM helpers (`entityDto`, `filtersFromEntity`, `tableDefOf`) to reuse entity metadata for payload validation and database filtering.
|
|
14
16
|
- End-to-end coverage for both direct API handlers and MetalORM REST routes using Vitest + Supertest.
|
|
15
17
|
|
|
16
|
-
For detailed writeups of each feature, see the companion guides under `docs
|
|
18
|
+
For detailed writeups of each feature, see the companion guides under `docs/` (including the Stage-3 decorator setup).
|
|
17
19
|
|
|
18
20
|
## Requirements
|
|
19
21
|
- Node.js v18+
|
|
20
22
|
- SQLite (only for in-memory tests; runtime persistence is pluggable via MetalORM executors)
|
|
23
|
+
- TypeScript 5.x with Stage-3 decorators (do not enable `experimentalDecorators`)
|
|
21
24
|
|
|
22
25
|
## Getting started
|
|
23
26
|
1. `npm install` to pull runtime and dev dependencies (Express, MetalORM, Vitest).
|
|
@@ -1,20 +1,158 @@
|
|
|
1
|
-
import { type Express } from 'express';
|
|
2
|
-
import type { ControllerCtor } from '../../core/registry/types.js';
|
|
1
|
+
import { type Express, type Router } from 'express';
|
|
2
|
+
import type { ControllerCtor, Registry } from '../../core/registry/types.js';
|
|
3
3
|
import type { Validator } from '../../contracts/validator.js';
|
|
4
4
|
import { type ApplyRoutesOptions } from './router.js';
|
|
5
|
+
import { type AdornErrorHandlerOptions } from './middleware/errorHandler.js';
|
|
5
6
|
import type { OpenApiBuildOptions } from '../../core/openapi/buildOpenApi.js';
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Options for OpenAPI documentation generation and serving.
|
|
9
|
+
* Extends OpenApiBuildOptions with serving configuration.
|
|
10
|
+
*/
|
|
11
|
+
export type AdornOpenApiOptions = OpenApiBuildOptions & {
|
|
12
|
+
/** Whether to enable OpenAPI documentation (default: true) */
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
/** Path to serve the OpenAPI JSON specification (default: '/openapi.json') */
|
|
15
|
+
jsonPath?: string;
|
|
16
|
+
/** Path to serve the OpenAPI documentation UI (default: '/docs') */
|
|
17
|
+
docsPath?: string;
|
|
18
|
+
/** Whether to serve Swagger UI (default: true) */
|
|
19
|
+
swaggerUi?: boolean;
|
|
20
|
+
/** Configuration options for Swagger UI */
|
|
21
|
+
swaggerUiConfig?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Options for creating an Adorn Express router with controllers.
|
|
25
|
+
*
|
|
26
|
+
* @see ApplyRoutesOptions for additional routing options
|
|
27
|
+
*/
|
|
28
|
+
export type CreateAdornExpressRouterOptions = ApplyRoutesOptions & {
|
|
29
|
+
/** Array of controller constructors to register */
|
|
7
30
|
controllers: ControllerCtor[];
|
|
8
|
-
|
|
31
|
+
/** Whether to automatically add JSON body parser middleware (default: true) */
|
|
9
32
|
jsonBodyParser?: boolean;
|
|
33
|
+
/** Validator instance for request validation */
|
|
10
34
|
validator?: Validator;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
35
|
+
/** Error handler configuration or false to disable (default: built-in handler) */
|
|
36
|
+
errorHandler?: AdornErrorHandlerOptions | false;
|
|
37
|
+
/** OpenAPI documentation configuration */
|
|
38
|
+
openapi?: AdornOpenApiOptions;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Result of creating an Adorn Express router.
|
|
42
|
+
*/
|
|
43
|
+
export type CreateAdornExpressRouterResult = {
|
|
44
|
+
/** Configured Express router with all routes */
|
|
45
|
+
router: Router;
|
|
46
|
+
/** Route registry containing metadata about all registered routes */
|
|
47
|
+
registry: Registry;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Options for creating an Adorn Express application.
|
|
51
|
+
* Extends router options with mount path configuration.
|
|
52
|
+
*
|
|
53
|
+
* @see CreateAdornExpressRouterOptions for base options
|
|
54
|
+
*/
|
|
55
|
+
export type CreateAdornExpressAppOptions = CreateAdornExpressRouterOptions & {
|
|
56
|
+
/** Path to mount the router (default: '/') */
|
|
57
|
+
mountPath?: string;
|
|
18
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Creates a complete Express application with Adorn API functionality.
|
|
61
|
+
*
|
|
62
|
+
* This function sets up an Express app with all Adorn features including:
|
|
63
|
+
* - Controller-based routing
|
|
64
|
+
* - Automatic OpenAPI documentation
|
|
65
|
+
* - Built-in error handling
|
|
66
|
+
* - Request validation
|
|
67
|
+
*
|
|
68
|
+
* @param options - Configuration options for the application
|
|
69
|
+
* @returns Configured Express application instance
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { createAdornExpressApp } from '@adorn/api';
|
|
74
|
+
* import { UserController } from './controllers/user.controller';
|
|
75
|
+
*
|
|
76
|
+
* const app = createAdornExpressApp({
|
|
77
|
+
* controllers: [UserController],
|
|
78
|
+
* openapi: {
|
|
79
|
+
* title: 'My API',
|
|
80
|
+
* version: '1.0.0'
|
|
81
|
+
* }
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* app.listen(3000, () => {
|
|
85
|
+
* console.log('Server running on port 3000');
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* // With custom mount path
|
|
92
|
+
* const app = createAdornExpressApp({
|
|
93
|
+
* controllers: [UserController, ProductController],
|
|
94
|
+
* mountPath: '/api/v1',
|
|
95
|
+
* jsonBodyParser: true,
|
|
96
|
+
* errorHandler: {
|
|
97
|
+
* logErrors: true,
|
|
98
|
+
* exposeStack: process.env.NODE_ENV === 'development'
|
|
99
|
+
* }
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @see createAdornExpressRouter for router-specific functionality
|
|
104
|
+
* @see AdornOpenApiOptions for OpenAPI configuration
|
|
105
|
+
*/
|
|
19
106
|
export declare function createAdornExpressApp(options: CreateAdornExpressAppOptions): Express;
|
|
107
|
+
/**
|
|
108
|
+
* Creates an Express router with Adorn API functionality.
|
|
109
|
+
*
|
|
110
|
+
* This function sets up an Express router with all Adorn features including:
|
|
111
|
+
* - Controller-based routing
|
|
112
|
+
* - Automatic OpenAPI documentation
|
|
113
|
+
* - Built-in error handling
|
|
114
|
+
* - Request validation
|
|
115
|
+
*
|
|
116
|
+
* @param options - Configuration options for the router
|
|
117
|
+
* @returns Object containing the configured router and route registry
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { createAdornExpressRouter } from '@adorn/api';
|
|
122
|
+
* import { UserController } from './controllers/user.controller';
|
|
123
|
+
* import express from 'express';
|
|
124
|
+
*
|
|
125
|
+
* const app = express();
|
|
126
|
+
* const { router, registry } = createAdornExpressRouter({
|
|
127
|
+
* controllers: [UserController],
|
|
128
|
+
* openapi: {
|
|
129
|
+
* title: 'My API',
|
|
130
|
+
* version: '1.0.0',
|
|
131
|
+
* docsPath: '/api-docs'
|
|
132
|
+
* }
|
|
133
|
+
* });
|
|
134
|
+
*
|
|
135
|
+
* app.use('/api', router);
|
|
136
|
+
*
|
|
137
|
+
* // Access the registry for runtime inspection
|
|
138
|
+
* console.log('Registered routes:', registry.routes.length);
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* // With custom validator and error handling
|
|
144
|
+
* const { router } = createAdornExpressRouter({
|
|
145
|
+
* controllers: [UserController],
|
|
146
|
+
* validator: new CustomValidator(),
|
|
147
|
+
* errorHandler: {
|
|
148
|
+
* logErrors: true,
|
|
149
|
+
* customErrorFormatter: (err) => ({ ...err, timestamp: new Date() })
|
|
150
|
+
* }
|
|
151
|
+
* });
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @see createAdornExpressApp for full application setup
|
|
155
|
+
* @see AdornOpenApiOptions for OpenAPI configuration
|
|
156
|
+
*/
|
|
157
|
+
export declare function createAdornExpressRouter(options: CreateAdornExpressRouterOptions): CreateAdornExpressRouterResult;
|
|
20
158
|
//# sourceMappingURL=createApp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/createApp.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/createApp.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAgC,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAG9E;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,GAAG;IACtD,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,kBAAkB,GAAG;IACjE,mDAAmD;IACnD,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gDAAgD;IAChD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kFAAkF;IAClF,YAAY,CAAC,EAAE,wBAAwB,GAAG,KAAK,CAAC;IAChD,0CAA0C;IAC1C,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,4BAA4B,GAAG,+BAA+B,GAAG;IAC3E,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAKpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,8BAA8B,CAqChC"}
|
|
@@ -1,15 +1,117 @@
|
|
|
1
1
|
import express, {} from 'express';
|
|
2
2
|
import { buildRegistry } from '../../core/registry/buildRegistry.js';
|
|
3
3
|
import { applyRegistryToExpressRouter } from './router.js';
|
|
4
|
-
import { adornErrorHandler } from './middleware/errorHandler.js';
|
|
4
|
+
import { adornErrorHandler, createAdornExpressErrorHandler, } from './middleware/errorHandler.js';
|
|
5
5
|
import { serveOpenApi } from './swagger/serve.js';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a complete Express application with Adorn API functionality.
|
|
8
|
+
*
|
|
9
|
+
* This function sets up an Express app with all Adorn features including:
|
|
10
|
+
* - Controller-based routing
|
|
11
|
+
* - Automatic OpenAPI documentation
|
|
12
|
+
* - Built-in error handling
|
|
13
|
+
* - Request validation
|
|
14
|
+
*
|
|
15
|
+
* @param options - Configuration options for the application
|
|
16
|
+
* @returns Configured Express application instance
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { createAdornExpressApp } from '@adorn/api';
|
|
21
|
+
* import { UserController } from './controllers/user.controller';
|
|
22
|
+
*
|
|
23
|
+
* const app = createAdornExpressApp({
|
|
24
|
+
* controllers: [UserController],
|
|
25
|
+
* openapi: {
|
|
26
|
+
* title: 'My API',
|
|
27
|
+
* version: '1.0.0'
|
|
28
|
+
* }
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* app.listen(3000, () => {
|
|
32
|
+
* console.log('Server running on port 3000');
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* // With custom mount path
|
|
39
|
+
* const app = createAdornExpressApp({
|
|
40
|
+
* controllers: [UserController, ProductController],
|
|
41
|
+
* mountPath: '/api/v1',
|
|
42
|
+
* jsonBodyParser: true,
|
|
43
|
+
* errorHandler: {
|
|
44
|
+
* logErrors: true,
|
|
45
|
+
* exposeStack: process.env.NODE_ENV === 'development'
|
|
46
|
+
* }
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @see createAdornExpressRouter for router-specific functionality
|
|
51
|
+
* @see AdornOpenApiOptions for OpenAPI configuration
|
|
52
|
+
*/
|
|
6
53
|
export function createAdornExpressApp(options) {
|
|
7
54
|
const app = express();
|
|
55
|
+
const { router } = createAdornExpressRouter(options);
|
|
56
|
+
app.use(options.mountPath ?? '/', router);
|
|
57
|
+
return app;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates an Express router with Adorn API functionality.
|
|
61
|
+
*
|
|
62
|
+
* This function sets up an Express router with all Adorn features including:
|
|
63
|
+
* - Controller-based routing
|
|
64
|
+
* - Automatic OpenAPI documentation
|
|
65
|
+
* - Built-in error handling
|
|
66
|
+
* - Request validation
|
|
67
|
+
*
|
|
68
|
+
* @param options - Configuration options for the router
|
|
69
|
+
* @returns Object containing the configured router and route registry
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { createAdornExpressRouter } from '@adorn/api';
|
|
74
|
+
* import { UserController } from './controllers/user.controller';
|
|
75
|
+
* import express from 'express';
|
|
76
|
+
*
|
|
77
|
+
* const app = express();
|
|
78
|
+
* const { router, registry } = createAdornExpressRouter({
|
|
79
|
+
* controllers: [UserController],
|
|
80
|
+
* openapi: {
|
|
81
|
+
* title: 'My API',
|
|
82
|
+
* version: '1.0.0',
|
|
83
|
+
* docsPath: '/api-docs'
|
|
84
|
+
* }
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* app.use('/api', router);
|
|
88
|
+
*
|
|
89
|
+
* // Access the registry for runtime inspection
|
|
90
|
+
* console.log('Registered routes:', registry.routes.length);
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // With custom validator and error handling
|
|
96
|
+
* const { router } = createAdornExpressRouter({
|
|
97
|
+
* controllers: [UserController],
|
|
98
|
+
* validator: new CustomValidator(),
|
|
99
|
+
* errorHandler: {
|
|
100
|
+
* logErrors: true,
|
|
101
|
+
* customErrorFormatter: (err) => ({ ...err, timestamp: new Date() })
|
|
102
|
+
* }
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @see createAdornExpressApp for full application setup
|
|
107
|
+
* @see AdornOpenApiOptions for OpenAPI configuration
|
|
108
|
+
*/
|
|
109
|
+
export function createAdornExpressRouter(options) {
|
|
110
|
+
const router = express.Router();
|
|
8
111
|
if (options.jsonBodyParser ?? true) {
|
|
9
|
-
|
|
112
|
+
router.use(express.json());
|
|
10
113
|
}
|
|
11
114
|
const registry = buildRegistry(options.controllers);
|
|
12
|
-
const router = express.Router();
|
|
13
115
|
applyRegistryToExpressRouter(router, registry, options);
|
|
14
116
|
const oa = options.openapi;
|
|
15
117
|
if (oa?.enabled ?? true) {
|
|
@@ -28,8 +130,12 @@ export function createAdornExpressApp(options) {
|
|
|
28
130
|
router.use(serveOpenApi(registry, openApiOptions, serveOptions));
|
|
29
131
|
}
|
|
30
132
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
133
|
+
if (options.errorHandler !== false) {
|
|
134
|
+
const handler = options.errorHandler
|
|
135
|
+
? createAdornExpressErrorHandler(options.errorHandler)
|
|
136
|
+
: adornErrorHandler;
|
|
137
|
+
router.use(handler);
|
|
138
|
+
}
|
|
139
|
+
return { router, registry };
|
|
34
140
|
}
|
|
35
141
|
//# sourceMappingURL=createApp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createApp.js","sourceRoot":"","sources":["../../../src/adapters/express/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"createApp.js","sourceRoot":"","sources":["../../../src/adapters/express/createApp.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,194 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { ErrorRequestHandler, Request, Response } from 'express';
|
|
2
|
+
import type { ProblemDetails } from '../../../contracts/errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Context object provided to custom error handlers.
|
|
5
|
+
*
|
|
6
|
+
* Contains the Express request and response objects, the request path,
|
|
7
|
+
* and the default problem details that would be returned.
|
|
8
|
+
*/
|
|
9
|
+
export type AdornErrorHandlerContext = {
|
|
10
|
+
/** Express request object */
|
|
11
|
+
req: Request;
|
|
12
|
+
/** Express response object */
|
|
13
|
+
res: Response;
|
|
14
|
+
/** Request path/URL */
|
|
15
|
+
instance: string;
|
|
16
|
+
/** Default problem details that would be returned */
|
|
17
|
+
defaultProblem: ProblemDetails;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Result types that can be returned from a custom error handler.
|
|
21
|
+
*
|
|
22
|
+
* Supports returning ProblemDetails, custom responses, or void (to use default).
|
|
23
|
+
*/
|
|
24
|
+
export type AdornErrorHandlerResult = ProblemDetails | {
|
|
25
|
+
status: number;
|
|
26
|
+
body: unknown;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
} | void;
|
|
29
|
+
/**
|
|
30
|
+
* Options for configuring the Adorn error handler.
|
|
31
|
+
*
|
|
32
|
+
* Allows customization of error handling behavior through the onError callback.
|
|
33
|
+
*/
|
|
34
|
+
export type AdornErrorHandlerOptions = {
|
|
35
|
+
/**
|
|
36
|
+
* Custom error handler function.
|
|
37
|
+
*
|
|
38
|
+
* @param err - The error that occurred
|
|
39
|
+
* @param ctx - Error handler context with request/response info
|
|
40
|
+
* @returns Custom error response, problem details, or void to use default
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // Custom error formatting
|
|
45
|
+
* onError: (err, ctx) => {
|
|
46
|
+
* if (err instanceof ValidationError) {
|
|
47
|
+
* return {
|
|
48
|
+
* status: 400,
|
|
49
|
+
* body: {
|
|
50
|
+
* success: false,
|
|
51
|
+
* errors: err.issues,
|
|
52
|
+
* timestamp: new Date().toISOString()
|
|
53
|
+
* }
|
|
54
|
+
* };
|
|
55
|
+
* }
|
|
56
|
+
* return ctx.defaultProblem; // Use default for other errors
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
onError?: (err: unknown, ctx: AdornErrorHandlerContext) => AdornErrorHandlerResult;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Default Adorn error handler for Express applications.
|
|
64
|
+
*
|
|
65
|
+
* This is the built-in error handler that converts errors to appropriate
|
|
66
|
+
* HTTP responses. It handles HttpError, ValidationError, and other errors
|
|
67
|
+
* by converting them to Problem Details format.
|
|
68
|
+
*
|
|
69
|
+
* @param err - The error that occurred
|
|
70
|
+
* @param req - Express request object
|
|
71
|
+
* @param res - Express response object
|
|
72
|
+
* @param next - Express next function
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Basic usage in Express app
|
|
77
|
+
* import { adornErrorHandler } from '@adorn/api';
|
|
78
|
+
*
|
|
79
|
+
* const app = express();
|
|
80
|
+
* // ... routes and middleware
|
|
81
|
+
* app.use(adornErrorHandler); // Use as last middleware
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // With custom error handling
|
|
87
|
+
* app.use((err, req, res, next) => {
|
|
88
|
+
* // Custom logging
|
|
89
|
+
* console.error('Error occurred:', err);
|
|
90
|
+
*
|
|
91
|
+
* // Use adorn error handler
|
|
92
|
+
* adornErrorHandler(err, req, res, next);
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @see createAdornExpressErrorHandler for customizable error handler
|
|
97
|
+
* @see HttpError for HTTP error class
|
|
98
|
+
*/
|
|
99
|
+
export declare function adornErrorHandler(err: unknown, req: Request, res: Response, next: Parameters<ErrorRequestHandler>[3]): unknown;
|
|
100
|
+
/**
|
|
101
|
+
* Creates a customizable Adorn error handler for Express applications.
|
|
102
|
+
*
|
|
103
|
+
* This function allows customization of error handling behavior while
|
|
104
|
+
* maintaining the core functionality of converting errors to appropriate
|
|
105
|
+
* HTTP responses.
|
|
106
|
+
*
|
|
107
|
+
* @param options - Error handler configuration options
|
|
108
|
+
* @returns Express error request handler function
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* // Basic custom error handler
|
|
113
|
+
* const errorHandler = createAdornExpressErrorHandler({
|
|
114
|
+
* onError: (err, ctx) => {
|
|
115
|
+
* // Add custom logging
|
|
116
|
+
* console.error('Error:', err.message, 'Path:', ctx.instance);
|
|
117
|
+
*
|
|
118
|
+
* // Return default problem details
|
|
119
|
+
* return ctx.defaultProblem;
|
|
120
|
+
* }
|
|
121
|
+
* });
|
|
122
|
+
*
|
|
123
|
+
* app.use(errorHandler);
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* // Advanced error handling with custom responses
|
|
129
|
+
* const errorHandler = createAdornExpressErrorHandler({
|
|
130
|
+
* onError: (err, ctx) => {
|
|
131
|
+
* if (err instanceof ValidationError) {
|
|
132
|
+
* return {
|
|
133
|
+
* status: 400,
|
|
134
|
+
* body: {
|
|
135
|
+
* success: false,
|
|
136
|
+
* type: 'validation_error',
|
|
137
|
+
* issues: err.issues,
|
|
138
|
+
* timestamp: new Date().toISOString(),
|
|
139
|
+
* requestId: ctx.req.id
|
|
140
|
+
* },
|
|
141
|
+
* headers: {
|
|
142
|
+
* 'X-Error-Type': 'validation'
|
|
143
|
+
* }
|
|
144
|
+
* };
|
|
145
|
+
* }
|
|
146
|
+
*
|
|
147
|
+
* if (err instanceof HttpError && err.status === 404) {
|
|
148
|
+
* return {
|
|
149
|
+
* status: 404,
|
|
150
|
+
* body: {
|
|
151
|
+
* success: false,
|
|
152
|
+
* type: 'not_found',
|
|
153
|
+
* message: 'Resource not found',
|
|
154
|
+
* details: err.details
|
|
155
|
+
* }
|
|
156
|
+
* };
|
|
157
|
+
* }
|
|
158
|
+
*
|
|
159
|
+
* // Use default for other errors
|
|
160
|
+
* return ctx.defaultProblem;
|
|
161
|
+
* }
|
|
162
|
+
* });
|
|
163
|
+
*
|
|
164
|
+
* app.use(errorHandler);
|
|
165
|
+
* ```
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* // Error handler with request ID correlation
|
|
170
|
+
* const errorHandler = createAdornExpressErrorHandler({
|
|
171
|
+
* onError: (err, ctx) => {
|
|
172
|
+
* const requestId = ctx.req.headers['x-request-id'] || ctx.req.id;
|
|
173
|
+
*
|
|
174
|
+
* // Add request ID to all error responses
|
|
175
|
+
* const problem = ctx.defaultProblem;
|
|
176
|
+
* return {
|
|
177
|
+
* ...problem,
|
|
178
|
+
* body: {
|
|
179
|
+
* ...problem,
|
|
180
|
+
* requestId,
|
|
181
|
+
* timestamp: new Date().toISOString()
|
|
182
|
+
* }
|
|
183
|
+
* };
|
|
184
|
+
* }
|
|
185
|
+
* });
|
|
186
|
+
*
|
|
187
|
+
* app.use(errorHandler);
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @see adornErrorHandler for the default error handler
|
|
191
|
+
* @see AdornErrorHandlerOptions for configuration options
|
|
192
|
+
*/
|
|
193
|
+
export declare function createAdornExpressErrorHandler(options?: AdornErrorHandlerOptions): ErrorRequestHandler;
|
|
3
194
|
//# sourceMappingURL=errorHandler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapters/express/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapters/express/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,6BAA6B;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,8BAA8B;IAC9B,GAAG,EAAE,QAAQ,CAAC;IACd,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,cAAc,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd;IACE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,GACD,IAAI,CAAC;AAET;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,wBAAwB,KAAK,uBAAuB,CAAC;CACpF,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,WAGzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4FG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,wBAA6B,GACrC,mBAAmB,CA+BrB"}
|