@fluojs/http 1.0.0-beta.1 → 1.0.0-beta.3

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 (66) hide show
  1. package/README.ko.md +11 -4
  2. package/README.md +11 -4
  3. package/dist/adapter.d.ts +31 -0
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +37 -0
  6. package/dist/adapters/binding.d.ts +6 -0
  7. package/dist/adapters/binding.d.ts.map +1 -1
  8. package/dist/adapters/binding.js +8 -0
  9. package/dist/adapters/dto-validation-adapter.d.ts +3 -0
  10. package/dist/adapters/dto-validation-adapter.d.ts.map +1 -1
  11. package/dist/adapters/dto-validation-adapter.js +3 -0
  12. package/dist/context/sse.d.ts +38 -0
  13. package/dist/context/sse.d.ts.map +1 -1
  14. package/dist/context/sse.js +50 -2
  15. package/dist/decorators.d.ts.map +1 -1
  16. package/dist/decorators.js +2 -2
  17. package/dist/dispatch/dispatch-content-negotiation.d.ts +17 -0
  18. package/dist/dispatch/dispatch-content-negotiation.d.ts.map +1 -1
  19. package/dist/dispatch/dispatch-content-negotiation.js +21 -0
  20. package/dist/dispatch/dispatch-error-policy.d.ts +8 -0
  21. package/dist/dispatch/dispatch-error-policy.d.ts.map +1 -1
  22. package/dist/dispatch/dispatch-error-policy.js +9 -0
  23. package/dist/dispatch/dispatch-handler-policy.d.ts +8 -0
  24. package/dist/dispatch/dispatch-handler-policy.d.ts.map +1 -1
  25. package/dist/dispatch/dispatch-handler-policy.js +9 -0
  26. package/dist/dispatch/dispatch-response-policy.d.ts +10 -0
  27. package/dist/dispatch/dispatch-response-policy.d.ts.map +1 -1
  28. package/dist/dispatch/dispatch-response-policy.js +11 -0
  29. package/dist/dispatch/dispatch-routing-policy.d.ts +13 -0
  30. package/dist/dispatch/dispatch-routing-policy.d.ts.map +1 -1
  31. package/dist/dispatch/dispatch-routing-policy.js +14 -0
  32. package/dist/dispatch/dispatcher.d.ts.map +1 -1
  33. package/dist/dispatch/dispatcher.js +55 -16
  34. package/dist/errors.d.ts +3 -0
  35. package/dist/errors.d.ts.map +1 -1
  36. package/dist/errors.js +4 -0
  37. package/dist/guards.d.ts +7 -0
  38. package/dist/guards.d.ts.map +1 -1
  39. package/dist/guards.js +11 -0
  40. package/dist/input-error-detail.d.ts +9 -0
  41. package/dist/input-error-detail.d.ts.map +1 -1
  42. package/dist/input-error-detail.js +10 -0
  43. package/dist/interceptors.d.ts +8 -0
  44. package/dist/interceptors.d.ts.map +1 -1
  45. package/dist/interceptors.js +14 -1
  46. package/dist/mapping.d.ts +7 -0
  47. package/dist/mapping.d.ts.map +1 -1
  48. package/dist/mapping.js +93 -11
  49. package/dist/middleware/correlation.d.ts +5 -0
  50. package/dist/middleware/correlation.d.ts.map +1 -1
  51. package/dist/middleware/correlation.js +6 -0
  52. package/dist/middleware/cors.d.ts +9 -0
  53. package/dist/middleware/cors.d.ts.map +1 -1
  54. package/dist/middleware/cors.js +11 -0
  55. package/dist/middleware/middleware.d.ts +34 -0
  56. package/dist/middleware/middleware.d.ts.map +1 -1
  57. package/dist/middleware/middleware.js +47 -0
  58. package/dist/middleware/security-headers.d.ts +9 -0
  59. package/dist/middleware/security-headers.d.ts.map +1 -1
  60. package/dist/middleware/security-headers.js +11 -0
  61. package/dist/route-path.d.ts +41 -0
  62. package/dist/route-path.d.ts.map +1 -1
  63. package/dist/route-path.js +50 -0
  64. package/dist/types.d.ts +5 -0
  65. package/dist/types.d.ts.map +1 -1
  66. package/package.json +4 -4
