@bymax-one/nest-core 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nestjs_common from '@nestjs/common';
2
- import { DynamicModule, ExceptionFilter, ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
2
+ import { NestModule, MiddlewareConsumer, DynamicModule, ExceptionFilter, ArgumentsHost, NestInterceptor, ExecutionContext, CallHandler, NestMiddleware } from '@nestjs/common';
3
3
  import { HttpAdapterHost } from '@nestjs/core';
4
4
  import { Observable } from 'rxjs';
5
5
 
@@ -68,6 +68,59 @@ interface OpenApiServerDescriptor {
68
68
  * so the consumer's declaration reaches the UI unchanged.
69
69
  */
70
70
  type OpenApiSecurityScheme = Readonly<Record<string, unknown>>;
71
+ /**
72
+ * One security requirement: scheme name to the scopes it needs, empty for a
73
+ * scheme that takes none. An operation's requirements are alternatives — any
74
+ * one of them satisfies it — so an empty *array* of requirements means the
75
+ * operation needs no authentication at all, which is how the specification
76
+ * expresses a public route that overrides a document-level default.
77
+ */
78
+ type OpenApiSecurityRequirement = Readonly<Record<string, readonly string[]>>;
79
+ /** The HTTP methods an OpenAPI path item can carry an operation under. */
80
+ type OpenApiHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE';
81
+ /**
82
+ * Addresses one operation in the generated document, as `"<METHOD> <path>"`.
83
+ *
84
+ * This format is a documented contract, not an implementation detail: a sibling
85
+ * library may ship a plain-data map of its own operations keyed this way, so a
86
+ * consumer spreads it into {@link OpenApiOptions.operationSecurity} instead of
87
+ * restating which of that library's routes are public. Import the type to get
88
+ * that map checked at the library's own compile time.
89
+ *
90
+ * The method is uppercase, one space separates the two parts, and the path is
91
+ * written **exactly as it appears in the generated document**: leading slash,
92
+ * OpenAPI template braces (`/users/{id}`), no trailing slash, and including any
93
+ * global prefix the application sets. That last part is the one that surprises:
94
+ * `@nestjs/swagger` includes `app.setGlobalPrefix('api')` in the documented
95
+ * paths, so the key is `'POST /api/auth/login'` in an application that sets one.
96
+ * A library shipping such a map should therefore expose a *function* taking the
97
+ * prefix rather than a frozen constant — the call site is the only place that
98
+ * knows it.
99
+ *
100
+ * @example 'GET /users/{id}'
101
+ * @example 'POST /api/auth/login'
102
+ */
103
+ type OpenApiOperationKey = `${OpenApiHttpMethod} /${string}`;
104
+ /**
105
+ * Per-operation security requirements, keyed by {@link OpenApiOperationKey}.
106
+ * An empty array marks the operation public, overriding any document default.
107
+ */
108
+ type OperationSecurityMap = Readonly<Record<OpenApiOperationKey, readonly OpenApiSecurityRequirement[]>>;
109
+ /**
110
+ * Names the operation a route handler produced, in the generated document.
111
+ *
112
+ * Matches `@nestjs/swagger`'s own factory signature so a consumer's existing one
113
+ * can be handed over unchanged. This package installs a factory of its own to
114
+ * learn which handler produced which operation — a contract a library keys its
115
+ * contributed fragments against — and delegates the id string to this one when
116
+ * it is set, so nothing an application already generates is renamed.
117
+ *
118
+ * @param controllerKey - The controller class name.
119
+ * @param methodKey - The handler method name.
120
+ * @param version - The route's version, when the application versions routes.
121
+ * @returns The operation id to publish.
122
+ */
123
+ type OpenApiOperationIdFactory = (controllerKey: string, methodKey: string, version?: string) => string;
71
124
  /**
72
125
  * OpenAPI document configuration.
73
126
  *
@@ -96,10 +149,63 @@ interface OpenApiOptions {
96
149
  servers?: readonly OpenApiServerDescriptor[];
97
150
  /** Security schemes added to the document's components. Default: `{}`. */
98
151
  securitySchemes?: Readonly<Record<string, OpenApiSecurityScheme>>;
152
+ /**
153
+ * The requirement every operation carries unless it says otherwise, naming
154
+ * schemes declared in {@link OpenApiOptions.securitySchemes}. Default: `[]`,
155
+ * which documents nothing and leaves every operation as it was generated.
156
+ *
157
+ * Set this when most of the API is authenticated, and mark the exceptions
158
+ * public through {@link OpenApiOptions.operationSecurity}. An operation that
159
+ * already declares its own requirement is never overwritten.
160
+ *
161
+ * @example [{ cookieAuth: [] }]
162
+ */
163
+ security?: readonly OpenApiSecurityRequirement[];
164
+ /**
165
+ * Per-operation overrides of {@link OpenApiOptions.security}, keyed by
166
+ * {@link OpenApiOperationKey}. An empty array marks that operation public.
167
+ * Default: `{}`.
168
+ *
169
+ * A key matching no operation in the generated document is a configuration
170
+ * error and fails the document build, naming the keys that do exist. Silence
171
+ * would be worse: a route renamed out from under a stale key would quietly
172
+ * inherit the document default and be documented as authenticated when it is
173
+ * not, or the reverse.
174
+ *
175
+ * That check runs only when the document is built. With
176
+ * {@link OpenApiOptions.enabled} false, or in a production runtime where the
177
+ * feature is forced off, a stale key is not reported — refusing to boot a
178
+ * service over a documentation setting it never serves would be the wrong
179
+ * trade. The cost is that the error waits for an environment that has the
180
+ * document switched on.
181
+ *
182
+ * @example
183
+ * {
184
+ * 'POST /auth/login': [],
185
+ * 'POST /auth/refresh': [{ refreshCookie: [] }]
186
+ * }
187
+ */
188
+ operationSecurity?: OperationSecurityMap;
189
+ /**
190
+ * Name the operations in the generated document. Default: the format
191
+ * `@nestjs/swagger` itself produces, `<ControllerKey>_<methodKey>`.
192
+ *
193
+ * Set it to control the ids a client generator will use. This package always
194
+ * installs a factory of its own so it can learn which handler produced which
195
+ * operation, and delegates to this one when it is set — so supplying it
196
+ * changes the published ids, and leaving it unset changes nothing.
197
+ */
198
+ operationIdFactory?: OpenApiOperationIdFactory;
99
199
  /**
100
200
  * Contribute the schemas this package owns — the error envelope, the health
101
- * response, and the pagination shapes — to the document's components.
102
- * Default: `true`.
201
+ * response, and the pagination shapes — to the document's components, and
202
+ * reference them from the operations that return them: the error envelope as
203
+ * every operation's `default` response, and the health response on the health
204
+ * endpoints this package registers. Default: `true`.
205
+ *
206
+ * The two halves are one switch because they are one decision. Referencing a
207
+ * schema this package did not contribute would leave a dangling `$ref`, and a
208
+ * document that resolves nowhere is worse than one that says less.
103
209
  */
104
210
  includeCoreSchemas?: boolean;
105
211
  }
@@ -221,6 +327,9 @@ interface ResolvedOpenApiOptions {
221
327
  version: string;
222
328
  servers: readonly OpenApiServerDescriptor[];
223
329
  securitySchemes: Readonly<Record<string, OpenApiSecurityScheme>>;
330
+ security: readonly OpenApiSecurityRequirement[];
331
+ operationSecurity: OperationSecurityMap;
332
+ operationIdFactory?: OpenApiOperationIdFactory;
224
333
  includeCoreSchemas: boolean;
225
334
  }
226
335
  /**
@@ -255,7 +364,69 @@ declare const ASYNC_OPTIONS_TYPE: _nestjs_common.ConfigurableModuleAsyncOptions<
255
364
  /**
256
365
  * `BymaxCoreModule`, the application foundation module for NestJS 11.
257
366
  */
258
- declare class BymaxCoreModule extends BymaxCoreModuleBase {
367
+ declare class BymaxCoreModule extends BymaxCoreModuleBase implements NestModule {
368
+ private readonly resolved;
369
+ private readonly adapterHost?;
370
+ /**
371
+ * @param options - The resolved snapshot, read to decide whether the timing
372
+ * middleware is applied at all.
373
+ */
374
+ constructor(resolved: ResolvedCoreOptions, adapterHost?: HttpAdapterHost | undefined);
375
+ /**
376
+ * Apply the request-timing middleware to every route.
377
+ *
378
+ * Middleware rather than the interceptor this replaced, because guards run
379
+ * before interceptors: a request rejected by an authentication, authorization
380
+ * or throttling guard never reached the interceptor, and one matching no
381
+ * route never reached a controller at all. A deployment could therefore be
382
+ * under a credential-stuffing run — a flood of 401s — with a flat error
383
+ * graph, which is why this is a security fix rather than a metrics
384
+ * improvement.
385
+ *
386
+ * Applied on both registration paths, and only when timing is enabled: the
387
+ * middleware is the sole recorder now, since a second one would count every
388
+ * matched request twice.
389
+ *
390
+ * There is no single pattern that covers both adapters, which is the whole
391
+ * reason this reads the adapter first. Measured, requesting the root, a
392
+ * parameterised route, a nested path and an unmatched path, with and without
393
+ * `setGlobalPrefix('api')`:
394
+ *
395
+ * | `forRoutes(...)` | Express | Fastify |
396
+ * | ---------------- | ---------------- | -------------------- |
397
+ * | `'*splat'` | skips the root | — |
398
+ * | `'{*splat}'` | skips `/api` | every path |
399
+ * | `'/'` | every path | matches `/` only |
400
+ *
401
+ * On Express `'/'` is a mount and matches everything beneath whatever prefix
402
+ * it is scoped to, while `'{*splat}'` — the form Nest 11's migration guide
403
+ * prescribes for "all routes" — stops matching the prefixed root once an
404
+ * application calls `setGlobalPrefix`. That was reported as nest#14520 and
405
+ * fixed by nest#14522, whose regression test covers Fastify; on
406
+ * `@nestjs/core` 11.1.28 with the Express adapter the prefixed root still
407
+ * reaches no middleware while resolving to `200`.
408
+ *
409
+ * On Fastify the same `'/'` is an exact match rather than a mount — one of
410
+ * three requests reached the middleware — so the wildcard is the only form
411
+ * that works there.
412
+ *
413
+ * A recorder that quietly omits one route is the same class of defect this
414
+ * middleware exists to fix, so each adapter gets the form that omits none.
415
+ *
416
+ * Fastify also needs {@link bridgeFastifyRouteMetadata}, because middie hands
417
+ * middleware the raw request, which carries no route metadata at all; see
418
+ * that file for why the label would otherwise be `<unmatched>` for every
419
+ * request.
420
+ *
421
+ * One limit stays and is documented in the README: Nest scopes module
422
+ * middleware to the global prefix, so with `setGlobalPrefix('api')` a request
423
+ * to `/nope` — outside the prefix entirely — reaches no middleware and is not
424
+ * recorded, while `/api/nope` is. No `forRoutes` argument changes that, and
425
+ * nothing this module can register reaches outside its own scope.
426
+ *
427
+ * @param consumer - Nest's middleware consumer.
428
+ */
429
+ configure(consumer: MiddlewareConsumer): void;
259
430
  /**
260
431
  * Register the module synchronously. Options are known now, so disabled
261
432
  * features are omitted from the providers and controllers arrays and the
@@ -345,7 +516,7 @@ declare const BYMAX_CORE_OPTIONS: unique symbol;
345
516
  */
346
517
  declare const BYMAX_CORRELATION_PROVIDER: unique symbol;
347
518
  /**
348
- * Provide the `ITimingSink` that receives one sample per completed request.
519
+ * Provide the `ITimingSink` that receives one sample per closed request.
349
520
  * Defaults to a no-op sink.
350
521
  */
351
522
  declare const BYMAX_TIMING_SINK: unique symbol;
@@ -662,9 +833,11 @@ interface MonotonicClock {
662
833
  }
663
834
 
664
835
  /**
665
- * @fileoverview Request-timing contracts. The timing interceptor emits one
666
- * {@link RequestTimingSample} per completed request to the bound
667
- * {@link ITimingSink}. The default sink is a no-op; consumers plug in a logger
836
+ * @fileoverview Request-timing contracts. `BymaxTimingMiddleware` emits one
837
+ * {@link RequestTimingSample} per **closed** request to the bound
838
+ * {@link ITimingSink} every request the server finished with, including the
839
+ * ones a guard rejected, the ones that matched no route, and the ones a client
840
+ * abandoned mid-flight. The default sink is a no-op; consumers plug in a logger
668
841
  * bridge or the metrics bridge through the `BYMAX_TIMING_SINK` token.
669
842
  * @layer Contract
670
843
  */
@@ -694,12 +867,16 @@ interface RequestTimingSample {
694
867
  }
695
868
  /**
696
869
  * Receive request-timing samples. Implementations must never throw: a sink
697
- * failure is caught and silenced by the interceptor so timing never breaks a
870
+ * failure is caught and silenced by the recorder so timing never breaks a
698
871
  * request.
699
872
  */
700
873
  interface ITimingSink {
701
874
  /**
702
- * Record one sample for a completed request.
875
+ * Record one sample for a closed request, however it ended.
876
+ *
877
+ * Called once per request the server closed — not only the ones a handler
878
+ * answered. A rejection issued by a guard, a request matching no route, and a
879
+ * client that hung up mid-response all arrive here.
703
880
  *
704
881
  * @param sample - The timing sample to record.
705
882
  */
@@ -707,10 +884,15 @@ interface ITimingSink {
707
884
  }
708
885
 
709
886
  /**
710
- * Request-timing interceptor. Registered as the `APP_INTERCEPTOR` when the
711
- * timing feature is enabled, on both the sync and async registration paths.
712
- * Non-HTTP execution contexts (GraphQL, RPC) pass through untouched: this
713
- * feature is HTTP-first, matching the exception filter's documented scope.
887
+ * Request-timing interceptor. No longer registered by `BymaxCoreModule`, which
888
+ * records through {@link BymaxTimingMiddleware} instead so that requests ended
889
+ * by a guard or by no route matching are counted too. Non-HTTP execution
890
+ * contexts (GraphQL, RPC) pass through untouched: this feature is HTTP-first,
891
+ * matching the exception filter's documented scope.
892
+ *
893
+ * @deprecated Since 1.4.0, superseded by `BymaxTimingMiddleware`, which the
894
+ * module registers automatically. Registering this interceptor as well
895
+ * records a second sample for every request that reaches a handler.
714
896
  */
715
897
  declare class TimingInterceptor implements NestInterceptor {
716
898
  private readonly options;
@@ -759,9 +941,9 @@ declare class TimingInterceptor implements NestInterceptor {
759
941
  */
760
942
  private readErrorStatus;
761
943
  /**
762
- * Build the sample, compute the slow flag, and deliver it to the sink inside
763
- * a try/catch that silences any failure: a throwing sink must never affect
764
- * the request it is observing.
944
+ * Build the sample and deliver it to the sink inside a try/catch that
945
+ * silences any failure: a throwing sink must never affect the request it is
946
+ * observing.
765
947
  *
766
948
  * @param method - HTTP method of the request.
767
949
  * @param route - Route template of the request.
@@ -771,6 +953,133 @@ declare class TimingInterceptor implements NestInterceptor {
771
953
  private recordSample;
772
954
  }
773
955
 
956
+ /**
957
+ * @fileoverview Neutral request-info accessor for request timing. Reads the
958
+ * HTTP method and the route template off a request without assuming Express or
959
+ * Fastify, so `RequestTimingSample.route` always carries a bounded-cardinality
960
+ * label instead of the raw URL.
961
+ *
962
+ * The bound is a security property, not a tidiness one. Requests that match no
963
+ * route are exactly the ones a scanner produces, each at a different path, so a
964
+ * label taken from the URL would mint one time series per probe — turning the
965
+ * scrape endpoint into the most expensive route in the service and the metric
966
+ * into the outage. Every unmatched request therefore shares one label.
967
+ *
968
+ * Dropping the raw-URL fallback bought a **second** guarantee that is worth
969
+ * stating because it was a side effect rather than the intent, and anyone
970
+ * weighing the fallback again would otherwise only re-weigh the cardinality
971
+ * argument. The recorder is middleware mounted at `'/'`, and Express gives
972
+ * mounted middleware a `req.url` relative to its mount point: under
973
+ * `setGlobalPrefix('api')` a request to `/api` arrives as `/`, so a path read
974
+ * there reports somewhere the caller never asked for. Nothing in this file
975
+ * reads `req.url` any more — the only `.url` left is Fastify's
976
+ * `routeOptions.url`, which is a template, not a path — so that class of bug
977
+ * has nowhere to land. Reintroducing a path-derived label brings both problems
978
+ * back, not just the cardinality one. If a raw path is ever genuinely needed,
979
+ * the correct read is `req.originalUrl ?? req.url`: `originalUrl` is Express's
980
+ * and carries the mount prefix, and the `??` covers an adapter that supplies
981
+ * only `url`, where no mount trimmed it in the first place.
982
+ * @layer Utility
983
+ */
984
+
985
+ /**
986
+ * The route label carried by every request that matched no route.
987
+ *
988
+ * A single constant rather than the request's own path, and exported rather
989
+ * than inlined: it is the value an alert rule matches on to see a scan, so it
990
+ * belongs to the contract and must not drift from what this package writes.
991
+ * Reading `route="<unmatched>"` in a dashboard says what happened; an empty
992
+ * label — which Prometheus treats as equivalent to no label at all — reads as
993
+ * missing data and gets scrolled past, which for a signal whose purpose is to
994
+ * be noticed is the same as not emitting it.
995
+ */
996
+ declare const UNMATCHED_ROUTE = "<unmatched>";
997
+ /** Structural shape of an Express request's route metadata. */
998
+ interface ExpressRouteShape {
999
+ route?: {
1000
+ path?: string;
1001
+ };
1002
+ baseUrl?: string;
1003
+ }
1004
+ /** Structural shape of a Fastify request's route metadata. */
1005
+ interface FastifyRouteShape {
1006
+ routeOptions?: {
1007
+ url?: string;
1008
+ };
1009
+ }
1010
+ /** Structural shape shared by both frameworks for the method. */
1011
+ interface RawRequestShape {
1012
+ method?: string;
1013
+ }
1014
+ /** The combined structural shape read off the request object. */
1015
+ type RequestShape = ExpressRouteShape & FastifyRouteShape & RawRequestShape;
1016
+
1017
+ /** The part of a response this middleware reads and listens on. */
1018
+ interface ResponseShape {
1019
+ /** Node's event emitter, used for the single `'close'` subscription. */
1020
+ on(event: 'close', listener: () => void): unknown;
1021
+ /**
1022
+ * Final status code. Optional and explicitly nullable: a connection can close
1023
+ * before anything settled one, and that case has to be expressible rather
1024
+ * than assumed away.
1025
+ */
1026
+ statusCode?: number | undefined;
1027
+ }
1028
+ /**
1029
+ * Records one timing sample per request, whatever ended it.
1030
+ *
1031
+ * Registered by `BymaxCoreModule` for every route when the timing feature is
1032
+ * enabled. It replaces the interceptor as the recorder rather than joining it:
1033
+ * two recorders would count every matched request twice, which is a worse
1034
+ * defect than the one being fixed because it is silent and plausible.
1035
+ */
1036
+ declare class BymaxTimingMiddleware implements NestMiddleware {
1037
+ private readonly options;
1038
+ private readonly clock;
1039
+ /** The bound sink, or an in-code no-op when nothing is bound. */
1040
+ private readonly sink;
1041
+ /** The bound trace reader, or an in-code no-op when nothing is bound. */
1042
+ private readonly traceContext;
1043
+ /**
1044
+ * @param options - The resolved options, read for the slow-request threshold.
1045
+ * @param sink - The bound timing sink; its failures are swallowed, because a
1046
+ * throwing sink must never affect the request it is observing.
1047
+ * @param clock - Monotonic clock seam, so a test advances time by controlled
1048
+ * amounts instead of sleeping.
1049
+ * @param traceContext - Reads the active span's identifiers. Optional: the
1050
+ * middleware stays constructible on its own, and a no-op resolves nothing.
1051
+ */
1052
+ constructor(options: ResolvedCoreOptions, sink: ITimingSink | undefined, clock?: MonotonicClock, traceContext?: ITraceContextProvider);
1053
+ /**
1054
+ * Start the measurement and arrange for the sample to be recorded once the
1055
+ * connection closes, then hand the request straight on.
1056
+ *
1057
+ * The route is read inside the listener rather than here: at middleware time
1058
+ * the router has not matched yet, so `req.route` is still empty. By the time
1059
+ * the connection closes it is populated — including for a request a guard
1060
+ * rejected, since matching happens before guards run.
1061
+ *
1062
+ * The trace lookup is tried in the live context first and in this moment's
1063
+ * captured context second; see this file's header for the measurements that
1064
+ * decided that order.
1065
+ *
1066
+ * @param request - The framework request object.
1067
+ * @param response - The framework response object.
1068
+ * @param next - Continues the chain; called synchronously and unconditionally.
1069
+ */
1070
+ use(request: RequestShape, response: ResponseShape, next: () => void): void;
1071
+ /**
1072
+ * Build the sample and hand it to the sink, guarding both steps.
1073
+ *
1074
+ * @param request - The framework request object.
1075
+ * @param response - The framework response object.
1076
+ * @param start - Monotonic timestamp captured before the chain ran.
1077
+ * @param trace - The span identifiers already resolved by the caller, which
1078
+ * owns the choice of which context to read them from.
1079
+ */
1080
+ private record;
1081
+ }
1082
+
774
1083
  /**
775
1084
  * @fileoverview Stable `BYMAX_*` error-code catalog and HTTP-status derivation.
776
1085
  * These codes are the machine-readable half of the error envelope contract and
@@ -824,4 +1133,4 @@ declare const BYMAX_GATEWAY_TIMEOUT = "BYMAX_GATEWAY_TIMEOUT";
824
1133
  */
825
1134
  declare function codeForStatus(status: number): string;
826
1135
 
827
- export { BYMAX_BAD_GATEWAY, BYMAX_BAD_REQUEST, BYMAX_CLIENT_ERROR, BYMAX_CONFLICT, BYMAX_CORE_OPTIONS, BYMAX_CORRELATION_PROVIDER, BYMAX_FORBIDDEN, BYMAX_GATEWAY_TIMEOUT, BYMAX_HEALTH_INDICATORS, BYMAX_INTERNAL_ERROR, BYMAX_METRICS_REGISTRY, BYMAX_NOT_FOUND, BYMAX_NOT_IMPLEMENTED, BYMAX_PAYLOAD_TOO_LARGE, BYMAX_SERVICE_UNAVAILABLE, BYMAX_TIMING_SINK, BYMAX_TOO_MANY_REQUESTS, BYMAX_TRACE_CONTEXT, BYMAX_UNAUTHORIZED, BYMAX_UNPROCESSABLE_ENTITY, BYMAX_UNSUPPORTED_MEDIA_TYPE, BYMAX_VALIDATION_FAILED, type BuildErrorEnvelopeInput, BymaxCoreModule, type BymaxCoreModuleOptions, BymaxExceptionFilter, type EnvelopeOptions, type ErrorDetails, type ErrorEnvelope, type FilterErrorContext, type HealthOptions, type ICorrelationIdProvider, type ITimingSink, type ITraceContextProvider, type MetricsOptions, type OpenApiOptions, type OpenApiSecurityScheme, type OpenApiServerDescriptor, type RequestTimingSample, type ResolvedCoreOptions, type TelemetryOptions, TimingInterceptor, type TimingOptions, type TraceContext, buildErrorEnvelope, codeForStatus };
1136
+ export { BYMAX_BAD_GATEWAY, BYMAX_BAD_REQUEST, BYMAX_CLIENT_ERROR, BYMAX_CONFLICT, BYMAX_CORE_OPTIONS, BYMAX_CORRELATION_PROVIDER, BYMAX_FORBIDDEN, BYMAX_GATEWAY_TIMEOUT, BYMAX_HEALTH_INDICATORS, BYMAX_INTERNAL_ERROR, BYMAX_METRICS_REGISTRY, BYMAX_NOT_FOUND, BYMAX_NOT_IMPLEMENTED, BYMAX_PAYLOAD_TOO_LARGE, BYMAX_SERVICE_UNAVAILABLE, BYMAX_TIMING_SINK, BYMAX_TOO_MANY_REQUESTS, BYMAX_TRACE_CONTEXT, BYMAX_UNAUTHORIZED, BYMAX_UNPROCESSABLE_ENTITY, BYMAX_UNSUPPORTED_MEDIA_TYPE, BYMAX_VALIDATION_FAILED, type BuildErrorEnvelopeInput, BymaxCoreModule, type BymaxCoreModuleOptions, BymaxExceptionFilter, BymaxTimingMiddleware, type EnvelopeOptions, type ErrorDetails, type ErrorEnvelope, type FilterErrorContext, type HealthOptions, type ICorrelationIdProvider, type ITimingSink, type ITraceContextProvider, type MetricsOptions, type OpenApiHttpMethod, type OpenApiOperationIdFactory, type OpenApiOperationKey, type OpenApiOptions, type OpenApiSecurityRequirement, type OpenApiSecurityScheme, type OpenApiServerDescriptor, type OperationSecurityMap, type RequestTimingSample, type ResolvedCoreOptions, type TelemetryOptions, TimingInterceptor, type TimingOptions, type TraceContext, UNMATCHED_ROUTE, buildErrorEnvelope, codeForStatus };