@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.
Files changed (97) hide show
  1. package/dist/backend/core/global.cjs +283 -0
  2. package/dist/backend/core/global.cjs.map +1 -0
  3. package/dist/backend/core/global.d.cts +294 -0
  4. package/dist/backend/core/global.d.ts +294 -0
  5. package/dist/backend/core/global.js +39 -0
  6. package/dist/backend/core/global.js.map +1 -0
  7. package/dist/backend/core/onion-layers.cjs +2302 -0
  8. package/dist/backend/core/onion-layers.cjs.map +1 -0
  9. package/dist/backend/core/onion-layers.d.cts +1675 -0
  10. package/dist/backend/core/onion-layers.d.ts +1675 -0
  11. package/dist/backend/core/onion-layers.js +1158 -0
  12. package/dist/backend/core/onion-layers.js.map +1 -0
  13. package/dist/backend/core/presentation.cjs +573 -0
  14. package/dist/backend/core/presentation.cjs.map +1 -0
  15. package/dist/backend/core/presentation.d.cts +5 -0
  16. package/dist/backend/core/presentation.d.ts +5 -0
  17. package/dist/backend/core/presentation.js +28 -0
  18. package/dist/backend/core/presentation.js.map +1 -0
  19. package/dist/backend/core/validators/arktype.cjs +947 -0
  20. package/dist/backend/core/validators/arktype.cjs.map +1 -0
  21. package/dist/backend/core/validators/arktype.d.cts +188 -0
  22. package/dist/backend/core/validators/arktype.d.ts +188 -0
  23. package/dist/backend/core/validators/arktype.js +287 -0
  24. package/dist/backend/core/validators/arktype.js.map +1 -0
  25. package/dist/backend/core/validators/typebox.cjs +939 -0
  26. package/dist/backend/core/validators/typebox.cjs.map +1 -0
  27. package/dist/backend/core/validators/typebox.d.cts +189 -0
  28. package/dist/backend/core/validators/typebox.d.ts +189 -0
  29. package/dist/backend/core/validators/typebox.js +281 -0
  30. package/dist/backend/core/validators/typebox.js.map +1 -0
  31. package/dist/backend/core/validators/valibot.cjs +942 -0
  32. package/dist/backend/core/validators/valibot.cjs.map +1 -0
  33. package/dist/backend/core/validators/valibot.d.cts +160 -0
  34. package/dist/backend/core/validators/valibot.d.ts +160 -0
  35. package/dist/backend/core/validators/valibot.js +294 -0
  36. package/dist/backend/core/validators/valibot.js.map +1 -0
  37. package/dist/backend/core/validators/zod.cjs +934 -0
  38. package/dist/backend/core/validators/zod.cjs.map +1 -0
  39. package/dist/backend/core/validators/zod.d.cts +188 -0
  40. package/dist/backend/core/validators/zod.d.ts +188 -0
  41. package/dist/backend/core/validators/zod.js +278 -0
  42. package/dist/backend/core/validators/zod.js.map +1 -0
  43. package/dist/backend/frameworks/elysia.cjs +715 -0
  44. package/dist/backend/frameworks/elysia.cjs.map +1 -0
  45. package/dist/backend/frameworks/elysia.d.cts +208 -0
  46. package/dist/backend/frameworks/elysia.d.ts +208 -0
  47. package/dist/backend/frameworks/elysia.js +251 -0
  48. package/dist/backend/frameworks/elysia.js.map +1 -0
  49. package/dist/backend/frameworks/fastify.cjs +677 -0
  50. package/dist/backend/frameworks/fastify.cjs.map +1 -0
  51. package/dist/backend/frameworks/fastify.d.cts +201 -0
  52. package/dist/backend/frameworks/fastify.d.ts +201 -0
  53. package/dist/backend/frameworks/fastify.js +213 -0
  54. package/dist/backend/frameworks/fastify.js.map +1 -0
  55. package/dist/backend/frameworks/hono.cjs +715 -0
  56. package/dist/backend/frameworks/hono.cjs.map +1 -0
  57. package/dist/backend/frameworks/hono.d.cts +163 -0
  58. package/dist/backend/frameworks/hono.d.ts +163 -0
  59. package/dist/backend/frameworks/hono.js +249 -0
  60. package/dist/backend/frameworks/hono.js.map +1 -0
  61. package/dist/backend/frameworks/nestjs.cjs +260 -0
  62. package/dist/backend/frameworks/nestjs.cjs.map +1 -0
  63. package/dist/backend/frameworks/nestjs.d.cts +168 -0
  64. package/dist/backend/frameworks/nestjs.d.ts +168 -0
  65. package/dist/backend/frameworks/nestjs.js +193 -0
  66. package/dist/backend/frameworks/nestjs.js.map +1 -0
  67. package/dist/base-dto.class-D7W9iqoU.d.cts +146 -0
  68. package/dist/base-dto.class-D7W9iqoU.d.ts +146 -0
  69. package/dist/base-uuid-v7.vo-BPGEIWLM.d.ts +799 -0
  70. package/dist/base-uuid-v7.vo-BjqKX44G.d.cts +799 -0
  71. package/dist/chunk-74IKUOSE.js +116 -0
  72. package/dist/chunk-74IKUOSE.js.map +1 -0
  73. package/dist/chunk-BKZOLGQW.js +29 -0
  74. package/dist/chunk-BKZOLGQW.js.map +1 -0
  75. package/dist/chunk-CGZBV6BD.js +54 -0
  76. package/dist/chunk-CGZBV6BD.js.map +1 -0
  77. package/dist/chunk-DDAHJZVK.js +258 -0
  78. package/dist/chunk-DDAHJZVK.js.map +1 -0
  79. package/dist/chunk-MQD5GXMT.js +171 -0
  80. package/dist/chunk-MQD5GXMT.js.map +1 -0
  81. package/dist/chunk-OKFXZHBC.js +43 -0
  82. package/dist/chunk-OKFXZHBC.js.map +1 -0
  83. package/dist/chunk-RLLWYFPI.js +168 -0
  84. package/dist/chunk-RLLWYFPI.js.map +1 -0
  85. package/dist/chunk-VCHFXT5W.js +425 -0
  86. package/dist/chunk-VCHFXT5W.js.map +1 -0
  87. package/dist/chunk-ZWLYNGO3.js +40 -0
  88. package/dist/chunk-ZWLYNGO3.js.map +1 -0
  89. package/dist/http-response-BAhi8lF4.d.cts +124 -0
  90. package/dist/http-response-BAhi8lF4.d.ts +124 -0
  91. package/dist/index-DingXh7B.d.cts +1187 -0
  92. package/dist/index-tOH7XBa3.d.ts +1187 -0
  93. package/dist/routing.type-DB4pt-d9.d.ts +184 -0
  94. package/dist/routing.type-DF2BIL7x.d.cts +184 -0
  95. package/dist/validation-error.type-kD4_qNZ9.d.cts +199 -0
  96. package/dist/validation-error.type-kD4_qNZ9.d.ts +199 -0
  97. package/package.json +191 -0