@@ -1,4 +1,17 @@
1
1
  import type { FrameworkRequest, HandlerMapping, HandlerMatch, RequestContext } from '../types.js';
2
+ /**
3
+ * Match handler or throw.
4
+ *
5
+ * @param handlerMapping The handler mapping.
6
+ * @param request The request.
7
+ * @returns The match handler or throw result.
8
+ */
2
9
  export declare function matchHandlerOrThrow(handlerMapping: HandlerMapping, request: FrameworkRequest): HandlerMatch;
10
+ /**
11
+ * Update request params.
12
+ *
13
+ * @param requestContext The request context.
14
+ * @param params The params.
15
+ */
3
16
  export declare function updateRequestParams(requestContext: RequestContext, params: Readonly<Record<string, string>>): void;
4
17
  //# sourceMappingURL=dispatch-routing-policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-routing-policy.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatch-routing-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElG,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,YAAY,CAQ3G;AAED,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAKlH"}
1
+ {"version":3,"file":"dispatch-routing-policy.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatch-routing-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElG;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,YAAY,CAQ3G;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAKlH"}
@@ -1,4 +1,11 @@
1
1
  import { HandlerNotFoundError } from '../errors.js';
2
+ /**
3
+ * Match handler or throw.
4
+ *
5
+ * @param handlerMapping The handler mapping.
6
+ * @param request The request.
7
+ * @returns The match handler or throw result.
8
+ */
2
9
  export function matchHandlerOrThrow(handlerMapping, request) {
3
10
  const match = handlerMapping.match(request);
4
11
  if (!match) {
@@ -6,6 +13,13 @@ export function matchHandlerOrThrow(handlerMapping, request) {
6
13
  }
7
14
  return match;
8
15
  }
16
+
17
+ /**
18
+ * Update request params.
19
+ *
20
+ * @param requestContext The request context.
21
+ * @param params The params.
22
+ */
9
23
  export function updateRequestParams(requestContext, params) {
10
24
  requestContext.request = {
11
25
  ...requestContext.request,
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAW5C,OAAO,KAAK,EACV,MAAM,EACN,yBAAyB,EACzB,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAGjB,cAAc,EACd,eAAe,EAGf,cAAc,EAId,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpK;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,sDAAsD;IACtD,cAAc,EAAE,cAAc,CAAC;IAC/B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,qCAAqC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,SAAS,CAAC;CAC1B;AAmQD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU,CA8B7E"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAW5C,OAAO,KAAK,EACV,MAAM,EACN,yBAAyB,EACzB,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAGjB,cAAc,EACd,eAAe,EAEf,cAAc,EAId,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpK;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,sDAAsD;IACtD,cAAc,EAAE,cAAc,CAAC;IAC/B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,qCAAqC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,SAAS,CAAC;CAC1B;AA8SD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU,CAoC7E"}
@@ -31,6 +31,28 @@ function createDispatchRequest(request) {
31
31
  }
32
32
  };
33
33
  }
34
+ function cloneHandlerDescriptor(descriptor) {
35
+ return {
36
+ ...descriptor,
37
+ metadata: {
38
+ ...descriptor.metadata,
39
+ moduleMiddleware: [...descriptor.metadata.moduleMiddleware],
40
+ pathParams: [...descriptor.metadata.pathParams]
41
+ },
42
+ route: {
43
+ ...descriptor.route,
44
+ guards: descriptor.route.guards ? [...descriptor.route.guards] : undefined,
45
+ headers: descriptor.route.headers?.map(header => ({
46
+ ...header
47
+ })),
48
+ interceptors: descriptor.route.interceptors ? [...descriptor.route.interceptors] : undefined,
49
+ produces: descriptor.route.produces ? [...descriptor.route.produces] : undefined,
50
+ redirect: descriptor.route.redirect ? {
51
+ ...descriptor.route.redirect
52
+ } : undefined
53
+ }
54
+ };
55
+ }
34
56
  function readRequestId(request) {
35
57
  const raw = request.headers['x-request-id'] ?? request.headers['X-Request-Id'];
36
58
  const value = Array.isArray(raw) ? raw[0] : raw;
@@ -71,29 +93,41 @@ async function notifyObservers(observers, requestContext, callback, handler) {
71
93
  }
72
94
  }
