@cosmneo/onion-lasagna 0.1.0
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/dist/backend/core/global.cjs +283 -0
- package/dist/backend/core/global.cjs.map +1 -0
- package/dist/backend/core/global.d.cts +294 -0
- package/dist/backend/core/global.d.ts +294 -0
- package/dist/backend/core/global.js +39 -0
- package/dist/backend/core/global.js.map +1 -0
- package/dist/backend/core/onion-layers.cjs +2302 -0
- package/dist/backend/core/onion-layers.cjs.map +1 -0
- package/dist/backend/core/onion-layers.d.cts +1675 -0
- package/dist/backend/core/onion-layers.d.ts +1675 -0
- package/dist/backend/core/onion-layers.js +1158 -0
- package/dist/backend/core/onion-layers.js.map +1 -0
- package/dist/backend/core/presentation.cjs +573 -0
- package/dist/backend/core/presentation.cjs.map +1 -0
- package/dist/backend/core/presentation.d.cts +5 -0
- package/dist/backend/core/presentation.d.ts +5 -0
- package/dist/backend/core/presentation.js +28 -0
- package/dist/backend/core/presentation.js.map +1 -0
- package/dist/backend/core/validators/arktype.cjs +947 -0
- package/dist/backend/core/validators/arktype.cjs.map +1 -0
- package/dist/backend/core/validators/arktype.d.cts +188 -0
- package/dist/backend/core/validators/arktype.d.ts +188 -0
- package/dist/backend/core/validators/arktype.js +287 -0
- package/dist/backend/core/validators/arktype.js.map +1 -0
- package/dist/backend/core/validators/typebox.cjs +939 -0
- package/dist/backend/core/validators/typebox.cjs.map +1 -0
- package/dist/backend/core/validators/typebox.d.cts +189 -0
- package/dist/backend/core/validators/typebox.d.ts +189 -0
- package/dist/backend/core/validators/typebox.js +281 -0
- package/dist/backend/core/validators/typebox.js.map +1 -0
- package/dist/backend/core/validators/valibot.cjs +942 -0
- package/dist/backend/core/validators/valibot.cjs.map +1 -0
- package/dist/backend/core/validators/valibot.d.cts +160 -0
- package/dist/backend/core/validators/valibot.d.ts +160 -0
- package/dist/backend/core/validators/valibot.js +294 -0
- package/dist/backend/core/validators/valibot.js.map +1 -0
- package/dist/backend/core/validators/zod.cjs +934 -0
- package/dist/backend/core/validators/zod.cjs.map +1 -0
- package/dist/backend/core/validators/zod.d.cts +188 -0
- package/dist/backend/core/validators/zod.d.ts +188 -0
- package/dist/backend/core/validators/zod.js +278 -0
- package/dist/backend/core/validators/zod.js.map +1 -0
- package/dist/backend/frameworks/elysia.cjs +715 -0
- package/dist/backend/frameworks/elysia.cjs.map +1 -0
- package/dist/backend/frameworks/elysia.d.cts +208 -0
- package/dist/backend/frameworks/elysia.d.ts +208 -0
- package/dist/backend/frameworks/elysia.js +251 -0
- package/dist/backend/frameworks/elysia.js.map +1 -0
- package/dist/backend/frameworks/fastify.cjs +677 -0
- package/dist/backend/frameworks/fastify.cjs.map +1 -0
- package/dist/backend/frameworks/fastify.d.cts +201 -0
- package/dist/backend/frameworks/fastify.d.ts +201 -0
- package/dist/backend/frameworks/fastify.js +213 -0
- package/dist/backend/frameworks/fastify.js.map +1 -0
- package/dist/backend/frameworks/hono.cjs +715 -0
- package/dist/backend/frameworks/hono.cjs.map +1 -0
- package/dist/backend/frameworks/hono.d.cts +163 -0
- package/dist/backend/frameworks/hono.d.ts +163 -0
- package/dist/backend/frameworks/hono.js +249 -0
- package/dist/backend/frameworks/hono.js.map +1 -0
- package/dist/backend/frameworks/nestjs.cjs +260 -0
- package/dist/backend/frameworks/nestjs.cjs.map +1 -0
- package/dist/backend/frameworks/nestjs.d.cts +168 -0
- package/dist/backend/frameworks/nestjs.d.ts +168 -0
- package/dist/backend/frameworks/nestjs.js +193 -0
- package/dist/backend/frameworks/nestjs.js.map +1 -0
- package/dist/base-dto.class-D7W9iqoU.d.cts +146 -0
- package/dist/base-dto.class-D7W9iqoU.d.ts +146 -0
- package/dist/base-uuid-v7.vo-BPGEIWLM.d.ts +799 -0
- package/dist/base-uuid-v7.vo-BjqKX44G.d.cts +799 -0
- package/dist/chunk-74IKUOSE.js +116 -0
- package/dist/chunk-74IKUOSE.js.map +1 -0
- package/dist/chunk-BKZOLGQW.js +29 -0
- package/dist/chunk-BKZOLGQW.js.map +1 -0
- package/dist/chunk-CGZBV6BD.js +54 -0
- package/dist/chunk-CGZBV6BD.js.map +1 -0
- package/dist/chunk-DDAHJZVK.js +258 -0
- package/dist/chunk-DDAHJZVK.js.map +1 -0
- package/dist/chunk-MQD5GXMT.js +171 -0
- package/dist/chunk-MQD5GXMT.js.map +1 -0
- package/dist/chunk-OKFXZHBC.js +43 -0
- package/dist/chunk-OKFXZHBC.js.map +1 -0
- package/dist/chunk-RLLWYFPI.js +168 -0
- package/dist/chunk-RLLWYFPI.js.map +1 -0
- package/dist/chunk-VCHFXT5W.js +425 -0
- package/dist/chunk-VCHFXT5W.js.map +1 -0
- package/dist/chunk-ZWLYNGO3.js +40 -0
- package/dist/chunk-ZWLYNGO3.js.map +1 -0
- package/dist/http-response-BAhi8lF4.d.cts +124 -0
- package/dist/http-response-BAhi8lF4.d.ts +124 -0
- package/dist/index-DingXh7B.d.cts +1187 -0
- package/dist/index-tOH7XBa3.d.ts +1187 -0
- package/dist/routing.type-DB4pt-d9.d.ts +184 -0
- package/dist/routing.type-DF2BIL7x.d.cts +184 -0
- package/dist/validation-error.type-kD4_qNZ9.d.cts +199 -0
- package/dist/validation-error.type-kD4_qNZ9.d.ts +199 -0
- package/package.json +191 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { B as BaseDto } from './base-dto.class-D7W9iqoU.js';
|
|
2
|
+
import { H as HttpRequest, a as HttpResponse, C as Controller } from './http-response-BAhi8lF4.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Core routing types for the presentation layer.
|
|
6
|
+
*
|
|
7
|
+
* This module provides framework-agnostic routing abstractions that can be
|
|
8
|
+
* used with any HTTP framework (Hono, Fastify, Elysia, etc.).
|
|
9
|
+
*
|
|
10
|
+
* @example Basic route definition
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import type { RouteInput } from '@cosmneo/onion-lasagna/backend/core/presentation';
|
|
13
|
+
*
|
|
14
|
+
* const getUserRoute: RouteInput<GetUserRequestDto, GetUserResponseDto> = {
|
|
15
|
+
* metadata: { path: '/users/{id}', method: 'GET' },
|
|
16
|
+
* controller: getUserController,
|
|
17
|
+
* requestDtoFactory: (req) => GetUserRequestDto.create(req),
|
|
18
|
+
* };
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module routing
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Standard HTTP methods supported by the routing system.
|
|
26
|
+
*
|
|
27
|
+
* Includes all methods commonly used in RESTful APIs:
|
|
28
|
+
* - `GET` - Retrieve a resource
|
|
29
|
+
* - `POST` - Create a new resource
|
|
30
|
+
* - `PUT` - Replace a resource
|
|
31
|
+
* - `PATCH` - Partially update a resource
|
|
32
|
+
* - `DELETE` - Remove a resource
|
|
33
|
+
* - `OPTIONS` - CORS preflight and capability discovery
|
|
34
|
+
* - `HEAD` - Retrieve headers only (no body)
|
|
35
|
+
*/
|
|
36
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
37
|
+
/**
|
|
38
|
+
* HTTP endpoint metadata defining the route's method and path.
|
|
39
|
+
*
|
|
40
|
+
* Path parameters use curly brace syntax (`{param}`) which is framework-agnostic.
|
|
41
|
+
* Each framework adapter converts this to its native format:
|
|
42
|
+
* - Hono/Express: `/users/:id`
|
|
43
|
+
* - Fastify: `/users/:id`
|
|
44
|
+
* - AWS API Gateway: `/users/{id}`
|
|
45
|
+
*
|
|
46
|
+
* The `path` should be the full route path (computed from service + resource + endpoint
|
|
47
|
+
* using `computeRoutePath()` when needed).
|
|
48
|
+
*
|
|
49
|
+
* @example Simple route
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const metadata: RouteMetadata = {
|
|
52
|
+
* path: '/health',
|
|
53
|
+
* method: 'GET',
|
|
54
|
+
* };
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example Route with path parameters
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const metadata: RouteMetadata = {
|
|
60
|
+
* path: '/users/{userId}/orders/{orderId}',
|
|
61
|
+
* method: 'GET',
|
|
62
|
+
* };
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
interface RouteMetadata {
|
|
66
|
+
/**
|
|
67
|
+
* Full path pattern for the route.
|
|
68
|
+
*
|
|
69
|
+
* Uses curly brace syntax for path parameters: `/users/{id}`
|
|
70
|
+
*
|
|
71
|
+
* This should be the complete path including service and resource segments.
|
|
72
|
+
* Use `computeRoutePath()` to compute from service, resource, and endpoint metadata.
|
|
73
|
+
*
|
|
74
|
+
* @example '/users'
|
|
75
|
+
* @example '/users/{id}'
|
|
76
|
+
* @example '/organizations/{orgId}/members/{memberId}'
|
|
77
|
+
*/
|
|
78
|
+
path: string;
|
|
79
|
+
/**
|
|
80
|
+
* The HTTP method for this route.
|
|
81
|
+
*
|
|
82
|
+
* Accepts either uppercase (`'GET'`) or lowercase (`'get'`) format.
|
|
83
|
+
* Framework adapters normalize to lowercase for registration.
|
|
84
|
+
*/
|
|
85
|
+
method: HttpMethod | Uppercase<HttpMethod> | Lowercase<HttpMethod>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Factory function that creates a validated request DTO from an HTTP request.
|
|
89
|
+
*
|
|
90
|
+
* This factory is called by framework adapters to transform the HTTP request
|
|
91
|
+
* (body, headers, query params, path params) into a validated DTO before passing
|
|
92
|
+
* to the controller.
|
|
93
|
+
*
|
|
94
|
+
* @typeParam TRequestDto - The validated request DTO type (must extend BaseDto)
|
|
95
|
+
*
|
|
96
|
+
* @example Creating from HttpRequest
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const factory: RequestDtoFactory<CreateUserRequestDto> = (req) =>
|
|
99
|
+
* CreateUserRequestDto.create({
|
|
100
|
+
* name: req.body.name,
|
|
101
|
+
* email: req.body.email,
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example With path parameters
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const factory: RequestDtoFactory<GetUserRequestDto> = (req) =>
|
|
108
|
+
* GetUserRequestDto.create({
|
|
109
|
+
* userId: req.pathParams?.id,
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
type RequestDtoFactory<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>> = (request: HttpRequest) => TRequestDto;
|
|
114
|
+
/**
|
|
115
|
+
* Complete route definition combining metadata, controller, and request factory.
|
|
116
|
+
*
|
|
117
|
+
* This is the primary type used to define routes in a framework-agnostic way.
|
|
118
|
+
* Framework adapters (Hono, Fastify, Elysia) accept arrays of `RouteInput` and
|
|
119
|
+
* register them with the underlying framework.
|
|
120
|
+
*
|
|
121
|
+
* The controller receives a validated `TRequestDto` and returns a `TResponseDto`
|
|
122
|
+
* wrapping an {@link HttpResponse}. Framework adapters extract `.data` from the
|
|
123
|
+
* response DTO to get the actual HTTP response.
|
|
124
|
+
*
|
|
125
|
+
* @typeParam TRequestDto - The validated request DTO type
|
|
126
|
+
* @typeParam TResponseDto - The response DTO type (wraps HttpResponse)
|
|
127
|
+
*
|
|
128
|
+
* @example Single route definition
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const createUserRoute: RouteInput<CreateUserRequestDto, CreateUserResponseDto> = {
|
|
131
|
+
* metadata: { path: '/users', method: 'POST' },
|
|
132
|
+
* controller: createUserController,
|
|
133
|
+
* requestDtoFactory: (req) => CreateUserRequestDto.create(req.body),
|
|
134
|
+
* };
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example Route array for a resource
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const userRoutes: RouteInput[] = [
|
|
140
|
+
* {
|
|
141
|
+
* metadata: { path: '/users', method: 'GET' },
|
|
142
|
+
* controller: listUsersController,
|
|
143
|
+
* requestDtoFactory: (req) => ListUsersRequestDto.create(req.queryParams),
|
|
144
|
+
* },
|
|
145
|
+
* {
|
|
146
|
+
* metadata: { path: '/users/{id}', method: 'GET' },
|
|
147
|
+
* controller: getUserController,
|
|
148
|
+
* requestDtoFactory: (req) => GetUserRequestDto.create(req.pathParams),
|
|
149
|
+
* },
|
|
150
|
+
* ];
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @example Registering with Hono
|
|
154
|
+
* ```typescript
|
|
155
|
+
* import { registerHonoRoutes } from '@cosmneo/onion-lasagna/backend/frameworks/hono';
|
|
156
|
+
*
|
|
157
|
+
* const app = new Hono();
|
|
158
|
+
* registerHonoRoutes(app, userRoutes, { prefix: '/api/v1' });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
interface RouteInput<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>, TResponseDto extends BaseDto<HttpResponse> = BaseDto<HttpResponse>> {
|
|
162
|
+
/**
|
|
163
|
+
* Route metadata defining the HTTP method and path.
|
|
164
|
+
*/
|
|
165
|
+
metadata: RouteMetadata;
|
|
166
|
+
/**
|
|
167
|
+
* The controller that handles requests to this route.
|
|
168
|
+
*
|
|
169
|
+
* Receives a validated request DTO and returns a response DTO
|
|
170
|
+
* wrapping an {@link HttpResponse}.
|
|
171
|
+
*/
|
|
172
|
+
controller: Controller<TRequestDto, TResponseDto>;
|
|
173
|
+
/**
|
|
174
|
+
* Factory to create a validated request DTO from the raw framework request.
|
|
175
|
+
*
|
|
176
|
+
* The framework adapter calls this factory to transform the raw HTTP request
|
|
177
|
+
* into a validated DTO before invoking the controller.
|
|
178
|
+
*
|
|
179
|
+
* @throws {ObjectValidationError} When the raw request fails DTO validation
|
|
180
|
+
*/
|
|
181
|
+
requestDtoFactory: RequestDtoFactory<TRequestDto>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type { HttpMethod as H, RouteInput as R, RouteMetadata as a, RequestDtoFactory as b };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { B as BaseDto } from './base-dto.class-D7W9iqoU.cjs';
|
|
2
|
+
import { H as HttpRequest, a as HttpResponse, C as Controller } from './http-response-BAhi8lF4.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Core routing types for the presentation layer.
|
|
6
|
+
*
|
|
7
|
+
* This module provides framework-agnostic routing abstractions that can be
|
|
8
|
+
* used with any HTTP framework (Hono, Fastify, Elysia, etc.).
|
|
9
|
+
*
|
|
10
|
+
* @example Basic route definition
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import type { RouteInput } from '@cosmneo/onion-lasagna/backend/core/presentation';
|
|
13
|
+
*
|
|
14
|
+
* const getUserRoute: RouteInput<GetUserRequestDto, GetUserResponseDto> = {
|
|
15
|
+
* metadata: { path: '/users/{id}', method: 'GET' },
|
|
16
|
+
* controller: getUserController,
|
|
17
|
+
* requestDtoFactory: (req) => GetUserRequestDto.create(req),
|
|
18
|
+
* };
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module routing
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Standard HTTP methods supported by the routing system.
|
|
26
|
+
*
|
|
27
|
+
* Includes all methods commonly used in RESTful APIs:
|
|
28
|
+
* - `GET` - Retrieve a resource
|
|
29
|
+
* - `POST` - Create a new resource
|
|
30
|
+
* - `PUT` - Replace a resource
|
|
31
|
+
* - `PATCH` - Partially update a resource
|
|
32
|
+
* - `DELETE` - Remove a resource
|
|
33
|
+
* - `OPTIONS` - CORS preflight and capability discovery
|
|
34
|
+
* - `HEAD` - Retrieve headers only (no body)
|
|
35
|
+
*/
|
|
36
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
37
|
+
/**
|
|
38
|
+
* HTTP endpoint metadata defining the route's method and path.
|
|
39
|
+
*
|
|
40
|
+
* Path parameters use curly brace syntax (`{param}`) which is framework-agnostic.
|
|
41
|
+
* Each framework adapter converts this to its native format:
|
|
42
|
+
* - Hono/Express: `/users/:id`
|
|
43
|
+
* - Fastify: `/users/:id`
|
|
44
|
+
* - AWS API Gateway: `/users/{id}`
|
|
45
|
+
*
|
|
46
|
+
* The `path` should be the full route path (computed from service + resource + endpoint
|
|
47
|
+
* using `computeRoutePath()` when needed).
|
|
48
|
+
*
|
|
49
|
+
* @example Simple route
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const metadata: RouteMetadata = {
|
|
52
|
+
* path: '/health',
|
|
53
|
+
* method: 'GET',
|
|
54
|
+
* };
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example Route with path parameters
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const metadata: RouteMetadata = {
|
|
60
|
+
* path: '/users/{userId}/orders/{orderId}',
|
|
61
|
+
* method: 'GET',
|
|
62
|
+
* };
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
interface RouteMetadata {
|
|
66
|
+
/**
|
|
67
|
+
* Full path pattern for the route.
|
|
68
|
+
*
|
|
69
|
+
* Uses curly brace syntax for path parameters: `/users/{id}`
|
|
70
|
+
*
|
|
71
|
+
* This should be the complete path including service and resource segments.
|
|
72
|
+
* Use `computeRoutePath()` to compute from service, resource, and endpoint metadata.
|
|
73
|
+
*
|
|
74
|
+
* @example '/users'
|
|
75
|
+
* @example '/users/{id}'
|
|
76
|
+
* @example '/organizations/{orgId}/members/{memberId}'
|
|
77
|
+
*/
|
|
78
|
+
path: string;
|
|
79
|
+
/**
|
|
80
|
+
* The HTTP method for this route.
|
|
81
|
+
*
|
|
82
|
+
* Accepts either uppercase (`'GET'`) or lowercase (`'get'`) format.
|
|
83
|
+
* Framework adapters normalize to lowercase for registration.
|
|
84
|
+
*/
|
|
85
|
+
method: HttpMethod | Uppercase<HttpMethod> | Lowercase<HttpMethod>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Factory function that creates a validated request DTO from an HTTP request.
|
|
89
|
+
*
|
|
90
|
+
* This factory is called by framework adapters to transform the HTTP request
|
|
91
|
+
* (body, headers, query params, path params) into a validated DTO before passing
|
|
92
|
+
* to the controller.
|
|
93
|
+
*
|
|
94
|
+
* @typeParam TRequestDto - The validated request DTO type (must extend BaseDto)
|
|
95
|
+
*
|
|
96
|
+
* @example Creating from HttpRequest
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const factory: RequestDtoFactory<CreateUserRequestDto> = (req) =>
|
|
99
|
+
* CreateUserRequestDto.create({
|
|
100
|
+
* name: req.body.name,
|
|
101
|
+
* email: req.body.email,
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example With path parameters
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const factory: RequestDtoFactory<GetUserRequestDto> = (req) =>
|
|
108
|
+
* GetUserRequestDto.create({
|
|
109
|
+
* userId: req.pathParams?.id,
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
type RequestDtoFactory<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>> = (request: HttpRequest) => TRequestDto;
|
|
114
|
+
/**
|
|
115
|
+
* Complete route definition combining metadata, controller, and request factory.
|
|
116
|
+
*
|
|
117
|
+
* This is the primary type used to define routes in a framework-agnostic way.
|
|
118
|
+
* Framework adapters (Hono, Fastify, Elysia) accept arrays of `RouteInput` and
|
|
119
|
+
* register them with the underlying framework.
|
|
120
|
+
*
|
|
121
|
+
* The controller receives a validated `TRequestDto` and returns a `TResponseDto`
|
|
122
|
+
* wrapping an {@link HttpResponse}. Framework adapters extract `.data` from the
|
|
123
|
+
* response DTO to get the actual HTTP response.
|
|
124
|
+
*
|
|
125
|
+
* @typeParam TRequestDto - The validated request DTO type
|
|
126
|
+
* @typeParam TResponseDto - The response DTO type (wraps HttpResponse)
|
|
127
|
+
*
|
|
128
|
+
* @example Single route definition
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const createUserRoute: RouteInput<CreateUserRequestDto, CreateUserResponseDto> = {
|
|
131
|
+
* metadata: { path: '/users', method: 'POST' },
|
|
132
|
+
* controller: createUserController,
|
|
133
|
+
* requestDtoFactory: (req) => CreateUserRequestDto.create(req.body),
|
|
134
|
+
* };
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example Route array for a resource
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const userRoutes: RouteInput[] = [
|
|
140
|
+
* {
|
|
141
|
+
* metadata: { path: '/users', method: 'GET' },
|
|
142
|
+
* controller: listUsersController,
|
|
143
|
+
* requestDtoFactory: (req) => ListUsersRequestDto.create(req.queryParams),
|
|
144
|
+
* },
|
|
145
|
+
* {
|
|
146
|
+
* metadata: { path: '/users/{id}', method: 'GET' },
|
|
147
|
+
* controller: getUserController,
|
|
148
|
+
* requestDtoFactory: (req) => GetUserRequestDto.create(req.pathParams),
|
|
149
|
+
* },
|
|
150
|
+
* ];
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @example Registering with Hono
|
|
154
|
+
* ```typescript
|
|
155
|
+
* import { registerHonoRoutes } from '@cosmneo/onion-lasagna/backend/frameworks/hono';
|
|
156
|
+
*
|
|
157
|
+
* const app = new Hono();
|
|
158
|
+
* registerHonoRoutes(app, userRoutes, { prefix: '/api/v1' });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
interface RouteInput<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>, TResponseDto extends BaseDto<HttpResponse> = BaseDto<HttpResponse>> {
|
|
162
|
+
/**
|
|
163
|
+
* Route metadata defining the HTTP method and path.
|
|
164
|
+
*/
|
|
165
|
+
metadata: RouteMetadata;
|
|
166
|
+
/**
|
|
167
|
+
* The controller that handles requests to this route.
|
|
168
|
+
*
|
|
169
|
+
* Receives a validated request DTO and returns a response DTO
|
|
170
|
+
* wrapping an {@link HttpResponse}.
|
|
171
|
+
*/
|
|
172
|
+
controller: Controller<TRequestDto, TResponseDto>;
|
|
173
|
+
/**
|
|
174
|
+
* Factory to create a validated request DTO from the raw framework request.
|
|
175
|
+
*
|
|
176
|
+
* The framework adapter calls this factory to transform the raw HTTP request
|
|
177
|
+
* into a validated DTO before invoking the controller.
|
|
178
|
+
*
|
|
179
|
+
* @throws {ObjectValidationError} When the raw request fails DTO validation
|
|
180
|
+
*/
|
|
181
|
+
requestDtoFactory: RequestDtoFactory<TRequestDto>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type { HttpMethod as H, RouteInput as R, RouteMetadata as a, RequestDtoFactory as b };
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized registry of all error codes used across the application.
|
|
3
|
+
*
|
|
4
|
+
* Error codes are grouped by architectural layer to maintain clear boundaries
|
|
5
|
+
* and make it easy to identify where an error originated.
|
|
6
|
+
*
|
|
7
|
+
* @example Using error codes in custom errors
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { ErrorCodes } from '@cosmneo/onion-lasagna/backend/core/global';
|
|
10
|
+
*
|
|
11
|
+
* throw new NotFoundError({
|
|
12
|
+
* message: 'User not found',
|
|
13
|
+
* code: ErrorCodes.App.NOT_FOUND,
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @example Checking error codes programmatically
|
|
18
|
+
* ```typescript
|
|
19
|
+
* if (error.code === ErrorCodes.App.NOT_FOUND) {
|
|
20
|
+
* // Handle not found case
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare const ErrorCodes: {
|
|
25
|
+
/**
|
|
26
|
+
* Domain layer error codes.
|
|
27
|
+
* Used for business rule violations and invariant failures.
|
|
28
|
+
*/
|
|
29
|
+
readonly Domain: {
|
|
30
|
+
/** Generic domain error */
|
|
31
|
+
readonly DOMAIN_ERROR: "DOMAIN_ERROR";
|
|
32
|
+
/** Business invariant was violated */
|
|
33
|
+
readonly INVARIANT_VIOLATION: "INVARIANT_VIOLATION";
|
|
34
|
+
/** Aggregate was partially loaded (missing required relations) */
|
|
35
|
+
readonly PARTIAL_LOAD: "PARTIAL_LOAD";
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Application layer (use case) error codes.
|
|
39
|
+
* Used for orchestration failures and business operation errors.
|
|
40
|
+
*/
|
|
41
|
+
readonly App: {
|
|
42
|
+
/** Generic use case error */
|
|
43
|
+
readonly USE_CASE_ERROR: "USE_CASE_ERROR";
|
|
44
|
+
/** Requested resource was not found */
|
|
45
|
+
readonly NOT_FOUND: "NOT_FOUND";
|
|
46
|
+
/** Resource state conflict (e.g., duplicate, already exists) */
|
|
47
|
+
readonly CONFLICT: "CONFLICT";
|
|
48
|
+
/** Request is valid but cannot be processed due to business rules */
|
|
49
|
+
readonly UNPROCESSABLE: "UNPROCESSABLE";
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Infrastructure layer error codes.
|
|
53
|
+
* Used for data access, external services, and I/O failures.
|
|
54
|
+
*/
|
|
55
|
+
readonly Infra: {
|
|
56
|
+
/** Generic infrastructure error */
|
|
57
|
+
readonly INFRA_ERROR: "INFRA_ERROR";
|
|
58
|
+
/** Database operation failed */
|
|
59
|
+
readonly DB_ERROR: "DB_ERROR";
|
|
60
|
+
/** Network connectivity or communication error */
|
|
61
|
+
readonly NETWORK_ERROR: "NETWORK_ERROR";
|
|
62
|
+
/** Operation timed out */
|
|
63
|
+
readonly TIMEOUT_ERROR: "TIMEOUT_ERROR";
|
|
64
|
+
/** External/third-party service error */
|
|
65
|
+
readonly EXTERNAL_SERVICE_ERROR: "EXTERNAL_SERVICE_ERROR";
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Presentation layer error codes.
|
|
69
|
+
* Used for controller, request handling, and authorization errors.
|
|
70
|
+
*/
|
|
71
|
+
readonly Presentation: {
|
|
72
|
+
/** Generic controller error */
|
|
73
|
+
readonly CONTROLLER_ERROR: "CONTROLLER_ERROR";
|
|
74
|
+
/** Request denied due to authorization failure */
|
|
75
|
+
readonly ACCESS_DENIED: "ACCESS_DENIED";
|
|
76
|
+
/** Request validation failed (malformed input) */
|
|
77
|
+
readonly INVALID_REQUEST: "INVALID_REQUEST";
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Global/cross-cutting error codes.
|
|
81
|
+
* Used for validation and other cross-layer concerns.
|
|
82
|
+
*/
|
|
83
|
+
readonly Global: {
|
|
84
|
+
/** Object/schema validation failed */
|
|
85
|
+
readonly OBJECT_VALIDATION_ERROR: "OBJECT_VALIDATION_ERROR";
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Type representing all possible domain error codes.
|
|
90
|
+
*/
|
|
91
|
+
type DomainErrorCode = (typeof ErrorCodes.Domain)[keyof typeof ErrorCodes.Domain];
|
|
92
|
+
/**
|
|
93
|
+
* Type representing all possible application error codes.
|
|
94
|
+
*/
|
|
95
|
+
type AppErrorCode = (typeof ErrorCodes.App)[keyof typeof ErrorCodes.App];
|
|
96
|
+
/**
|
|
97
|
+
* Type representing all possible infrastructure error codes.
|
|
98
|
+
*/
|
|
99
|
+
type InfraErrorCode = (typeof ErrorCodes.Infra)[keyof typeof ErrorCodes.Infra];
|
|
100
|
+
/**
|
|
101
|
+
* Type representing all possible presentation error codes.
|
|
102
|
+
*/
|
|
103
|
+
type PresentationErrorCode = (typeof ErrorCodes.Presentation)[keyof typeof ErrorCodes.Presentation];
|
|
104
|
+
/**
|
|
105
|
+
* Type representing all possible global error codes.
|
|
106
|
+
*/
|
|
107
|
+
type GlobalErrorCode = (typeof ErrorCodes.Global)[keyof typeof ErrorCodes.Global];
|
|
108
|
+
/**
|
|
109
|
+
* Union type of all error codes across all layers.
|
|
110
|
+
*
|
|
111
|
+
* Use this when you need to accept any valid error code.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* function logError(code: ErrorCode, message: string) {
|
|
116
|
+
* console.error(`[${code}] ${message}`);
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
type ErrorCode = DomainErrorCode | AppErrorCode | InfraErrorCode | PresentationErrorCode | GlobalErrorCode;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Base error class for all application errors with a machine-readable code.
|
|
124
|
+
*
|
|
125
|
+
* Abstract class that extends the native `Error` with:
|
|
126
|
+
* - A `code` property for programmatic error handling
|
|
127
|
+
* - Optional `cause` for error chaining (ES2022 compatible)
|
|
128
|
+
* - A `fromError` static factory pattern for error transformation
|
|
129
|
+
*
|
|
130
|
+
* **Why abstract:** Prevents non-declarative error usage. All errors must
|
|
131
|
+
* be explicitly defined as subclasses to ensure consistent error taxonomy.
|
|
132
|
+
*
|
|
133
|
+
* @example Subclass implementation
|
|
134
|
+
* ```typescript
|
|
135
|
+
* class DbError extends InfraError {
|
|
136
|
+
* static override fromError(cause: unknown): DbError {
|
|
137
|
+
* return new DbError({
|
|
138
|
+
* message: cause instanceof Error ? cause.message : 'Database error',
|
|
139
|
+
* cause,
|
|
140
|
+
* });
|
|
141
|
+
* }
|
|
142
|
+
* }
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example Usage with wrapErrorAsync
|
|
146
|
+
* ```typescript
|
|
147
|
+
* await wrapErrorAsync(
|
|
148
|
+
* () => this.db.query(...),
|
|
149
|
+
* DbError.fromError,
|
|
150
|
+
* );
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
declare abstract class CodedError extends Error {
|
|
154
|
+
/** Machine-readable error code for programmatic handling. */
|
|
155
|
+
readonly code: ErrorCode | string;
|
|
156
|
+
/**
|
|
157
|
+
* Creates a new CodedError instance.
|
|
158
|
+
*
|
|
159
|
+
* @param options - Error configuration
|
|
160
|
+
* @param options.message - Human-readable error message
|
|
161
|
+
* @param options.code - Machine-readable error code from ErrorCodes registry or custom string
|
|
162
|
+
* @param options.cause - Optional underlying error that caused this error
|
|
163
|
+
*/
|
|
164
|
+
constructor({ message, code, cause, }: {
|
|
165
|
+
message: string;
|
|
166
|
+
code: ErrorCode | string;
|
|
167
|
+
cause?: unknown;
|
|
168
|
+
});
|
|
169
|
+
/**
|
|
170
|
+
* Factory method to create a typed error from a caught error.
|
|
171
|
+
*
|
|
172
|
+
* Subclasses should override this to provide proper error transformation.
|
|
173
|
+
* Designed for use with {@link wrapErrorAsync} and {@link wrapError}.
|
|
174
|
+
*
|
|
175
|
+
* @param _cause - The original caught error
|
|
176
|
+
* @returns A new CodedError instance
|
|
177
|
+
* @throws {Error} If not overridden by subclass
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* class NotFoundError extends UseCaseError {
|
|
182
|
+
* static override fromError(cause: unknown): NotFoundError {
|
|
183
|
+
* return new NotFoundError({
|
|
184
|
+
* message: 'Resource not found',
|
|
185
|
+
* cause,
|
|
186
|
+
* });
|
|
187
|
+
* }
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
static fromError(_cause: unknown): CodedError;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface ValidationError {
|
|
195
|
+
field: string;
|
|
196
|
+
message: string;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export { type AppErrorCode as A, CodedError as C, type DomainErrorCode as D, ErrorCodes as E, type GlobalErrorCode as G, type InfraErrorCode as I, type PresentationErrorCode as P, type ValidationError as V, type ErrorCode as a };
|