@@ -0,0 +1,168 @@
1
+ import { ExceptionFilter, ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
2
+ import { Observable } from 'rxjs';
3
+ export { C as HttpController, H as HttpRequest, a as HttpResponse } from '../../http-response-BAhi8lF4.cjs';
4
+
5
+ /**
6
+ * Base controller for NestJS that auto-wires onion-lasagna integration.
7
+ *
8
+ * Extending this class automatically applies:
9
+ * - {@link OnionLasagnaExceptionFilter} - Maps domain errors to HTTP responses
10
+ * - {@link OnionLasagnaResponseInterceptor} - Transforms HttpResponse to NestJS response
11
+ *
12
+ * This reduces boilerplate when creating controllers that work with
13
+ * onion-lasagna's architecture.
14
+ *
15
+ * @example Basic usage
16
+ * ```typescript
17
+ * import { Controller, Get, Post } from '@nestjs/common';
18
+ * import { BaseNestController, OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
19
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/core/presentation';
20
+ *
21
+ * @Controller('users')
22
+ * export class UsersController extends BaseNestController {
23
+ * constructor(
24
+ * private readonly getUserController: GetUserController,
25
+ * private readonly createUserController: CreateUserController,
26
+ * ) {
27
+ * super();
28
+ * }
29
+ *
30
+ * @Get(':id')
31
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
32
+ * return this.getUserController.execute(request);
33
+ * }
34
+ *
35
+ * @Post()
36
+ * createUser(@OnionLasagnaRequest() request: HttpRequest) {
37
+ * return this.createUserController.execute(request);
38
+ * }
39
+ * }
40
+ * ```
41
+ *
42
+ * @example With NestJS guards
43
+ * ```typescript
44
+ * @Controller('admin')
45
+ * @UseGuards(JwtAuthGuard, RolesGuard)
46
+ * export class AdminController extends BaseNestController {
47
+ * @Get('dashboard')
48
+ * @Roles('admin')
49
+ * getDashboard(@OnionLasagnaRequest() request: HttpRequest) {
50
+ * return this.dashboardController.execute(request);
51
+ * }
52
+ * }
53
+ * ```
54
+ */
55
+ declare abstract class BaseNestController {
56
+ }
57
+
58
+ /**
59
+ * Parameter decorator that extracts the request from NestJS context
60
+ * and transforms it into onion-lasagna's `HttpRequest` format.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { Controller, Get } from '@nestjs/common';
65
+ * import { OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
66
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
67
+ *
68
+ * @Controller('users')
69
+ * export class UsersController {
70
+ * @Get(':id')
71
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
72
+ * return getUserController.execute(request);
73
+ * }
74
+ * }
75
+ * ```
76
+ */
77
+ declare const OnionLasagnaRequest: (...dataOrPipes: unknown[]) => ParameterDecorator;
78
+
79
+ /**
80
+ * NestJS exception filter that maps onion-lasagna errors to HTTP responses.
81
+ *
82
+ * Mapping strategy:
83
+ * - `ObjectValidationError` → 400 Bad Request
84
+ * - `InvalidRequestError` → 400 Bad Request
85
+ * - `AccessDeniedError` → 403 Forbidden
86
+ * - `NotFoundError` → 404 Not Found
87
+ * - `ConflictError` → 409 Conflict
88
+ * - `UnprocessableError` → 422 Unprocessable Entity
89
+ * - `UseCaseError` (other) → 400 Bad Request
90
+ * - `DomainError` → 500 Internal Server Error (masked)
91
+ * - `InfraError` → 500 Internal Server Error (masked)
92
+ * - `ControllerError` → 500 Internal Server Error (masked)
93
+ * - Unknown → 500 Internal Server Error (masked)
94
+ *
95
+ * **Security Note:** Domain and infrastructure errors are masked to avoid
96
+ * leaking internal implementation details.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * import { Controller, UseFilters } from '@nestjs/common';
101
+ * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
102
+ *
103
+ * @Controller('users')
104
+ * @UseFilters(OnionLasagnaExceptionFilter)
105
+ * export class UsersController {
106
+ * // ...
107
+ * }
108
+ * ```
109
+ *
110
+ * @example Global registration in main.ts
111
+ * ```typescript
112
+ * import { NestFactory } from '@nestjs/core';
113
+ * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
114
+ *
115
+ * const app = await NestFactory.create(AppModule);
116
+ * app.useGlobalFilters(new OnionLasagnaExceptionFilter());
117
+ * ```
118
+ */
119
+ declare class OnionLasagnaExceptionFilter implements ExceptionFilter {
120
+ catch(exception: unknown, host: ArgumentsHost): void;
121
+ private mapError;
122
+ }
123
+
124
+ /**
125
+ * NestJS interceptor that transforms onion-lasagna `HttpResponse` objects
126
+ * into proper NestJS responses.
127
+ *
128
+ * When a controller returns an `HttpResponse` object (with `statusCode`, `body`, and optional `headers`),
129
+ * this interceptor:
130
+ * 1. Sets the HTTP status code from `response.statusCode`
131
+ * 2. Sets any custom headers from `response.headers`
132
+ * 3. Returns only `response.body` to NestJS for serialization
133
+ *
134
+ * If the response is not an `HttpResponse` object, it passes through unchanged.
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { Controller, Get, UseInterceptors, UseFilters } from '@nestjs/common';
139
+ * import { OnionLasagnaRequest, OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
140
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
141
+ *
142
+ * @Controller('users')
143
+ * @UseFilters(OnionLasagnaExceptionFilter)
144
+ * @UseInterceptors(OnionLasagnaResponseInterceptor)
145
+ * export class UsersController {
146
+ * @Get(':id')
147
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
148
+ * return getUserController.execute(request);
149
+ * }
150
+ * }
151
+ * ```
152
+ *
153
+ * @example Global registration in main.ts
154
+ * ```typescript
155
+ * import { NestFactory } from '@nestjs/core';
156
+ * import { OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
157
+ *
158
+ * const app = await NestFactory.create(AppModule);
159
+ * app.useGlobalFilters(new OnionLasagnaExceptionFilter());
160
+ * app.useGlobalInterceptors(new OnionLasagnaResponseInterceptor());
161
+ * await app.listen(3000);
162
+ * ```
163
+ */
164
+ declare class OnionLasagnaResponseInterceptor implements NestInterceptor {
165
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
166
+ }
167
+
168
+ export { BaseNestController, OnionLasagnaExceptionFilter, OnionLasagnaRequest, OnionLasagnaResponseInterceptor };
@@ -0,0 +1,168 @@
1
+ import { ExceptionFilter, ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
2
+ import { Observable } from 'rxjs';
3
+ export { C as HttpController, H as HttpRequest, a as HttpResponse } from '../../http-response-BAhi8lF4.js';
4
+
5
+ /**
6
+ * Base controller for NestJS that auto-wires onion-lasagna integration.
7
+ *
8
+ * Extending this class automatically applies:
9
+ * - {@link OnionLasagnaExceptionFilter} - Maps domain errors to HTTP responses
10
+ * - {@link OnionLasagnaResponseInterceptor} - Transforms HttpResponse to NestJS response
11
+ *
12
+ * This reduces boilerplate when creating controllers that work with
13
+ * onion-lasagna's architecture.
14
+ *
15
+ * @example Basic usage
16
+ * ```typescript
17
+ * import { Controller, Get, Post } from '@nestjs/common';
18
+ * import { BaseNestController, OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
19
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/core/presentation';
20
+ *
21
+ * @Controller('users')
22
+ * export class UsersController extends BaseNestController {
23
+ * constructor(
24
+ * private readonly getUserController: GetUserController,
25
+ * private readonly createUserController: CreateUserController,
26
+ * ) {
27
+ * super();
28
+ * }
29
+ *
30
+ * @Get(':id')
31
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
32
+ * return this.getUserController.execute(request);
33
+ * }
34
+ *
35
+ * @Post()
36
+ * createUser(@OnionLasagnaRequest() request: HttpRequest) {
37
+ * return this.createUserController.execute(request);
38
+ * }
39
+ * }
40
+ * ```
41
+ *
42
+ * @example With NestJS guards
43
+ * ```typescript
44
+ * @Controller('admin')
45
+ * @UseGuards(JwtAuthGuard, RolesGuard)
46
+ * export class AdminController extends BaseNestController {
47
+ * @Get('dashboard')
48
+ * @Roles('admin')
49
+ * getDashboard(@OnionLasagnaRequest() request: HttpRequest) {
50
+ * return this.dashboardController.execute(request);
51
+ * }
52
+ * }
53
+ * ```
54
+ */
55
+ declare abstract class BaseNestController {
56
+ }
57
+
58
+ /**
59
+ * Parameter decorator that extracts the request from NestJS context
60
+ * and transforms it into onion-lasagna's `HttpRequest` format.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { Controller, Get } from '@nestjs/common';
65
+ * import { OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
66
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
67
+ *
68
+ * @Controller('users')
69
+ * export class UsersController {
70
+ * @Get(':id')
71
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
72
+ * return getUserController.execute(request);
73
+ * }
74
+ * }
75
+ * ```
76
+ */
77
+ declare const OnionLasagnaRequest: (...dataOrPipes: unknown[]) => ParameterDecorator;
78
+
79
+ /**
80
+ * NestJS exception filter that maps onion-lasagna errors to HTTP responses.
81
+ *
82
+ * Mapping strategy:
83
+ * - `ObjectValidationError` → 400 Bad Request
84
+ * - `InvalidRequestError` → 400 Bad Request
85
+ * - `AccessDeniedError` → 403 Forbidden
86
+ * - `NotFoundError` → 404 Not Found
87
+ * - `ConflictError` → 409 Conflict
88
+ * - `UnprocessableError` → 422 Unprocessable Entity
89
+ * - `UseCaseError` (other) → 400 Bad Request
90
+ * - `DomainError` → 500 Internal Server Error (masked)
91
+ * - `InfraError` → 500 Internal Server Error (masked)
92
+ * - `ControllerError` → 500 Internal Server Error (masked)
93
+ * - Unknown → 500 Internal Server Error (masked)
94
+ *
95
+ * **Security Note:** Domain and infrastructure errors are masked to avoid
96
+ * leaking internal implementation details.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * import { Controller, UseFilters } from '@nestjs/common';
101
+ * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
102
+ *
103
+ * @Controller('users')
104
+ * @UseFilters(OnionLasagnaExceptionFilter)
105
+ * export class UsersController {
106
+ * // ...
107
+ * }
108
+ * ```
109
+ *
110
+ * @example Global registration in main.ts
111
+ * ```typescript
112
+ * import { NestFactory } from '@nestjs/core';
113
+ * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
114
+ *
115
+ * const app = await NestFactory.create(AppModule);
116
+ * app.useGlobalFilters(new OnionLasagnaExceptionFilter());
117
+ * ```
118
+ */
119
+ declare class OnionLasagnaExceptionFilter implements ExceptionFilter {
120
+ catch(exception: unknown, host: ArgumentsHost): void;
121
+ private mapError;
122
+ }
123
+
124
+ /**
125
+ * NestJS interceptor that transforms onion-lasagna `HttpResponse` objects
126
+ * into proper NestJS responses.
127
+ *
128
+ * When a controller returns an `HttpResponse` object (with `statusCode`, `body`, and optional `headers`),
129
+ * this interceptor:
130
+ * 1. Sets the HTTP status code from `response.statusCode`
131
+ * 2. Sets any custom headers from `response.headers`
132
+ * 3. Returns only `response.body` to NestJS for serialization
133
+ *
134
+ * If the response is not an `HttpResponse` object, it passes through unchanged.
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { Controller, Get, UseInterceptors, UseFilters } from '@nestjs/common';
139
+ * import { OnionLasagnaRequest, OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
140
+ * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
141
+ *
142
+ * @Controller('users')
143
+ * @UseFilters(OnionLasagnaExceptionFilter)
144
+ * @UseInterceptors(OnionLasagnaResponseInterceptor)
145
+ * export class UsersController {
146
+ * @Get(':id')
147
+ * getUser(@OnionLasagnaRequest() request: HttpRequest) {
148
+ * return getUserController.execute(request);
149
+ * }
150
+ * }
151
+ * ```
152
+ *
153
+ * @example Global registration in main.ts
154
+ * ```typescript
155
+ * import { NestFactory } from '@nestjs/core';
156
+ * import { OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';
157
+ *
158
+ * const app = await NestFactory.create(AppModule);
159
+ * app.useGlobalFilters(new OnionLasagnaExceptionFilter());
160
+ * app.useGlobalInterceptors(new OnionLasagnaResponseInterceptor());
161
+ * await app.listen(3000);
162
+ * ```
163
+ */
164
+ declare class OnionLasagnaResponseInterceptor implements NestInterceptor {
165
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
166
+ }
167
+
168
+ export { BaseNestController, OnionLasagnaExceptionFilter, OnionLasagnaRequest, OnionLasagnaResponseInterceptor };
@@ -0,0 +1,193 @@
1
+ import {
2
+ __decorateElement,
3
+ __decoratorStart,
4
+ __runInitializers
5
+ } from "../../chunk-CGZBV6BD.js";
6
+
7
+ // src/backend/frameworks/nestjs/classes/base-nest-controller.class.ts
8
+ import { UseFilters, UseInterceptors } from "@nestjs/common";
9
+
10
+ // src/backend/frameworks/nestjs/filters/onion-lasagna-exception.filter.ts
11
+ import { Catch, HttpStatus } from "@nestjs/common";
12
+ function isErrorType(error, typeName) {
13
+ if (!error || typeof error !== "object") return false;
14
+ const constructor = error.constructor;
15
+ const name = constructor?.name;
16
+ return name === typeName || name === `_${typeName}`;
17
+ }
18
+ function hasValidationErrors(error) {
19
+ if (!error || typeof error !== "object") return false;
20
+ return "validationErrors" in error && Array.isArray(error.validationErrors);
21
+ }
22
+ var INTERNAL_ERROR_TYPES = [
23
+ "DomainError",
24
+ "InfraError",
25
+ "ControllerError",
26
+ "NetworkError",
27
+ "PersistenceError",
28
+ "ExternalServiceError",
29
+ "InvariantViolationError"
30
+ ];
31
+ var _OnionLasagnaExceptionFilter_decorators, _init;
32
+ _OnionLasagnaExceptionFilter_decorators = [Catch()];
33
+ var OnionLasagnaExceptionFilter = class {
34
+ catch(exception, host) {
35
+ const ctx = host.switchToHttp();
36
+ const response = ctx.getResponse();
37
+ const { status, body } = this.mapError(exception);
38
+ response.status(status).json(body);
39
+ }
40
+ mapError(error) {
41
+ if (isErrorType(error, "ObjectValidationError") && hasValidationErrors(error)) {
42
+ return {
43
+ status: HttpStatus.BAD_REQUEST,
44
+ body: {
45
+ message: error.message,
46
+ errorCode: error.code,
47
+ errorItems: error.validationErrors.map((e) => ({
48
+ item: e.field,
49
+ message: e.message
50
+ }))
51
+ }
52
+ };
53
+ }
54
+ if (isErrorType(error, "InvalidRequestError") && hasValidationErrors(error)) {
55
+ return {
56
+ status: HttpStatus.BAD_REQUEST,
57
+ body: {
58
+ message: error.message,
59
+ errorCode: error.code,
60
+ errorItems: error.validationErrors.map((e) => ({
61
+ item: e.field,
62
+ message: e.message
63
+ }))
64
+ }
65
+ };
66
+ }
67
+ if (isErrorType(error, "AccessDeniedError")) {
68
+ return {
69
+ status: HttpStatus.FORBIDDEN,
70
+ body: { message: error.message, errorCode: error.code }
71
+ };
72
+ }
73
+ if (isErrorType(error, "NotFoundError")) {
74
+ return {
75
+ status: HttpStatus.NOT_FOUND,
76
+ body: { message: error.message, errorCode: error.code }
77
+ };
78
+ }
79
+ if (isErrorType(error, "ConflictError")) {
80
+ return {
81
+ status: HttpStatus.CONFLICT,
82
+ body: { message: error.message, errorCode: error.code }
83
+ };
84
+ }
85
+ if (isErrorType(error, "UnprocessableError")) {
86
+ return {
87
+ status: HttpStatus.UNPROCESSABLE_ENTITY,
88
+ body: { message: error.message, errorCode: error.code }
89
+ };
90
+ }
91
+ if (isErrorType(error, "UseCaseError")) {
92
+ return {
93
+ status: HttpStatus.BAD_REQUEST,
94
+ body: { message: error.message, errorCode: error.code }
95
+ };
96
+ }
97
+ for (const errorType of INTERNAL_ERROR_TYPES) {
98
+ if (isErrorType(error, errorType)) {
99
+ return {
100
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
101
+ body: { message: "An unexpected error occurred", errorCode: "INTERNAL_ERROR" }
102
+ };
103
+ }
104
+ }
105
+ if (isErrorType(error, "CodedError")) {
106
+ return {
107
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
108
+ body: { message: "An unexpected error occurred", errorCode: "INTERNAL_ERROR" }
109
+ };
110
+ }
111
+ return {
112
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
113
+ body: { message: "An unexpected error occurred", errorCode: "INTERNAL_ERROR" }
114
+ };
115
+ }
116
+ };
117
+ _init = __decoratorStart(null);
118
+ OnionLasagnaExceptionFilter = __decorateElement(_init, 0, "OnionLasagnaExceptionFilter", _OnionLasagnaExceptionFilter_decorators, OnionLasagnaExceptionFilter);
119
+ __runInitializers(_init, 1, OnionLasagnaExceptionFilter);
120
+
121
+ // src/backend/frameworks/nestjs/interceptors/onion-lasagna-response.interceptor.ts
122
+ import {
123
+ Injectable
124
+ } from "@nestjs/common";
125
+ import { map } from "rxjs/operators";
126
+ function isHttpResponse(value) {
127
+ if (!value || typeof value !== "object") return false;
128
+ const obj = value;
129
+ return typeof obj.statusCode === "number" && "body" in obj;
130
+ }
131
+ var _OnionLasagnaResponseInterceptor_decorators, _init2;
132
+ _OnionLasagnaResponseInterceptor_decorators = [Injectable()];
133
+ var OnionLasagnaResponseInterceptor = class {
134
+ intercept(context, next) {
135
+ return next.handle().pipe(
136
+ map((data) => {
137
+ if (!isHttpResponse(data)) {
138
+ return data;
139
+ }
140
+ const res = context.switchToHttp().getResponse();
141
+ res.status(data.statusCode);
142
+ if (data.headers) {
143
+ for (const [key, value] of Object.entries(data.headers)) {
144
+ if (value != null) {
145
+ res.setHeader(key, String(value));
146
+ }
147
+ }
148
+ }
149
+ return data.body;
150
+ })
151
+ );
152
+ }
153
+ };
154
+ _init2 = __decoratorStart(null);
155
+ OnionLasagnaResponseInterceptor = __decorateElement(_init2, 0, "OnionLasagnaResponseInterceptor", _OnionLasagnaResponseInterceptor_decorators, OnionLasagnaResponseInterceptor);
156
+ __runInitializers(_init2, 1, OnionLasagnaResponseInterceptor);
157
+
158
+ // src/backend/frameworks/nestjs/classes/base-nest-controller.class.ts
159
+ var _BaseNestController_decorators, _init3;
160
+ _BaseNestController_decorators = [UseFilters(OnionLasagnaExceptionFilter), UseInterceptors(OnionLasagnaResponseInterceptor)];
161
+ var BaseNestController = class {
162
+ };
163
+ _init3 = __decoratorStart(null);
164
+ BaseNestController = __decorateElement(_init3, 0, "BaseNestController", _BaseNestController_decorators, BaseNestController);
165
+ __runInitializers(_init3, 1, BaseNestController);
166
+
167
+ // src/backend/frameworks/nestjs/decorators/onion-lasagna-request.decorator.ts
168
+ import { createParamDecorator } from "@nestjs/common";
169
+ function normalizeHeaders(headers) {
170
+ const normalized = {};
171
+ for (const [key, value] of Object.entries(headers)) {
172
+ normalized[key.toLowerCase()] = String(value);
173
+ }
174
+ return normalized;
175
+ }
176
+ var OnionLasagnaRequest = createParamDecorator(
177
+ (_data, ctx) => {
178
+ const request = ctx.switchToHttp().getRequest();
179
+ return {
180
+ body: request.body,
181
+ headers: normalizeHeaders(request.headers),
182
+ queryParams: request.query,
183
+ pathParams: request.params
184
+ };
185
+ }
186
+ );
187
+ export {
188
+ BaseNestController,
189
+ OnionLasagnaExceptionFilter,
190
+ OnionLasagnaRequest,
191
+ OnionLasagnaResponseInterceptor
192
+ };
193
+ //# sourceMappingURL=nestjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/backend/frameworks/nestjs/classes/base-nest-controller.class.ts","../../../src/backend/frameworks/nestjs/filters/onion-lasagna-exception.filter.ts","../../../src/backend/frameworks/nestjs/interceptors/onion-lasagna-response.interceptor.ts","../../../src/backend/frameworks/nestjs/decorators/onion-lasagna-request.decorator.ts"],"sourcesContent":["import { UseFilters, UseInterceptors } from '@nestjs/common';\nimport { OnionLasagnaExceptionFilter } from '../filters/onion-lasagna-exception.filter';\nimport { OnionLasagnaResponseInterceptor } from '../interceptors/onion-lasagna-response.interceptor';\n\n/**\n * Base controller for NestJS that auto-wires onion-lasagna integration.\n *\n * Extending this class automatically applies:\n * - {@link OnionLasagnaExceptionFilter} - Maps domain errors to HTTP responses\n * - {@link OnionLasagnaResponseInterceptor} - Transforms HttpResponse to NestJS response\n *\n * This reduces boilerplate when creating controllers that work with\n * onion-lasagna's architecture.\n *\n * @example Basic usage\n * ```typescript\n * import { Controller, Get, Post } from '@nestjs/common';\n * import { BaseNestController, OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/core/presentation';\n *\n * @Controller('users')\n * export class UsersController extends BaseNestController {\n * constructor(\n * private readonly getUserController: GetUserController,\n * private readonly createUserController: CreateUserController,\n * ) {\n * super();\n * }\n *\n * @Get(':id')\n * getUser(@OnionLasagnaRequest() request: HttpRequest) {\n * return this.getUserController.execute(request);\n * }\n *\n * @Post()\n * createUser(@OnionLasagnaRequest() request: HttpRequest) {\n * return this.createUserController.execute(request);\n * }\n * }\n * ```\n *\n * @example With NestJS guards\n * ```typescript\n * @Controller('admin')\n * @UseGuards(JwtAuthGuard, RolesGuard)\n * export class AdminController extends BaseNestController {\n * @Get('dashboard')\n * @Roles('admin')\n * getDashboard(@OnionLasagnaRequest() request: HttpRequest) {\n * return this.dashboardController.execute(request);\n * }\n * }\n * ```\n */\n@UseFilters(OnionLasagnaExceptionFilter)\n@UseInterceptors(OnionLasagnaResponseInterceptor)\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class -- Abstract base with decorator inheritance only\nexport abstract class BaseNestController {}\n","import { Catch, HttpStatus, type ExceptionFilter, type ArgumentsHost } from '@nestjs/common';\nimport type { Response } from 'express';\n\n/**\n * Error item for field-level validation errors.\n */\ninterface ErrorItem {\n item: string;\n message: string;\n}\n\n/**\n * Standard error response body.\n */\ninterface ErrorResponseBody {\n message: string;\n errorCode: string;\n errorItems?: ErrorItem[];\n}\n\n/**\n * Validation error structure.\n */\ninterface ValidationErrorItem {\n field: string;\n message: string;\n}\n\n/**\n * Interface for errors with validation items.\n */\ninterface ErrorWithValidation {\n message: string;\n code: string;\n validationErrors: ValidationErrorItem[];\n}\n\n/**\n * Interface for coded errors.\n */\ninterface CodedErrorLike {\n message: string;\n code: string;\n}\n\n/**\n * Checks if error matches a specific error type by checking its constructor name.\n * This approach avoids issues with multiple class instances in bundled code.\n * Handles both original names and tsup's mangled names (prefixed with _).\n */\nfunction isErrorType(error: unknown, typeName: string): error is CodedErrorLike {\n if (!error || typeof error !== 'object') return false;\n const constructor = (error as object).constructor;\n const name = constructor?.name;\n // Check both the original name and the mangled name (tsup prefixes with _)\n return name === typeName || name === `_${typeName}`;\n}\n\n/**\n * Checks if error has validation errors array.\n */\nfunction hasValidationErrors(error: unknown): error is ErrorWithValidation {\n if (!error || typeof error !== 'object') return false;\n return (\n 'validationErrors' in error && Array.isArray((error as ErrorWithValidation).validationErrors)\n );\n}\n\n/**\n * Known internal error type names that should be masked.\n */\nconst INTERNAL_ERROR_TYPES = [\n 'DomainError',\n 'InfraError',\n 'ControllerError',\n 'NetworkError',\n 'PersistenceError',\n 'ExternalServiceError',\n 'InvariantViolationError',\n];\n\n/**\n * NestJS exception filter that maps onion-lasagna errors to HTTP responses.\n *\n * Mapping strategy:\n * - `ObjectValidationError` → 400 Bad Request\n * - `InvalidRequestError` → 400 Bad Request\n * - `AccessDeniedError` → 403 Forbidden\n * - `NotFoundError` → 404 Not Found\n * - `ConflictError` → 409 Conflict\n * - `UnprocessableError` → 422 Unprocessable Entity\n * - `UseCaseError` (other) → 400 Bad Request\n * - `DomainError` → 500 Internal Server Error (masked)\n * - `InfraError` → 500 Internal Server Error (masked)\n * - `ControllerError` → 500 Internal Server Error (masked)\n * - Unknown → 500 Internal Server Error (masked)\n *\n * **Security Note:** Domain and infrastructure errors are masked to avoid\n * leaking internal implementation details.\n *\n * @example\n * ```typescript\n * import { Controller, UseFilters } from '@nestjs/common';\n * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n *\n * @Controller('users')\n * @UseFilters(OnionLasagnaExceptionFilter)\n * export class UsersController {\n * // ...\n * }\n * ```\n *\n * @example Global registration in main.ts\n * ```typescript\n * import { NestFactory } from '@nestjs/core';\n * import { OnionLasagnaExceptionFilter } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n *\n * const app = await NestFactory.create(AppModule);\n * app.useGlobalFilters(new OnionLasagnaExceptionFilter());\n * ```\n */\n@Catch()\nexport class OnionLasagnaExceptionFilter implements ExceptionFilter {\n catch(exception: unknown, host: ArgumentsHost) {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<Response>();\n\n const { status, body } = this.mapError(exception);\n response.status(status).json(body);\n }\n\n private mapError(error: unknown): { status: number; body: ErrorResponseBody } {\n // Validation errors → 400 Bad Request\n if (isErrorType(error, 'ObjectValidationError') && hasValidationErrors(error)) {\n return {\n status: HttpStatus.BAD_REQUEST,\n body: {\n message: error.message,\n errorCode: error.code,\n errorItems: error.validationErrors.map((e) => ({\n item: e.field,\n message: e.message,\n })),\n },\n };\n }\n\n if (isErrorType(error, 'InvalidRequestError') && hasValidationErrors(error)) {\n return {\n status: HttpStatus.BAD_REQUEST,\n body: {\n message: error.message,\n errorCode: error.code,\n errorItems: error.validationErrors.map((e) => ({\n item: e.field,\n message: e.message,\n })),\n },\n };\n }\n\n // Access control → 403 Forbidden\n if (isErrorType(error, 'AccessDeniedError')) {\n return {\n status: HttpStatus.FORBIDDEN,\n body: { message: error.message, errorCode: error.code },\n };\n }\n\n // Use case errors → specific HTTP status codes\n if (isErrorType(error, 'NotFoundError')) {\n return {\n status: HttpStatus.NOT_FOUND,\n body: { message: error.message, errorCode: error.code },\n };\n }\n\n if (isErrorType(error, 'ConflictError')) {\n return {\n status: HttpStatus.CONFLICT,\n body: { message: error.message, errorCode: error.code },\n };\n }\n\n if (isErrorType(error, 'UnprocessableError')) {\n return {\n status: HttpStatus.UNPROCESSABLE_ENTITY,\n body: { message: error.message, errorCode: error.code },\n };\n }\n\n // Other use case errors → 400 Bad Request\n if (isErrorType(error, 'UseCaseError')) {\n return {\n status: HttpStatus.BAD_REQUEST,\n body: { message: error.message, errorCode: error.code },\n };\n }\n\n // Internal errors → 500 (masked)\n for (const errorType of INTERNAL_ERROR_TYPES) {\n if (isErrorType(error, errorType)) {\n return {\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n body: { message: 'An unexpected error occurred', errorCode: 'INTERNAL_ERROR' },\n };\n }\n }\n\n // CodedError (catch-all for known errors) → 500 (masked)\n if (isErrorType(error, 'CodedError')) {\n return {\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n body: { message: 'An unexpected error occurred', errorCode: 'INTERNAL_ERROR' },\n };\n }\n\n // Unknown errors → 500 Internal Server Error (masked)\n return {\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n body: { message: 'An unexpected error occurred', errorCode: 'INTERNAL_ERROR' },\n };\n }\n}\n","import {\n Injectable,\n type NestInterceptor,\n type ExecutionContext,\n type CallHandler,\n} from '@nestjs/common';\nimport type { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport type { Response } from 'express';\n\n/**\n * Interface matching onion-lasagna's HttpResponse type.\n */\ninterface HttpResponseLike {\n statusCode: number;\n body: unknown;\n headers?: Record<string, string | number | boolean | undefined>;\n}\n\n/**\n * Type guard to check if a value is an HttpResponse-like object.\n */\nfunction isHttpResponse(value: unknown): value is HttpResponseLike {\n if (!value || typeof value !== 'object') return false;\n const obj = value as HttpResponseLike;\n return typeof obj.statusCode === 'number' && 'body' in obj;\n}\n\n/**\n * NestJS interceptor that transforms onion-lasagna `HttpResponse` objects\n * into proper NestJS responses.\n *\n * When a controller returns an `HttpResponse` object (with `statusCode`, `body`, and optional `headers`),\n * this interceptor:\n * 1. Sets the HTTP status code from `response.statusCode`\n * 2. Sets any custom headers from `response.headers`\n * 3. Returns only `response.body` to NestJS for serialization\n *\n * If the response is not an `HttpResponse` object, it passes through unchanged.\n *\n * @example\n * ```typescript\n * import { Controller, Get, UseInterceptors, UseFilters } from '@nestjs/common';\n * import { OnionLasagnaRequest, OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n *\n * @Controller('users')\n * @UseFilters(OnionLasagnaExceptionFilter)\n * @UseInterceptors(OnionLasagnaResponseInterceptor)\n * export class UsersController {\n * @Get(':id')\n * getUser(@OnionLasagnaRequest() request: HttpRequest) {\n * return getUserController.execute(request);\n * }\n * }\n * ```\n *\n * @example Global registration in main.ts\n * ```typescript\n * import { NestFactory } from '@nestjs/core';\n * import { OnionLasagnaExceptionFilter, OnionLasagnaResponseInterceptor } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n *\n * const app = await NestFactory.create(AppModule);\n * app.useGlobalFilters(new OnionLasagnaExceptionFilter());\n * app.useGlobalInterceptors(new OnionLasagnaResponseInterceptor());\n * await app.listen(3000);\n * ```\n */\n@Injectable()\nexport class OnionLasagnaResponseInterceptor implements NestInterceptor {\n intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {\n return next.handle().pipe(\n map((data: unknown) => {\n // If not an HttpResponse, pass through unchanged\n if (!isHttpResponse(data)) {\n return data;\n }\n\n const res = context.switchToHttp().getResponse<Response>();\n\n // Set status code\n res.status(data.statusCode);\n\n // Set custom headers\n if (data.headers) {\n for (const [key, value] of Object.entries(data.headers)) {\n if (value != null) {\n res.setHeader(key, String(value));\n }\n }\n }\n\n // Return only the body for NestJS serialization\n return data.body;\n }),\n );\n }\n}\n","import { createParamDecorator, type ExecutionContext } from '@nestjs/common';\nimport type { HttpRequest } from '../../../core/onion-layers/presentation/interfaces/types/http/http-request';\n\n/**\n * Normalizes HTTP headers to lowercase keys with string values.\n */\nfunction normalizeHeaders(headers: Record<string, unknown>): Record<string, string> {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n normalized[key.toLowerCase()] = String(value);\n }\n return normalized;\n}\n\n/**\n * Parameter decorator that extracts the request from NestJS context\n * and transforms it into onion-lasagna's `HttpRequest` format.\n *\n * @example\n * ```typescript\n * import { Controller, Get } from '@nestjs/common';\n * import { OnionLasagnaRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n * import type { HttpRequest } from '@cosmneo/onion-lasagna/backend/frameworks/nestjs';\n *\n * @Controller('users')\n * export class UsersController {\n * @Get(':id')\n * getUser(@OnionLasagnaRequest() request: HttpRequest) {\n * return getUserController.execute(request);\n * }\n * }\n * ```\n */\nexport const OnionLasagnaRequest = createParamDecorator(\n (_data: unknown, ctx: ExecutionContext): HttpRequest => {\n const request = ctx.switchToHttp().getRequest();\n\n return {\n body: request.body,\n headers: normalizeHeaders(request.headers),\n queryParams: request.query,\n pathParams: request.params,\n };\n },\n);\n"],"mappings":"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","names":["_init","_init"]}