73
95
  async function notifyObserversSafely(observers, requestContext, callback, logger, handler) {
96
+ if (observers.length === 0) {
97
+ return;
98
+ }
74
99
  try {
75
100
  await notifyObservers(observers, requestContext, callback, handler);
76
101
  } catch (error) {
77
102
  logDispatchFailure(logger, 'Request observer threw an unhandled error.', error);
78
103
  }
79
104
  }
105
+ function mergeInterceptors(globalInterceptors, routeInterceptors) {
106
+ if (globalInterceptors.length === 0) {
107
+ return routeInterceptors;
108
+ }
109
+ if (routeInterceptors.length === 0) {
110
+ return globalInterceptors;
111
+ }
112
+ return [...globalInterceptors, ...routeInterceptors];
113
+ }
80
114
  async function dispatchMatchedHandler(handler, requestContext, observers, contentNegotiation, binder, globalInterceptors, logger) {
81
- const guardContext = {
82
- handler,
83
- requestContext
84
- };
85
- const interceptorContext = {
86
- handler,
87
- requestContext
88
- };
89
- await runGuardChain(handler.route.guards ?? [], guardContext);
115
+ const routeGuards = handler.route.guards ?? [];
116
+ if (routeGuards.length > 0) {
117
+ const guardContext = {
118
+ handler,
119
+ requestContext
120
+ };
121
+ await runGuardChain(routeGuards, guardContext);
122
+ }
90
123
  if (requestContext.response.committed) {
91
124
  return;
92
125
  }
93
- const interceptors = [...(globalInterceptors ?? []), ...(handler.route.interceptors ?? [])];
94
- const result = await runInterceptorChain(interceptors, interceptorContext, async () => {
95
- return invokeControllerHandler(handler, requestContext, binder);
96
- });
126
+ const routeInterceptors = handler.route.interceptors ?? [];
127
+ const result = globalInterceptors.length === 0 && routeInterceptors.length === 0 ? await invokeControllerHandler(handler, requestContext, binder) : await runInterceptorChain(mergeInterceptors(globalInterceptors, routeInterceptors), {
128
+ handler,
129
+ requestContext
130
+ }, async () => invokeControllerHandler(handler, requestContext, binder));
97
131
  ensureRequestNotAborted(requestContext.request);
98
132
  if (!(result instanceof SseResponse) && !requestContext.response.committed) {
99
133
  await writeSuccessResponse(handler, requestContext.request, requestContext.response, result, contentNegotiation);
@@ -143,7 +177,7 @@ async function runDispatchPipeline(context) {
143
177
  response: context.response
144
178
  };
145
179
  await runMiddlewareChain(match.descriptor.metadata.moduleMiddleware ?? [], moduleMiddlewareContext, async () => {
146
- await dispatchMatchedHandler(match.descriptor, context.requestContext, context.observers, context.contentNegotiation, context.options.binder, context.options.interceptors, context.options.logger);
180
+ await dispatchMatchedHandler(match.descriptor, context.requestContext, context.observers, context.contentNegotiation, context.options.binder, context.options.interceptors ?? [], context.options.logger);
147
181
  });
148
182
  });
149
183
  }
