@cosmneo/onion-lasagna 0.2.0 → 0.2.1

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 (45) hide show
  1. package/dist/{chunk-GGSAAZPM.js → chunk-AUMHMWDD.js} +19 -20
  2. package/dist/chunk-AUMHMWDD.js.map +1 -0
  3. package/dist/chunk-H5TNDC5U.js +138 -0
  4. package/dist/chunk-H5TNDC5U.js.map +1 -0
  5. package/dist/chunk-MF2JDREK.js +168 -0
  6. package/dist/chunk-MF2JDREK.js.map +1 -0
  7. package/dist/{chunk-PUVAB3JX.js → chunk-XIRJ73IO.js} +38 -36
  8. package/dist/chunk-XIRJ73IO.js.map +1 -0
  9. package/dist/{chunk-DS7TE6KZ.js → chunk-XP6PLTV2.js} +11 -3
  10. package/dist/chunk-XP6PLTV2.js.map +1 -0
  11. package/dist/global.js +3 -3
  12. package/dist/http/index.cjs +563 -93
  13. package/dist/http/index.cjs.map +1 -1
  14. package/dist/http/index.d.cts +4 -3
  15. package/dist/http/index.d.ts +4 -3
  16. package/dist/http/index.js +30 -12
  17. package/dist/http/openapi/index.cjs +43 -35
  18. package/dist/http/openapi/index.cjs.map +1 -1
  19. package/dist/http/openapi/index.d.cts +8 -34
  20. package/dist/http/openapi/index.d.ts +8 -34
  21. package/dist/http/openapi/index.js +2 -2
  22. package/dist/http/route/index.cjs +106 -9
  23. package/dist/http/route/index.cjs.map +1 -1
  24. package/dist/http/route/index.d.cts +133 -227
  25. package/dist/http/route/index.d.ts +133 -227
  26. package/dist/http/route/index.js +5 -2
  27. package/dist/http/server/index.cjs +24 -19
  28. package/dist/http/server/index.cjs.map +1 -1
  29. package/dist/http/server/index.d.cts +1 -1
  30. package/dist/http/server/index.d.ts +1 -1
  31. package/dist/http/server/index.js +2 -2
  32. package/dist/http/shared/index.cjs.map +1 -1
  33. package/dist/http/shared/index.d.cts +10 -14
  34. package/dist/http/shared/index.d.ts +10 -14
  35. package/dist/http/shared/index.js +11 -127
  36. package/dist/http/shared/index.js.map +1 -1
  37. package/dist/index.js +6 -6
  38. package/dist/{router-definition.type-ynBhT16T.d.cts → router-definition.type-BElX-Pl4.d.cts} +169 -256
  39. package/dist/{router-definition.type-DORVlLNk.d.ts → router-definition.type-DxG8ncJZ.d.ts} +169 -256
  40. package/package.json +1 -1
  41. package/dist/chunk-BZULBF4N.js +0 -82
  42. package/dist/chunk-BZULBF4N.js.map +0 -1
  43. package/dist/chunk-DS7TE6KZ.js.map +0 -1
  44. package/dist/chunk-GGSAAZPM.js.map +0 -1
  45. package/dist/chunk-PUVAB3JX.js.map +0 -1
@@ -22,38 +22,114 @@ var http_exports = {};
22
22
  __export(http_exports, {
23
23
  buildPath: () => buildPath,
24
24
  collectRoutes: () => collectRoutes,
25
+ createErrorResponseBody: () => createErrorResponseBody,
25
26
  createPassthroughAdapter: () => createPassthroughAdapter,
26
27
  createRejectingAdapter: () => createRejectingAdapter,
27
28
  defineRoute: () => defineRoute,
28
29
  defineRouter: () => defineRouter,
29
30
  generateOpenAPI: () => generateOpenAPI,
31
+ generateOperationId: () => generateOperationId,
32
+ getHttpStatusCode: () => getHttpStatusCode,
30
33
  getPathParamNames: () => getPathParamNames,
31
34
  hasPathParams: () => hasPathParams,
35
+ hasValidationErrors: () => hasValidationErrors,
36
+ isErrorType: () => isErrorType,
32
37
  isRouteDefinition: () => isRouteDefinition,
33
38
  isRouterDefinition: () => isRouterDefinition,
34
39
  isSchemaAdapter: () => isSchemaAdapter,
35
40
  isValidationFailure: () => isValidationFailure,
36
41
  isValidationSuccess: () => isValidationSuccess,
42
+ mapErrorToHttpResponse: () => mapErrorToHttpResponse,
37
43
  mergeRouters: () => mergeRouters,
38
44
  normalizePath: () => normalizePath,
39
45
  pathToRegex: () => pathToRegex,
40
- serverRoutes: () => serverRoutes
46
+ serverRoutes: () => serverRoutes,
47
+ shouldMaskError: () => shouldMaskError
41
48
  });
42
49
  module.exports = __toCommonJS(http_exports);
43
50
 