@@ -167,11 +201,15 @@ async function handleDispatchError(context, error) {
167
201
  */
168
202
  export function createDispatcher(options) {
169
203
  const contentNegotiation = resolveContentNegotiation(options.contentNegotiation);
170
- return {
204
+ const observers = options.observers ?? [];
205
+ const dispatcher = {
206
+ describeRoutes() {
207
+ return options.handlerMapping.descriptors.map(descriptor => cloneHandlerDescriptor(descriptor));
208
+ },
171
209
  async dispatch(request, response) {
172
210
  const phaseContext = {
173
211
  contentNegotiation,
174
- observers: options.observers ?? [],
212
+ observers,
175
213
  options,
176
214
  requestContext: createDispatchContext(createDispatchRequest(request), response, options.rootContainer),
177
215
  response
@@ -193,4 +231,5 @@ export function createDispatcher(options) {
193
231
  });
194
232
  }
195
233
  };
234
+ return dispatcher;
196
235
  }
package/dist/errors.d.ts CHANGED
@@ -5,6 +5,9 @@ import { FluoError } from '@fluojs/core';
5
5
  export declare class RouteConflictError extends FluoError {
6
6
  constructor(message: string);
7
7
  }
8
+ /**
9
+ * Represents the invalid route path error.
10
+ */
8
11
  export declare class InvalidRoutePathError extends FluoError {
9
12
  constructor(message: string);
10
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,qBAAsB,SAAQ,SAAS;gBACtC,OAAO,EAAE,MAAM;CAG5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,OAAO,EAAE,MAAM;CAG5B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,SAA4C;CAGhE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,EAAE,MAAM;CAG5B;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACtC,OAAO,EAAE,MAAM;CAG5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,OAAO,EAAE,MAAM;CAG5B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,SAA4C;CAGhE"}
package/dist/errors.js CHANGED
@@ -10,6 +10,10 @@ export class RouteConflictError extends FluoError {
10
10
  });
11
11
  }
12
12
  }