51
+ // src/presentation/http/schema/types/validation.type.ts
52
+ function isValidationSuccess(result) {
53
+ return result.success === true;
54
+ }
55
+ function isValidationFailure(result) {
56
+ return result.success === false;
57
+ }
58
+
59
+ // src/presentation/http/schema/types/schema-adapter.type.ts
60
+ function isSchemaAdapter(value) {
61
+ return typeof value === "object" && value !== null && "validate" in value && typeof value.validate === "function" && "toJsonSchema" in value && typeof value.toJsonSchema === "function";
62
+ }
63
+ function createPassthroughAdapter() {
64
+ return {
65
+ validate: (data) => ({ success: true, data }),
66
+ toJsonSchema: () => ({}),
67
+ _output: void 0,
68
+ _input: void 0
69
+ };
70
+ }
71
+ function createRejectingAdapter(message) {
72
+ return {
73
+ validate: () => ({
74
+ success: false,
75
+ issues: [{ path: [], message }]
76
+ }),
77
+ toJsonSchema: () => ({ not: {} }),
78
+ _output: void 0,
79
+ _input: void 0
80
+ };
81
+ }
82
+
44
83
  // src/presentation/http/route/define-route.ts
84
+ function extractSchema(field) {
85
+ if (field == null) return void 0;
86
+ if (isSchemaAdapter(field)) return field;
87
+ return field.schema;
88
+ }
89
+ function extractMeta(field) {
90
+ if (field == null || isSchemaAdapter(field)) return void 0;
91
+ const config = field;
92
+ if (config.description == null && config.contentType == null && config.required == null) {
93
+ return void 0;
94
+ }
95
+ return {
96
+ description: config.description,
97
+ contentType: config.contentType,
98
+ required: config.required
99
+ };
100
+ }
101
+ function normalizeResponses(responses) {
102
+ const result = {};
103
+ for (const [key, value] of Object.entries(responses)) {
104
+ result[String(key)] = value;
105
+ }
106
+ return result;
107
+ }
45
108
  function defineRoute(input) {
109
+ const req = input.request;
110
+ const bodyMeta = extractMeta(req?.body);
111
+ const queryMeta = extractMeta(req?.query);
112
+ const paramsMeta = extractMeta(req?.params);
113
+ const headersMeta = extractMeta(req?.headers);
114
+ const contextMeta = extractMeta(req?.context);
115
+ const _meta = {
116
+ ...bodyMeta ? { body: bodyMeta } : {},
117
+ ...queryMeta ? { query: { description: queryMeta.description } } : {},
118
+ ...paramsMeta ? { params: { description: paramsMeta.description } } : {},
119
+ ...headersMeta ? { headers: { description: headersMeta.description } } : {},
120
+ ...contextMeta ? { context: { description: contextMeta.description } } : {}
121
+ };
46
122
  const definition = {
47
123
  method: input.method,
48
124
  path: input.path,
49
125
  request: {
50
- body: input.request?.body ?? void 0,
51
- query: input.request?.query ?? void 0,
52
- params: input.request?.params ?? void 0,
53
- headers: input.request?.headers ?? void 0,
54
- context: input.request?.context ?? void 0
126
+ body: extractSchema(req?.body) ?? void 0,
127
+ query: extractSchema(req?.query) ?? void 0,
128
+ params: extractSchema(req?.params) ?? void 0,
129
+ headers: extractSchema(req?.headers) ?? void 0,
130
+ context: extractSchema(req?.context) ?? void 0
55
131
  },
56
- responses: input.responses,
132
+ responses: input.responses ? normalizeResponses(input.responses) : void 0,
57
133
  docs: {
58
134
  summary: input.docs?.summary,
59
135
  description: input.docs?.description,
@@ -63,6 +139,7 @@ function defineRoute(input) {
63
139
  security: input.docs?.security,
64
140
  externalDocs: input.docs?.externalDocs
65
141
  },
142
+ _meta,
66
143
  _types: void 0
67
144
  };
68
145
  return Object.freeze(definition);
@@ -95,7 +172,7 @@ function normalizePath(path) {
95
172
 
96
173
  // src/presentation/http/route/types/router-definition.type.ts
97
174
  function isRouteDefinition(value) {
98
- return typeof value === "object" && value !== null && "method" in value && "path" in value && "responses" in value && "_types" in value;
175
+ return typeof value === "object" && value !== null && "method" in value && "path" in value && "_types" in value;
99
176
  }
100
177
  function isRouterDefinition(value) {
101
178
  return typeof value === "object" && value !== null && "_isRouter" in value && value._isRouter === true;
@@ -117,14 +194,59 @@ function collectRoutes(config, basePath = "") {
117
194
 
118
195
  // src/presentation/http/route/define-router.ts
119
196
  function defineRouter(routes, options) {
197
+ const defaults = options?.defaults;
198
+ const processedRoutes = defaults?.context || defaults?.tags ? applyRouterDefaults(routes, defaults) : routes;
120
199
  const definition = {
121
- routes,
200
+ routes: processedRoutes,
122
201
  basePath: options?.basePath,
123
- tags: options?.tags,
202
+ defaults,
124
203
  _isRouter: true
125
204
  };
126
205
  return deepFreeze(definition);
127
206
  }
207
+ function applyRouterDefaults(routes, defaults) {
208
+ const result = {};
209
+ for (const [key, value] of Object.entries(routes)) {
210
+ if (isRouteDefinition(value)) {
211
+ result[key] = applyDefaultsToRoute(value, defaults);
212
+ } else if (isRouterDefinition(value)) {
213
+ result[key] = {
214
+ ...value,
215
+ routes: applyRouterDefaults(value.routes, defaults)
216
+ };
217
+ } else if (typeof value === "object" && value !== null) {
218
+ result[key] = applyRouterDefaults(value, defaults);
219
+ }
220
+ }
221
+ return result;
222
+ }
223
+ function applyDefaultsToRoute(route, defaults) {
224
+ const needsContext = defaults.context && !route.request.context;
225
+ const needsTags = defaults.tags && defaults.tags.length > 0;
226
+ if (!needsContext && !needsTags) return route;
227
+ return Object.freeze({
228
+ ...route,
229
+ request: {
230
+ ...route.request,
231
+ context: route.request.context ?? defaults.context ?? void 0
232
+ },
233
+ docs: {
234
+ ...route.docs,
235
+ tags: mergeTags(defaults.tags, route.docs.tags)
236
+ }
237
+ });
238
+ }
239
+ function mergeTags(routerTags, routeTags) {
240
+ if (!routerTags || routerTags.length === 0) return routeTags;
241
+ if (!routeTags || routeTags.length === 0) return routerTags;
242
+ const merged = [...routerTags];
243
+ for (const tag of routeTags) {
244
+ if (!merged.includes(tag)) {
245
+ merged.push(tag);
246
+ }
247
+ }
248
+ return merged;
249
+ }
128
250
  function deepFreeze(obj) {
129
251
  const propNames = Object.getOwnPropertyNames(obj);
130
252
  for (const name of propNames) {
@@ -159,36 +281,11 @@ function mergeRouters(...routers) {
159
281
  return defineRouter(merged);
160
282
  }
161
283
 
162
- // src/presentation/http/schema/types/validation.type.ts
163
- function isValidationSuccess(result) {
164
- return result.success === true;
165
- }
166
- function isValidationFailure(result) {
167
- return result.success === false;
168
- }
169
-
170
- // src/presentation/http/schema/types/schema-adapter.type.ts
171
- function isSchemaAdapter(value) {
172
- return typeof value === "object" && value !== null && "validate" in value && typeof value.validate === "function" && "toJsonSchema" in value && typeof value.toJsonSchema === "function";
173
- }
174
- function createPassthroughAdapter() {
175
- return {
176
- validate: (data) => ({ success: true, data }),
177
- toJsonSchema: () => ({}),
178
- _output: void 0,
179
- _input: void 0
180
- };
181
- }
182
- function createRejectingAdapter(message) {
183
- return {
184
- validate: () => ({
185
- success: false,
186
- issues: [{ path: [], message }]
187
- }),
188
- toJsonSchema: () => ({ not: {} }),
189
- _output: void 0,
190
- _input: void 0
191
- };
284
+ // src/presentation/http/route/utils.ts
285
+ function generateOperationId(key) {
286
+ return key.split(".").map(
287
+ (segment, index) => index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1)
288
+ ).join("");
192
289
  }
193
290
 
194
291
  // src/presentation/http/server/types.ts
@@ -489,7 +586,7 @@ function createServerRoutesInternal(router, handlers, options) {
489
586
  `Missing handler for route "${key}". All routes must have a handler configuration.`
490
587
  );
491
588
  }
492
- result.push(createRouteHandler(route, handlerConfig, resolvedOptions));
589
+ result.push(createRouteHandler(key, route, handlerConfig, resolvedOptions));
493
590
  }
494
591
  return result;
495
592
  }
@@ -514,7 +611,7 @@ function sortRoutesBySpecificity(routes) {
514
611
  return 0;
515
612
  });
516
613
  }
517
- function createRouteHandler(route, config, options) {
614
+ function createRouteHandler(key, route, config, options) {
518
615
  const middleware = config.middleware ?? [];
519
616
  const globalMiddleware = options?.middleware ?? [];
520
617
  const allMiddleware = [...globalMiddleware, ...middleware];
@@ -524,7 +621,7 @@ function createRouteHandler(route, config, options) {
524
621
  method: route.method,
525
622
  path: normalizePath(route.path),
526
623
  metadata: {
527
- operationId: route.docs.operationId,
624
+ operationId: route.docs.operationId ?? generateOperationId(key),
528
625
  summary: route.docs.summary,
529
626
  description: route.docs.description,
530
627
  tags: route.docs.tags,
@@ -532,7 +629,7 @@ function createRouteHandler(route, config, options) {
532
629
  },
533
630
  handler: async (rawRequest, ctx) => {
534
631
  const rawContext = options?.createContext ? options.createContext(rawRequest) : ctx ?? { requestId: generateRequestId() };
535
- const validatedContext = route.request.context?.schema ? wrapError(
632
+ const validatedContext = route.request.context ? wrapError(
536
633
  () => {
537
634
  const result = validateContextData(route, rawContext);
538
635
  if (!result.success) {
@@ -636,8 +733,8 @@ function createRouteHandler(route, config, options) {
636
733
  function validateRequestData(route, rawRequest) {
637
734
  const errors = [];
638
735
  const data = {};
639
- if (route.request.body?.schema) {
640
- const result = route.request.body.schema.validate(rawRequest.body);
736
+ if (route.request.body) {
737
+ const result = route.request.body.validate(rawRequest.body);
641
738
  if (result.success) {
642
739
  data.body = result.data;
643
740
  } else {
@@ -649,9 +746,9 @@ function validateRequestData(route, rawRequest) {
649
746
  );
650
747
  }
651
748
  }
652
- if (route.request.query?.schema) {
749
+ if (route.request.query) {
653
750
  const queryObj = normalizeQuery(rawRequest.query);
654
- const result = route.request.query.schema.validate(queryObj);
751
+ const result = route.request.query.validate(queryObj);
655
752
  if (result.success) {
656
753
  data.query = result.data;
657
754
  } else {
@@ -663,8 +760,8 @@ function validateRequestData(route, rawRequest) {
663
760
  );
664
761
  }
665
762
  }
666
- if (route.request.params?.schema) {
667
- const result = route.request.params.schema.validate(rawRequest.params ?? {});
763
+ if (route.request.params) {
764
+ const result = route.request.params.validate(rawRequest.params ?? {});
668
765
  if (result.success) {
669
766
  data.pathParams = result.data;
670
767
  } else {
@@ -678,9 +775,9 @@ function validateRequestData(route, rawRequest) {
678
775
  } else {
679
776
  data.pathParams = normalizePathParams(rawRequest.params);
680
777
  }
681
- if (route.request.headers?.schema) {
778
+ if (route.request.headers) {
682
779
  const headersObj = normalizeHeaders(rawRequest.headers);
683
- const result = route.request.headers.schema.validate(headersObj);
780
+ const result = route.request.headers.validate(headersObj);
684
781
  if (result.success) {
685
782
  data.headers = result.data;
686
783
  } else {
@@ -698,13 +795,11 @@ function validateRequestData(route, rawRequest) {
698
795
  return { success: true, data };
699
796
  }
700
797
  function validateResponseData(route, response) {
701
- const statusCode = String(response.status);
702
- const responses = route.responses;
703
- const responseConfig = responses[statusCode];
704
- if (!responseConfig) {
798
+ if (!route.responses) {
705
799
  return { success: true };
706
800
  }
707
- const schema = responseConfig.schema;
801
+ const entry = route.responses[String(response.status)];
802
+ const schema = entry?.schema;
708
803
  if (!schema) {
709
804
  return { success: true };
710
805
  }
@@ -719,7 +814,7 @@ function validateResponseData(route, response) {
719
814
  return { success: false, errors };
720
815
  }
721
816
  function validateContextData(route, context) {
722
- const contextSchema = route.request.context?.schema;
817
+ const contextSchema = route.request.context;
723
818
  if (!contextSchema) {
724
819
  return { success: true, data: context };
725
820
  }
@@ -857,12 +952,12 @@ function generateOpenAPI(router, config) {
857
952
  const collectedRoutes = collectRoutes(routes);
858
953
  const paths = {};
859
954
  const allTags = /* @__PURE__ */ new Set();
860
- for (const { route } of collectedRoutes) {
955
+ for (const { key, route } of collectedRoutes) {
861
956
  const openAPIPath = convertToOpenAPIPath(route.path);
862
957
  if (!paths[openAPIPath]) {
863
958
  paths[openAPIPath] = {};
864
959
  }
865
- const operation = buildOperation(route);
960
+ const operation = buildOperation(key, route);
866
961
  const method = route.method.toLowerCase();
867
962
  paths[openAPIPath][method] = operation;
868
963
  if (operation.tags) {
@@ -904,13 +999,12 @@ function generateOpenAPI(router, config) {
904
999
  function convertToOpenAPIPath(path) {
905
1000
  return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "{$1}");
906
1001
  }
907
- function buildOperation(route) {
1002
+ function buildOperation(key, route) {
908
1003
  const operation = {
909
1004
  responses: buildResponses(route)
910
1005
  };
911
- if (route.docs.operationId) {
912
- operation.operationId = route.docs.operationId;
913
- }
1006
+ const operationId = route.docs.operationId ?? generateOperationId(key);
1007
+ operation.operationId = operationId;
914
1008
  if (route.docs.summary) {
915
1009
  operation.summary = route.docs.summary;
916
1010
  }
@@ -948,8 +1042,8 @@ function buildParameters(route) {
948
1042
  required: true,
949
1043
  schema: { type: "string" }
950
1044
  };
951
- if (route.request.params?.schema) {
952
- const jsonSchema = route.request.params.schema.toJsonSchema();
1045
+ if (route.request.params) {
1046
+ const jsonSchema = route.request.params.toJsonSchema();
953
1047
  if (jsonSchema.properties && typeof jsonSchema.properties === "object") {
954
1048
  const propSchema = jsonSchema.properties[name];
955
1049
  if (isValidJsonSchema(propSchema)) {
@@ -959,8 +1053,8 @@ function buildParameters(route) {
959
1053
  }
960
1054
  parameters.push(param);
961
1055
  }
962
- if (route.request.query?.schema) {
963
- const querySchema = route.request.query.schema.toJsonSchema();
1056
+ if (route.request.query) {
1057
+ const querySchema = route.request.query.toJsonSchema();
964
1058
  if (querySchema.properties && typeof querySchema.properties === "object") {
965
1059
  const requiredFields = new Set(
966
1060
  Array.isArray(querySchema.required) ? querySchema.required : []
@@ -984,8 +1078,8 @@ function buildParameters(route) {
984
1078
  }
985
1079
  }
986
1080
  }
987
- if (route.request.headers?.schema) {
988
- const headersSchema = route.request.headers.schema.toJsonSchema();
1081
+ if (route.request.headers) {
1082
+ const headersSchema = route.request.headers.toJsonSchema();
989
1083
  if (headersSchema.properties && typeof headersSchema.properties === "object") {
990
1084
  const requiredFields = new Set(
991
1085
  Array.isArray(headersSchema.required) ? headersSchema.required : []
@@ -1009,63 +1103,439 @@ function buildParameters(route) {
1009
1103
  return parameters;
1010
1104
  }
1011
1105
  function buildRequestBody(route) {
1012
- const bodyConfig = route.request.body;
1013
- const contentType = bodyConfig.contentType ?? "application/json";
1106
+ const bodySchema = route.request.body;
1107
+ const meta = route._meta?.body;
1108
+ const contentType = meta?.contentType ?? "application/json";
1014
1109
  const requestBody = {
1015
- required: bodyConfig.required !== false,
1110
+ required: meta?.required !== false,
1016
1111
  content: {
1017
1112
  [contentType]: {
1018
- schema: bodyConfig.schema.toJsonSchema()
1113
+ schema: bodySchema.toJsonSchema()
1019
1114
  }
1020
1115
  }
1021
1116
  };
1022
- if (bodyConfig.description) {
1023
- requestBody.description = bodyConfig.description;
1117
+ if (meta?.description) {
1118
+ requestBody.description = meta.description;
1024
1119
  }
1025
1120
  return requestBody;
1026
1121
  }
1027
1122
  function buildResponses(route) {
1028
1123
  const responses = {};
1029
- for (const [statusCode, responseConfig] of Object.entries(route.responses)) {
1030
- if (!responseConfig || typeof responseConfig !== "object") continue;
1031
- const response = {
1032
- description: responseConfig.description ?? `Response ${statusCode}`
1033
- };
1034
- const schema = responseConfig.schema;
1035
- if (schema) {
1036
- const contentType = responseConfig.contentType ?? "application/json";
1037
- response.content = {
1038
- [contentType]: {
1039
- schema: schema.toJsonSchema()
1040
- }
1041
- };
1124
+ if (route.responses && Object.keys(route.responses).length > 0) {
1125
+ for (const [statusCode, config] of Object.entries(route.responses)) {
1126
+ const description = config.description ?? `Response ${statusCode}`;
1127
+ if (config.schema) {
1128
+ const contentType = config.contentType ?? "application/json";
1129
+ responses[statusCode] = {
1130
+ description,
1131
+ content: {
1132
+ [contentType]: {
1133
+ schema: config.schema.toJsonSchema()
1134
+ }
1135
+ }
1136
+ };
1137
+ } else {
1138
+ responses[statusCode] = { description };
1139
+ }
1042
1140
  }
1043
- responses[statusCode] = response;
1044
- }
1045
- if (Object.keys(responses).length === 0) {
1141
+ } else {
1046
1142
  responses["200"] = { description: "Successful response" };
1047
1143
  }
1048
1144
  return responses;
1049
1145
  }
1146
+
1147
+ // src/global/exceptions/object-validation.error.ts
1148
+ var ObjectValidationError = class _ObjectValidationError extends CodedError {
1149
+ /**
1150
+ * Array of field-level validation errors.
1151
+ *
1152
+ * Each entry contains:
1153
+ * - `field`: Dot-notation path to the invalid field (e.g., 'user.email')
1154
+ * - `message`: Human-readable validation failure message
1155
+ */
1156
+ validationErrors;
1157
+ /**
1158
+ * Creates a new ObjectValidationError instance.
1159
+ *
1160
+ * @param options - Error configuration
1161
+ * @param options.message - Human-readable summary message
1162
+ * @param options.code - Machine-readable error code (default: 'OBJECT_VALIDATION_ERROR')
1163
+ * @param options.cause - Optional underlying error from validation library
1164
+ * @param options.validationErrors - Array of field-level validation errors
1165
+ */
1166
+ constructor({
1167
+ message,
1168
+ code = ErrorCodes.Global.OBJECT_VALIDATION_ERROR,
1169
+ cause,
1170
+ validationErrors
1171
+ }) {
1172
+ super({ message, code, cause });
1173
+ this.validationErrors = validationErrors;
1174
+ }
1175
+ /**
1176
+ * Creates an ObjectValidationError from a caught error.
1177
+ *
1178
+ * @param cause - The original caught error
1179
+ * @returns A new ObjectValidationError instance with the cause attached
1180
+ */
1181
+ static fromError(cause) {
1182
+ return new _ObjectValidationError({
1183
+ message: cause instanceof Error ? cause.message : "Validation failed",
1184
+ cause,
1185
+ validationErrors: []
1186
+ });
1187
+ }
1188
+ };
1189
+
1190
+ // src/domain/exceptions/domain.error.ts
1191
+ var DomainError = class _DomainError extends CodedError {
1192
+ /**
1193
+ * Creates a new DomainError instance.
1194
+ *
1195
+ * @param options - Error configuration
1196
+ * @param options.message - Human-readable error description
1197
+ * @param options.code - Machine-readable error code (default: 'DOMAIN_ERROR')
1198
+ * @param options.cause - Optional underlying error
1199
+ */
1200
+ constructor({
1201
+ message,
1202
+ code = ErrorCodes.Domain.DOMAIN_ERROR,
1203
+ cause
1204
+ }) {
1205
+ super({ message, code, cause });
1206
+ }
1207
+ /**
1208
+ * Creates a DomainError from a caught error.
1209
+ *
1210
+ * @param cause - The original caught error
1211
+ * @returns A new DomainError instance with the cause attached
1212
+ */
1213
+ static fromError(cause) {
1214
+ return new _DomainError({
1215
+ message: cause instanceof Error ? cause.message : "Domain error",
1216
+ cause
1217
+ });
1218
+ }
1219
+ };
1220
+
1221
+ // src/app/exceptions/not-found.error.ts
1222
+ var NotFoundError = class _NotFoundError extends UseCaseError {
1223
+ /**
1224
+ * Creates a new NotFoundError instance.
1225
+ *
1226
+ * @param options - Error configuration
1227
+ * @param options.message - Description of what was not found
1228
+ * @param options.code - Machine-readable error code (default: 'NOT_FOUND')
1229
+ * @param options.cause - Optional underlying error
1230
+ */
1231
+ constructor({
1232
+ message,
1233
+ code = ErrorCodes.App.NOT_FOUND,
1234
+ cause
1235
+ }) {
1236
+ super({ message, code, cause });
1237
+ }
1238
+ /**
1239
+ * Creates a NotFoundError from a caught error.
1240
+ *
1241
+ * @param cause - The original caught error
1242
+ * @returns A new NotFoundError instance with the cause attached
1243
+ */
1244
+ static fromError(cause) {
1245
+ return new _NotFoundError({
1246
+ message: cause instanceof Error ? cause.message : "Resource not found",
1247
+ cause
1248
+ });
1249
+ }
1250
+ };
1251
+
1252
+ // src/app/exceptions/conflict.error.ts
1253
+ var ConflictError = class _ConflictError extends UseCaseError {
1254
+ /**
1255
+ * Creates a new ConflictError instance.
1256
+ *
1257
+ * @param options - Error configuration
1258
+ * @param options.message - Description of the conflict
1259
+ * @param options.code - Machine-readable error code (default: 'CONFLICT')
1260
+ * @param options.cause - Optional underlying error
1261
+ */
1262
+ constructor({
1263
+ message,
1264
+ code = ErrorCodes.App.CONFLICT,
1265
+ cause
1266
+ }) {
1267
+ super({ message, code, cause });
1268
+ }
1269
+ /**
1270
+ * Creates a ConflictError from a caught error.
1271
+ *
1272
+ * @param cause - The original caught error
1273
+ * @returns A new ConflictError instance with the cause attached
1274
+ */
1275
+ static fromError(cause) {
1276
+ return new _ConflictError({
1277
+ message: cause instanceof Error ? cause.message : "Conflict error",
1278
+ cause
1279
+ });
1280
+ }
1281
+ };
1282
+
1283
+ // src/app/exceptions/unprocessable.error.ts
1284
+ var UnprocessableError = class _UnprocessableError extends UseCaseError {
1285
+ /**
1286
+ * Creates a new UnprocessableError instance.
1287
+ *
1288
+ * @param options - Error configuration
1289
+ * @param options.message - Description of why the request cannot be processed
1290
+ * @param options.code - Machine-readable error code (default: 'UNPROCESSABLE')
1291
+ * @param options.cause - Optional underlying error
1292
+ */
1293
+ constructor({
1294
+ message,
1295
+ code = ErrorCodes.App.UNPROCESSABLE,
1296
+ cause
1297
+ }) {
1298
+ super({ message, code, cause });
1299
+ }
1300
+ /**
1301
+ * Creates an UnprocessableError from a caught error.
1302
+ *
1303
+ * @param cause - The original caught error
1304
+ * @returns A new UnprocessableError instance with the cause attached
1305
+ */
1306
+ static fromError(cause) {
1307
+ return new _UnprocessableError({
1308
+ message: cause instanceof Error ? cause.message : "Unprocessable request",
1309
+ cause
1310
+ });
1311
+ }
1312
+ };
1313
+
1314
+ // src/app/exceptions/forbidden.error.ts
1315
+ var ForbiddenError = class _ForbiddenError extends UseCaseError {
1316
+ /**
1317
+ * Creates a new ForbiddenError instance.
1318
+ *
1319
+ * @param options - Error configuration
1320
+ * @param options.message - Description of why authorization was denied
1321
+ * @param options.code - Machine-readable error code (default: 'FORBIDDEN')
1322
+ * @param options.cause - Optional underlying error
1323
+ */
1324
+ constructor({
1325
+ message,
1326
+ code = ErrorCodes.App.FORBIDDEN,
1327
+ cause
1328
+ }) {
1329
+ super({ message, code, cause });
1330
+ }
1331
+ /**
1332
+ * Creates a ForbiddenError from a caught error.
1333
+ *
1334
+ * @param cause - The original caught error
1335
+ * @returns A new ForbiddenError instance with the cause attached
1336
+ */
1337
+ static fromError(cause) {
1338
+ return new _ForbiddenError({
1339
+ message: cause instanceof Error ? cause.message : "Operation forbidden",
1340
+ cause
1341
+ });
1342
+ }
1343
+ };
1344
+
1345
+ // src/infra/exceptions/infra.error.ts
1346
+ var InfraError = class _InfraError extends CodedError {
1347
+ /**
1348
+ * Creates a new InfraError instance.
1349
+ *
1350
+ * @param options - Error configuration
1351
+ * @param options.message - Human-readable error description
1352
+ * @param options.code - Machine-readable error code (default: 'INFRA_ERROR')
1353
+ * @param options.cause - Optional underlying error
1354
+ */
1355
+ constructor({
1356
+ message,
1357
+ code = ErrorCodes.Infra.INFRA_ERROR,
1358
+ cause
1359
+ }) {
1360
+ super({ message, code, cause });
1361
+ }
1362
+ /**
1363
+ * Creates an InfraError from a caught error.
1364
+ *
1365
+ * @param cause - The original caught error
1366
+ * @returns A new InfraError instance with the cause attached
1367
+ */
1368
+ static fromError(cause) {
1369
+ return new _InfraError({
1370
+ message: cause instanceof Error ? cause.message : "Infrastructure error",
1371
+ cause
1372
+ });
1373
+ }
1374
+ };
1375
+
1376
+ // src/presentation/exceptions/access-denied.error.ts
1377
+ var AccessDeniedError = class _AccessDeniedError extends CodedError {
1378
+ /**
1379
+ * Creates a new AccessDeniedError instance.
1380
+ *
1381
+ * @param options - Error configuration
1382
+ * @param options.message - Description of why access was denied
1383
+ * @param options.code - Machine-readable error code (default: 'ACCESS_DENIED')
1384
+ * @param options.cause - Optional underlying error
1385
+ */
1386
+ constructor({
1387
+ message,
1388
+ code = ErrorCodes.Presentation.ACCESS_DENIED,
1389
+ cause
1390
+ }) {
1391
+ super({ message, code, cause });
1392
+ }
1393
+ /**
1394
+ * Creates an AccessDeniedError from a caught error.
1395
+ *
1396
+ * @param cause - The original caught error
1397
+ * @returns A new AccessDeniedError instance with the cause attached
1398
+ */
1399
+ static fromError(cause) {
1400
+ return new _AccessDeniedError({
1401
+ message: cause instanceof Error ? cause.message : "Access denied",
1402
+ cause
1403
+ });
1404
+ }
1405
+ };
1406
+
1407
+ // src/presentation/http/shared/error-mapping.ts
1408
+ var MASKED_ERROR_BODY = {
1409
+ message: "An unexpected error occurred",
1410
+ errorCode: "INTERNAL_ERROR"
1411
+ };
1412
+ var INTERNAL_ERROR_TYPES = [
1413
+ "DomainError",
1414
+ "InfraError",
1415
+ "ControllerError",
1416
+ "NetworkError",
1417
+ "PersistenceError",
1418
+ "ExternalServiceError",
1419
+ "InvariantViolationError"
1420
+ ];
1421
+ function isErrorType(error, typeName) {
1422
+ if (!error || typeof error !== "object") return false;
1423
+ const constructor = Object.prototype.hasOwnProperty.call(error, "constructor") ? error.constructor : Object.getPrototypeOf(error)?.constructor;
1424
+ if (!constructor) return false;
1425
+ const name = constructor.name;
1426
+ return name === typeName || name === `_${typeName}`;
1427
+ }
1428
+ function hasValidationErrors(error) {
1429
+ if (!error || typeof error !== "object") return false;
1430
+ return "validationErrors" in error && Array.isArray(error.validationErrors);
1431
+ }
1432
+ function buildValidationErrorBody(message, code, validationErrors) {
1433
+ return {
1434
+ message,
1435
+ errorCode: code,
1436
+ errorItems: validationErrors.map((e) => ({
1437
+ item: e.field,
1438
+ message: e.message
1439
+ }))
1440
+ };
1441
+ }
1442
+ function buildSimpleErrorBody(message, code) {
1443
+ return {
1444
+ message,
1445
+ errorCode: code
1446
+ };
1447
+ }
1448
+ function getHttpStatusCode(error) {
1449
+ if (error instanceof ObjectValidationError) return 400;
1450
+ if (error instanceof InvalidRequestError) return 400;
1451
+ if (error instanceof UnauthorizedError) return 401;
1452
+ if (error instanceof ForbiddenError) return 403;
1453
+ if (error instanceof AccessDeniedError) return 403;
1454
+ if (error instanceof NotFoundError) return 404;
1455
+ if (error instanceof ConflictError) return 409;
1456
+ if (error instanceof UnprocessableError) return 422;
1457
+ if (error instanceof UseCaseError) return 400;
1458
+ if (isErrorType(error, "ObjectValidationError")) return 400;
1459
+ if (isErrorType(error, "InvalidRequestError")) return 400;
1460
+ if (isErrorType(error, "UnauthorizedError")) return 401;
1461
+ if (isErrorType(error, "ForbiddenError")) return 403;
1462
+ if (isErrorType(error, "AccessDeniedError")) return 403;
1463
+ if (isErrorType(error, "NotFoundError")) return 404;
1464
+ if (isErrorType(error, "ConflictError")) return 409;
1465
+ if (isErrorType(error, "UnprocessableError")) return 422;
1466
+ if (isErrorType(error, "UseCaseError")) return 400;
1467
+ return 500;
1468
+ }
1469
+ function shouldMaskError(error) {
1470
+ if (error instanceof DomainError || error instanceof InfraError || error instanceof ControllerError) {
1471
+ return true;
1472
+ }
1473
+ for (const errorType of INTERNAL_ERROR_TYPES) {
1474
+ if (isErrorType(error, errorType)) {
1475
+ return true;
1476
+ }
1477
+ }
1478
+ return false;
1479
+ }
1480
+ function createErrorResponseBody(error) {
1481
+ if (shouldMaskError(error)) {
1482
+ return MASKED_ERROR_BODY;
1483
+ }
1484
+ if (error instanceof ObjectValidationError) {
1485
+ return buildValidationErrorBody(error.message, error.code, error.validationErrors);
1486
+ }
1487
+ if (error instanceof InvalidRequestError) {
1488
+ return buildValidationErrorBody(error.message, error.code, error.validationErrors);
1489
+ }
1490
+ if (isErrorType(error, "ObjectValidationError") && hasValidationErrors(error)) {
1491
+ return buildValidationErrorBody(error.message, error.code, error.validationErrors);
1492
+ }
1493
+ if (isErrorType(error, "InvalidRequestError") && hasValidationErrors(error)) {
1494
+ return buildValidationErrorBody(error.message, error.code, error.validationErrors);
1495
+ }
1496
+ if (error instanceof CodedError) {
1497
+ return buildSimpleErrorBody(error.message, error.code);
1498
+ }
1499
+ if (isErrorType(error, "CodedError")) {
1500
+ return buildSimpleErrorBody(error.message, error.code);
1501
+ }
1502
+ if (error && typeof error === "object" && "message" in error && "code" in error && typeof error.message === "string" && typeof error.code === "string") {
1503
+ return buildSimpleErrorBody(error.message, error.code);
1504
+ }
1505
+ return MASKED_ERROR_BODY;
1506
+ }
1507
+ function mapErrorToHttpResponse(error) {
1508
+ return {
1509
+ status: getHttpStatusCode(error),
1510
+ body: createErrorResponseBody(error)
1511
+ };
1512
+ }
1050
1513
  // Annotate the CommonJS export names for ESM import in node:
1051
1514
  0 && (module.exports = {
1052
1515
  buildPath,
1053
1516
  collectRoutes,
1517
+ createErrorResponseBody,
1054
1518
  createPassthroughAdapter,
1055
1519
  createRejectingAdapter,
1056
1520
  defineRoute,
1057
1521
  defineRouter,
1058
1522
  generateOpenAPI,
1523
+ generateOperationId,
1524
+ getHttpStatusCode,
1059
1525
  getPathParamNames,
1060
1526
  hasPathParams,
1527
+ hasValidationErrors,
1528
+ isErrorType,
1061
1529
  isRouteDefinition,
1062
1530
  isRouterDefinition,
1063
1531
  isSchemaAdapter,
1064
1532
  isValidationFailure,
1065
1533
  isValidationSuccess,
1534
+ mapErrorToHttpResponse,
1066
1535
  mergeRouters,
1067
1536
  normalizePath,
1068
1537
  pathToRegex,
1069
- serverRoutes
1538
+ serverRoutes,
1539
+ shouldMaskError
1070
1540
  });
1071
1541
  //# sourceMappingURL=index.cjs.map