13
+
14
+ /**
15
+ * Represents the invalid route path error.
16
+ */
13
17
  export class InvalidRoutePathError extends FluoError {
14
18
  constructor(message) {
15
19
  super(message, {
package/dist/guards.d.ts CHANGED
@@ -1,3 +1,10 @@
1
1
  import type { GuardContext, GuardLike } from './types.js';
2
+ /**
3
+ * Run guard chain.
4
+ *
5
+ * @param definitions The definitions.
6
+ * @param context The context.
7
+ * @returns The run guard chain result.
8
+ */
2
9
  export declare function runGuardChain(definitions: GuardLike[], context: GuardContext): Promise<void>;
3
10
  //# sourceMappingURL=guards.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAS,YAAY,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAcjF,wBAAsB,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CASlG"}
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAS,YAAY,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAcjF;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAalG"}
package/dist/guards.js CHANGED
@@ -8,7 +8,18 @@ async function resolveGuard(definition, requestContext) {
8
8
  }
9
9
  return requestContext.container.resolve(definition);
10
10
  }
11
+
12
+ /**
13
+ * Run guard chain.
14
+ *
15
+ * @param definitions The definitions.
16
+ * @param context The context.
17
+ * @returns The run guard chain result.
18
+ */
11
19
  export async function runGuardChain(definitions, context) {
20
+ if (definitions.length === 0) {
21
+ return;
22
+ }
12
23
  for (const definition of definitions) {
13
24
  const guard = await resolveGuard(definition, context.requestContext);
14
25
  const result = await guard.canActivate(context);
@@ -1,10 +1,19 @@
1
1
  import type { MetadataSource } from '@fluojs/core';
2
2
  import type { HttpExceptionDetail } from './exceptions.js';
3
+ /**
4
+ * Describes the input error detail contract.
5
+ */
3
6
  export interface InputErrorDetail {
4
7
  code: string;
5
8
  field?: string;
6
9
  message: string;
7
10
  source?: MetadataSource;
8
11
  }
12
+ /**
13
+ * To input error detail.
14
+ *
15
+ * @param detail The detail.
16
+ * @returns The to input error detail result.
17
+ */
9
18
  export declare function toInputErrorDetail(detail: InputErrorDetail): HttpExceptionDetail;
10
19
  //# sourceMappingURL=input-error-detail.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-error-detail.d.ts","sourceRoot":"","sources":["../src/input-error-detail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,mBAAmB,CAOhF"}
1
+ {"version":3,"file":"input-error-detail.d.ts","sourceRoot":"","sources":["../src/input-error-detail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,mBAAmB,CAOhF"}
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Describes the input error detail contract.
3
+ */
4
+
5
+ /**
6
+ * To input error detail.
7
+ *
8
+ * @param detail The detail.
9
+ * @returns The to input error detail result.
10
+ */
1
11
  export function toInputErrorDetail(detail) {
2
12
  return {
3
13
  code: detail.code,
@@ -1,3 +1,11 @@
1
1
  import type { InterceptorContext, InterceptorLike } from './types.js';
2
+ /**
3
+ * Run interceptor chain.
4
+ *
5
+ * @param definitions The definitions.
6
+ * @param context The context.
7
+ * @param terminal The terminal.
8
+ * @returns The run interceptor chain result.
9
+ */
2
10
  export declare function runInterceptorChain(definitions: InterceptorLike[], context: InterceptorContext, terminal: () => Promise<unknown>): Promise<unknown>;
3
11
  //# sourceMappingURL=interceptors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,kBAAkB,EAClB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAiBpB,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,eAAe,EAAE,EAC9B,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAelB"}
1
+ {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,kBAAkB,EAClB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAiBpB;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,eAAe,EAAE,EAC9B,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
@@ -7,11 +7,24 @@ async function resolveInterceptor(definition, requestContext) {
7
7
  }
8
8
  return requestContext.container.resolve(definition);
9
9
  }
10
+
11
+ /**
12
+ * Run interceptor chain.
13
+ *
14
+ * @param definitions The definitions.
15
+ * @param context The context.
16
+ * @param terminal The terminal.
17
+ * @returns The run interceptor chain result.
18
+ */
10
19
  export async function runInterceptorChain(definitions, context, terminal) {
20
+ if (definitions.length === 0) {
21
+ return terminal();
22
+ }
11
23
  let next = {
12
24
  handle: terminal
13
25
  };
14
- for (const definition of [...definitions].reverse()) {
26
+ for (let index = definitions.length - 1; index >= 0; index -= 1) {
27
+ const definition = definitions[index];
15
28
  const interceptor = await resolveInterceptor(definition, context.requestContext);
16
29
  const previous = next;
17
30
  next = {
package/dist/mapping.d.ts CHANGED
@@ -2,6 +2,13 @@ import type { HandlerMapping, HandlerSource, VersioningOptions } from './types.j
2
2
  interface CreateHandlerMappingOptions {
3
3
  versioning?: VersioningOptions;
4
4
  }
5
+ /**
6
+ * Create handler mapping.
7
+ *
8
+ * @param sources The sources.
9
+ * @param options The options.
10
+ * @returns The create handler mapping result.
11
+ */
5
12
  export declare function createHandlerMapping(sources: HandlerSource[], options?: CreateHandlerMappingOptions): HandlerMapping;
6
13
  export {};
7
14
  //# sourceMappingURL=mapping.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAIV,cAAc,EAEd,aAAa,EAIb,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAOpB,UAAU,2BAA2B;IACnC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAmQD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,2BAA2B,GAAG,cAAc,CA0DpH"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAIV,cAAc,EAEd,aAAa,EAIb,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAOpB,UAAU,2BAA2B;IACnC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AA6VD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,2BAA2B,GAAG,cAAc,CAuEpH"}
package/dist/mapping.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { getControllerMetadata, getRouteMetadata } from '@fluojs/core/internal';
2
2
  import { getRouteProducesMetadata } from './decorators.js';
3
3
  import { RouteConflictError } from './errors.js';
4
- import { extractRoutePathParams, matchRoutePath, normalizeRoutePath, parseRoutePath } from './route-path.js';
4
+ import { extractRoutePathParams, normalizeRoutePath, parseRoutePath } from './route-path.js';
5
5
  import { VersioningType } from './types.js';
6
6
  function joinPaths(basePath, routePath) {
7
7
  return normalizeRoutePath(`${basePath}/${routePath}`);
@@ -116,19 +116,32 @@ function matchesRouteVersion(descriptor, requestVersion) {
116
116
  function getControllerMethodNames(controllerToken) {
117
117
  return Object.getOwnPropertyNames(controllerToken.prototype).filter(propertyKey => propertyKey !== 'constructor');
118
118
  }
119
- function splitIncomingPathSegments(path) {
120
- return normalizeRoutePath(path).split('/').filter(Boolean);
121
- }
122
119
  function buildDescriptorIndex(descriptors) {
123
- const index = new Map();
120
+ const staticIndex = new Map();
121
+ const paramIndex = new Map();
124
122
  for (const descriptor of descriptors) {
125
123
  const method = descriptor.route.method;
126
124
  const segments = parseRoutePath(descriptor.route.path, `Registered ${descriptor.route.method} route path`);
125
+ if (segments.every(segment => segment.kind === 'literal')) {
126
+ let methodMap = staticIndex.get(method);
127
+ if (!methodMap) {
128
+ methodMap = new Map();
129
+ staticIndex.set(method, methodMap);
130
+ }
131
+ const path = descriptor.route.path;
132
+ const bucket = methodMap.get(path);
133
+ if (bucket) {
134
+ bucket.push(descriptor);
135
+ } else {
136
+ methodMap.set(path, [descriptor]);
137
+ }
138
+ continue;
139
+ }
127
140
  const segmentCount = segments.length;
128
- let methodMap = index.get(method);
141
+ let methodMap = paramIndex.get(method);
129
142
  if (!methodMap) {
130
143
  methodMap = new Map();
131
- index.set(method, methodMap);
144
+ paramIndex.set(method, methodMap);
132
145
  }
133
146
  let bucket = methodMap.get(segmentCount);
134
147
  if (!bucket) {
@@ -140,7 +153,61 @@ function buildDescriptorIndex(descriptors) {
140
153
  segments
141
154
  });
142
155
  }
143
- return index;
156
+ return {
157
+ param: paramIndex,
158
+ static: staticIndex
159
+ };
160
+ }
161
+ function findStaticMatch(descriptorBuckets, requestVersion, versioning) {
162
+ let firstUnversionedMatch;
163
+ for (const descriptors of descriptorBuckets) {
164
+ if (!descriptors || descriptors.length === 0) {
165
+ continue;
166
+ }
167
+ for (const descriptor of descriptors) {
168
+ if (versioning.type === VersioningType.URI) {
169
+ return {
170
+ descriptor,
171
+ params: {}
172
+ };
173
+ }
174
+ if (matchesRouteVersion(descriptor, requestVersion)) {
175
+ return {
176
+ descriptor,
177
+ params: {}
178
+ };
179
+ }
180
+ if (descriptor.route.version === undefined && !firstUnversionedMatch) {
181
+ firstUnversionedMatch = {
182
+ descriptor,
183
+ params: {}
184
+ };
185
+ }
186
+ }
187
+ }
188
+ return firstUnversionedMatch;
189
+ }
190
+ function matchParameterizedRoute(candidate, incomingSegments) {
191
+ const {
192
+ segments
193
+ } = candidate;
194
+ if (segments.length !== incomingSegments.length) {
195
+ return undefined;
196
+ }
197
+ for (let index = 0; index < segments.length; index += 1) {
198
+ const segment = segments[index];
199
+ if (segment.kind === 'literal' && segment.value !== incomingSegments[index]) {
200
+ return undefined;
201
+ }
202
+ }
203
+ const params = {};
204
+ for (let index = 0; index < segments.length; index += 1) {
205
+ const segment = segments[index];
206
+ if (segment.kind === 'param') {
207
+ params[segment.name] = incomingSegments[index];
208
+ }
209
+ }
210
+ return params;
144
211
  }
145
212
  function createHandlerDescriptors(source, versioning) {
146
213
  const controllerMetadata = getControllerMetadata(source.controllerToken) ?? {
@@ -194,6 +261,14 @@ function buildDescriptorList(sources, versioning) {
194
261
  }
195
262
  return descriptors;
196
263
  }
264
+
265
+ /**
266
+ * Create handler mapping.
267
+ *
268
+ * @param sources The sources.
269
+ * @param options The options.
270
+ * @returns The create handler mapping result.
271
+ */
197
272
  export function createHandlerMapping(sources, options) {
198
273
  const versioning = resolveVersioning(options);
199
274
  const descriptors = buildDescriptorList(sources, versioning);
@@ -203,11 +278,18 @@ export function createHandlerMapping(sources, options) {
203
278
  match(request) {
204
279
  const method = request.method.toUpperCase();
205
280
  const requestVersion = versioning.type === VersioningType.URI ? undefined : resolveRequestVersion(request, versioning);
206
- const incomingSegments = splitIncomingPathSegments(request.path);
207
- const candidates = [...(descriptorIndex.get(method)?.get(incomingSegments.length) ?? []), ...(descriptorIndex.get('ALL')?.get(incomingSegments.length) ?? [])];
281
+ const normalizedPath = normalizeRoutePath(request.path);
282
+ const methodStaticDescriptors = descriptorIndex.static.get(method)?.get(normalizedPath);
283
+ const allStaticDescriptors = descriptorIndex.static.get('ALL')?.get(normalizedPath);
284
+ const directStaticMatch = findStaticMatch([methodStaticDescriptors, allStaticDescriptors], requestVersion, versioning);
285
+ if (directStaticMatch) {
286
+ return directStaticMatch;
287
+ }
288
+ const incomingSegments = normalizedPath.split('/').filter(Boolean);
289
+ const candidates = [...(descriptorIndex.param.get(method)?.get(incomingSegments.length) ?? []), ...(descriptorIndex.param.get('ALL')?.get(incomingSegments.length) ?? [])];
208
290
  let firstUnversionedMatch;
209
291
  for (const candidate of candidates) {
210
- const params = matchRoutePath(candidate.segments, incomingSegments);
292
+ const params = matchParameterizedRoute(candidate, incomingSegments);
211
293
  if (!params) {
212
294
  continue;
213
295
  }
@@ -1,3 +1,8 @@
1
1
  import type { Middleware } from '../types.js';
2
+ /**
3
+ * Create correlation middleware.
4
+ *
5
+ * @returns The create correlation middleware result.
6
+ */
2
7
  export declare function createCorrelationMiddleware(): Middleware;
3
8
  //# sourceMappingURL=correlation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAY9C,wBAAgB,2BAA2B,IAAI,UAAU,CAYxD"}
1
+ {"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAY9C;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,UAAU,CAYxD"}
@@ -6,6 +6,12 @@ function resolveInboundRequestId(headers) {
6
6
  const value = Array.isArray(requestId) ? requestId[0] : requestId;
7
7
  return value ?? randomUUID();
8
8
  }
9
+
10
+ /**
11
+ * Create correlation middleware.
12
+ *
13
+ * @returns The create correlation middleware result.
14
+ */
9
15
  export function createCorrelationMiddleware() {
10
16
  return {
11
17
  async handle(context, next) {
@@ -1,4 +1,7 @@
1
1
  import type { Middleware } from '../types.js';
2
+ /**
3
+ * Describes the cors options contract.
4
+ */
2
5
  export interface CorsOptions {
3
6
  allowCredentials?: boolean;
4
7
  allowHeaders?: string[];
@@ -7,5 +10,11 @@ export interface CorsOptions {
7
10
  exposeHeaders?: string[];
8
11
  maxAge?: number;
9
12
  }
13
+ /**
14
+ * Create cors middleware.
15
+ *
16
+ * @param options The options.
17
+ * @returns The create cors middleware result.
18
+ */
10
19
  export declare function createCorsMiddleware(options?: CorsOptions): Middleware;
11
20
  //# sourceMappingURL=cors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;IACvF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,WAAgB,GAAG,UAAU,CA0D1E"}
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;IACvF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,WAAgB,GAAG,UAAU,CA0D1E"}
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Describes the cors options contract.
3
+ */
4
+
1
5
  function resolveOrigin(options, requestOrigin) {
2
6
  if (typeof options.allowOrigin === 'function') {
3
7
  return options.allowOrigin(requestOrigin);
@@ -15,6 +19,13 @@ function setHeaderIfValue(response, name, value) {
15
19
  response.setHeader(name, value);
16
20
  }
17
21
  }
22
+
23
+ /**
24
+ * Create cors middleware.
25
+ *
26
+ * @param options The options.
27
+ * @returns The create cors middleware result.
28
+ */
18
29
  export function createCorsMiddleware(options = {}) {
19
30
  if (options.allowCredentials === true) {
20
31
  if (options.allowOrigin === '*' || options.allowOrigin === undefined) {
@@ -1,8 +1,42 @@
1
1
  import type { Constructor } from '@fluojs/core';
2
2
  import type { Middleware, MiddlewareContext, MiddlewareLike, MiddlewareRouteConfig, Next } from '../types.js';
3
+ /**
4
+ * Is middleware route config.
5
+ *
6
+ * @param value The value.
7
+ * @returns The is middleware route config result.
8
+ */
3
9
  export declare function isMiddlewareRouteConfig(value: MiddlewareLike): value is MiddlewareRouteConfig;
10
+ /**
11
+ * Normalize route pattern.
12
+ *
13
+ * @param path The path.
14
+ * @returns The normalize route pattern result.
15
+ */
4
16
  export declare function normalizeRoutePattern(path: string): string;
17
+ /**
18
+ * Match route pattern.
19
+ *
20
+ * @param pattern The pattern.
21
+ * @param path The path.
22
+ * @returns The match route pattern result.
23
+ */
5
24
  export declare function matchRoutePattern(pattern: string, path: string): boolean;
25
+ /**
26
+ * For routes.
27
+ *
28
+ * @param middlewareClass The middleware class.
29
+ * @param routes The routes.
30
+ * @returns The for routes result.
31
+ */
6
32
  export declare function forRoutes<T extends Constructor<Middleware>>(middlewareClass: T, ...routes: string[]): MiddlewareRouteConfig;
33
+ /**
34
+ * Run middleware chain.
35
+ *
36
+ * @param definitions The definitions.
37
+ * @param context The context.
38
+ * @param terminal The terminal.
39
+ * @returns The run middleware chain result.
40
+ */
7
41
  export declare function runMiddlewareChain(definitions: MiddlewareLike[], context: MiddlewareContext, terminal: Next): Promise<void>;
8
42
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,cAAc,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,IAAI,EAAkB,MAAM,aAAa,CAAC;AAM9H,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,qBAAqB,CAE7F;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAUxE;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,EACzD,eAAe,EAAE,CAAC,EAClB,GAAG,MAAM,EAAE,MAAM,EAAE,GAClB,qBAAqB,CAEvB;AA2CD,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,IAAI,GACb,OAAO,CAAC,IAAI,CAAC,CAUf"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,cAAc,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,IAAI,EAAkB,MAAM,aAAa,CAAC;AAM9H;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,qBAAqB,CAE7F;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAUxE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,EACzD,eAAe,EAAE,CAAC,EAClB,GAAG,MAAM,EAAE,MAAM,EAAE,GAClB,qBAAqB,CAEvB;AA2CD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,IAAI,GACb,OAAO,CAAC,IAAI,CAAC,CAqBf"}