@dunx/http 3.0.0 → 3.0.2

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.
@@ -0,0 +1,108 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __name = (target, name) => {
6
+ Object.defineProperty(target, "name", {
7
+ value: name,
8
+ enumerable: false,
9
+ configurable: true
10
+ });
11
+ return target;
12
+ };
13
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
14
+ var __typeError = (msg) => {
15
+ throw TypeError(msg);
16
+ };
17
+ var __defNormalProp = (obj, key, value) => (key in obj) ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
18
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
19
+ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
20
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
21
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
22
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
23
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
24
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
25
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
26
+ var __expectFn = (fn) => fn !== undefined && typeof fn !== "function" ? __typeError("Function expected") : fn;
27
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({
28
+ kind: __decoratorStrings[kind],
29
+ name,
30
+ metadata,
31
+ addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null))
32
+ });
33
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
34
+ var __runInitializers = (array, flags, self, value) => {
35
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length;i < n; i++)
36
+ flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
37
+ return value;
38
+ };
39
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
40
+ var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
41
+ var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
42
+ var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
43
+ var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : {
44
+ get [name]() {
45
+ return __privateGet(this, extra);
46
+ },
47
+ set [name](x) {
48
+ __privateSet(this, extra, x);
49
+ }
50
+ }, name));
51
+ k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
52
+ for (var i = decorators.length - 1;i >= 0; i--) {
53
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
54
+ if (k) {
55
+ ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => (name in x) };
56
+ if (k ^ 3)
57
+ access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
58
+ if (k > 2)
59
+ access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
60
+ }
61
+ it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? undefined : { get: desc.get, set: desc.set } : target, ctx);
62
+ done._ = 1;
63
+ if (k ^ 4 || it === undefined)
64
+ __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
65
+ else if (typeof it !== "object" || it === null)
66
+ __typeError("Object expected");
67
+ else
68
+ __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
69
+ }
70
+ return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
71
+ };
72
+
73
+ // src/server/status.ts
74
+ var HttpStatusCode = Object.freeze({
75
+ OK: 200,
76
+ CREATED: 201,
77
+ ACCEPTED: 202,
78
+ NO_CONTENT: 204,
79
+ MOVED_PERMANENTLY: 301,
80
+ FOUND: 302,
81
+ NOT_MODIFIED: 304,
82
+ TEMPORARY_REDIRECT: 307,
83
+ PERMANENT_REDIRECT: 308,
84
+ BAD_REQUEST: 400,
85
+ UNAUTHORIZED: 401,
86
+ PAYMENT_REQUIRED: 402,
87
+ FORBIDDEN: 403,
88
+ NOT_FOUND: 404,
89
+ METHOD_NOT_ALLOWED: 405,
90
+ NOT_ACCEPTABLE: 406,
91
+ REQUEST_TIMEOUT: 408,
92
+ CONFLICT: 409,
93
+ GONE: 410,
94
+ PRECONDITION_FAILED: 412,
95
+ PAYLOAD_TOO_LARGE: 413,
96
+ URI_TOO_LONG: 414,
97
+ UNSUPPORTED_MEDIA_TYPE: 415,
98
+ IM_A_TEAPOT: 418,
99
+ UNPROCESSABLE_ENTITY: 422,
100
+ TOO_MANY_REQUESTS: 429,
101
+ INTERNAL_SERVER_ERROR: 500,
102
+ NOT_IMPLEMENTED: 501,
103
+ BAD_GATEWAY: 502,
104
+ SERVICE_UNAVAILABLE: 503,
105
+ GATEWAY_TIMEOUT: 504
106
+ });
107
+
108
+ export { __privateGet, __privateAdd, __decoratorStart, __decoratorMetadata, __runInitializers, __decorateElement, HttpStatusCode };
@@ -1,4 +1,4 @@
1
- import { type Deps, type DynamicModule, type FactoryProvider, type Token } from '@dunx/core';
1
+ import { type Deps, type DynamicModule, type AsyncModuleConfig, type Token } from '@dunx/core';
2
2
  import { type HttpClientOptionsInit } from './options.js';
3
3
  import { HttpService } from './service.js';
4
4
  /**
@@ -57,5 +57,5 @@ export declare class HttpModule {
57
57
  * token has to exist before the factory runs.
58
58
  */
59
59
  static forRootAsync(load: () => HttpClientOptionsInit | Promise<HttpClientOptionsInit>, name?: string): DynamicModule;
60
- static forRootAsync<const D extends Deps>(config: FactoryProvider<HttpClientOptionsInit, D>, name?: string): DynamicModule;
60
+ static forRootAsync<const D extends Deps>(config: AsyncModuleConfig<HttpClientOptionsInit, D>, name?: string): DynamicModule;
61
61
  }
package/dist/client.d.ts CHANGED
@@ -10,10 +10,3 @@ export { DEFAULT_REQUEST_ID_HEADER, HttpClientOptions, type HttpClientOptionsIni
10
10
  export type { BackoffOptions, RetryOptions } from './client/retry.js';
11
11
  export { httpClient, HttpModule } from './client/module.js';
12
12
  export { HttpService, type HeaderFactory, type RequestConfig, type RequestMethod, } from './client/service.js';
13
- /**
14
- * The client's own plumbing, still reachable here and moving out in 4.0.
15
- * Import it from `@dunx/http/internal`, which carries no stability promise.
16
- *
17
- * @deprecated Import from `@dunx/http/internal`. Removed in 4.0.
18
- */
19
- export { backoffDelay, executeWithRetry, isJsonBody, isPlainObject, isRetryableStatus, retryAfterMs, safeStringify, } from './internal.js';
package/dist/client.js CHANGED
@@ -6,14 +6,11 @@ import {
6
6
  import {
7
7
  FetchError,
8
8
  FetchTransportError,
9
- backoffDelay,
10
9
  executeWithRetry,
11
10
  isJsonBody,
12
- isPlainObject,
13
- isRetryableStatus,
14
- retryAfterMs,
15
11
  safeStringify
16
- } from "./chunk-ywdpxbkf.js";
12
+ } from "./chunk-b699cfes.js";
13
+ import"./chunk-sz4pvqxy.js";
17
14
  // src/client/options.ts
18
15
  var DEFAULT_REQUEST_ID_HEADER = "x-request-id";
19
16
 
@@ -295,11 +292,12 @@ var serviceFrom = (target, optionsToken) => provide(target, {
295
292
  useFactory: (options, logger, context) => new HttpService(options, logger, context),
296
293
  inject: [optionsToken, Logger2, RequestContext2]
297
294
  });
298
- var namedModule = (name, options) => {
295
+ var namedModule = (name, options, imports = []) => {
299
296
  const optionsToken = token(`HttpClientOptions(${name})`);
300
297
  const optionsProvider = options instanceof HttpClientOptions ? provide(optionsToken, { useValue: options }) : provide(optionsToken, options);
301
298
  return {
302
299
  module: HttpModule,
300
+ imports,
303
301
  exports: [optionsToken, httpClient(name)],
304
302
  providers: [optionsProvider, serviceFrom(httpClient(name), optionsToken)]
305
303
  };
@@ -322,12 +320,14 @@ class HttpModule {
322
320
  static forRootAsync(source, name) {
323
321
  const load = typeof source === "function" ? source : source.useFactory;
324
322
  const inject = typeof source === "function" ? [] : source.inject ?? [];
323
+ const imports = typeof source === "function" ? [] : source.imports ?? [];
325
324
  const useFactory = async (...deps) => new HttpClientOptions(await load(...deps));
326
325
  if (name !== undefined) {
327
- return namedModule(name, { useFactory, inject });
326
+ return namedModule(name, { useFactory, inject }, imports);
328
327
  }
329
328
  return {
330
329
  module: HttpModule,
330
+ imports,
331
331
  exports: [HttpClientOptions, HttpService],
332
332
  providers: [
333
333
  provide(HttpClientOptions, { useFactory, inject }),
@@ -343,12 +343,5 @@ export {
343
343
  HttpClientOptions,
344
344
  HttpModule,
345
345
  HttpService,
346
- backoffDelay,
347
- executeWithRetry,
348
- httpClient,
349
- isJsonBody,
350
- isPlainObject,
351
- isRetryableStatus,
352
- retryAfterMs,
353
- safeStringify
346
+ httpClient
354
347
  };
@@ -1,4 +1,4 @@
1
- import { type Deps, type DynamicModule, type FactoryProvider } from '@dunx/core';
1
+ import { type Deps, type DynamicModule, type AsyncModuleConfig } from '@dunx/core';
2
2
  import { type CompressionOptionsInit } from './options.js';
3
3
  /**
4
4
  * Binds `Compression` and its options. Like `StaticModule`, importing it does not
@@ -14,7 +14,5 @@ import { type CompressionOptionsInit } from './options.js';
14
14
  export declare class CompressionModule {
15
15
  static forRoot(init?: CompressionOptionsInit): DynamicModule;
16
16
  /** `forRoot` with the options read off the container - a config value, usually. */
17
- static forRootAsync<const D extends Deps>(config: FactoryProvider<CompressionOptionsInit, D> & {
18
- readonly imports?: DynamicModule['imports'];
19
- }): DynamicModule;
17
+ static forRootAsync<const D extends Deps>(config: AsyncModuleConfig<CompressionOptionsInit, D>): DynamicModule;
20
18
  }
@@ -1,4 +1,4 @@
1
- import { type Deps, type DynamicModule, type FactoryProvider } from '@dunx/core';
1
+ import { type Deps, type DynamicModule, type AsyncModuleConfig } from '@dunx/core';
2
2
  import { type HealthOptionsInit } from './registry.js';
3
3
  /**
4
4
  * Liveness and readiness, and the drain that makes readiness worth having.
@@ -33,8 +33,7 @@ export declare class HealthModule {
33
33
  * table is folded into one closure per route when the server binds, so it cannot
34
34
  * wait on a factory. Pass `routes: false` and mount your own if that matters.
35
35
  */
36
- static forRootAsync<const D extends Deps>(config: FactoryProvider<HealthOptionsInit, D> & {
37
- readonly imports?: DynamicModule['imports'];
36
+ static forRootAsync<const D extends Deps>(config: AsyncModuleConfig<HealthOptionsInit, D> & {
38
37
  readonly routes?: boolean;
39
38
  readonly documented?: boolean;
40
39
  }): DynamicModule;
@@ -1,5 +1,5 @@
1
1
  import type { OnBeforeShutdown } from '@dunx/core';
2
- export interface ReadinessOptionsInit {
2
+ interface ReadinessOptionsInit {
3
3
  /**
4
4
  * How long to keep failing readiness after the drain starts, before the server
5
5
  * stops accepting. Default `0`.
@@ -49,3 +49,4 @@ export declare class Readiness implements OnBeforeShutdown {
49
49
  */
50
50
  onBeforeShutdown(): Promise<void>;
51
51
  }
52
+ export {};
package/dist/index.d.ts CHANGED
@@ -39,10 +39,3 @@ export { HealthModule } from './health/module.js';
39
39
  export { HEALTH_REPORT_SCHEMA } from './health/report-schema.js';
40
40
  export { Readiness, ReadinessOptions } from './health/readiness.js';
41
41
  export { HealthOptions, HealthRegistry, type HealthCheckReport, type HealthOptionsInit, type HealthReport, } from './health/registry.js';
42
- /**
43
- * The framework's own plumbing, still reachable here and moving out in 4.0.
44
- * Import it from `@dunx/http/internal`, which carries no stability promise.
45
- *
46
- * @deprecated Import from `@dunx/http/internal`. Removed in 4.0.
47
- */
48
- export { assertNoCollisions, assertNoGatewayCollisions, buildContext, buildGateways, buildRoutes, buildRuntime, buildWebSocket, compose, composeSocket, decode, decodeRelay, defaultRelayUrl, defaultStatusFor, discoverGateway, discoverGateways, discoverRoutes, encode, encodeRelay, gatewaysOf, guardsOf, HandlerKind, HiddenHealthController, isCompressibleType, isErrorFilter, isGateway, joinPath, negotiate, normalizePath, normalizePrefix, observe, preflight, routesOf, toErrorMapper, withCors, withUpgradeRoutes, type BunRoutes, type DefaultStatus, type DiscoveredGateway, type DiscoveredHandler, type DiscoveredRoute, type GatewayHandler, type GatewayNode, type GatewayRuntime, type GuardResolver, type HandlerMeta, type Invoke, type RelayFrame, type RelayPhase, type RouteInputs, type RouteMeta, type RouteMethod, type RouteNode, type ServeRoutes, type UpgradeHandler, type WebSocketRuntime, } from './internal.js';
package/dist/index.js CHANGED
@@ -21,7 +21,6 @@ import {
21
21
  HealthRegistry,
22
22
  HiddenHealthController,
23
23
  HttpError,
24
- HttpStatusCode,
25
24
  PUBLIC,
26
25
  Patch,
27
26
  Post,
@@ -37,37 +36,19 @@ import {
37
36
  UNMATCHED,
38
37
  UseGuards,
39
38
  ValidationError,
40
- __decorateElement,
41
- __decoratorMetadata,
42
- __decoratorStart,
43
- __runInitializers,
44
39
  assertNoCollisions,
45
40
  assertNoGatewayCollisions,
46
- buildContext,
47
41
  buildFallback,
48
- buildGateways,
49
42
  buildRoutes,
50
- buildRuntime,
51
43
  buildWebSocket,
52
- compose,
53
- composeSocket,
54
- decode,
55
44
  decodeRelay,
56
45
  defaultErrorMapper,
57
46
  defaultRelayError,
58
- defaultRelayUrl,
59
- defaultStatusFor,
60
- discoverGateway,
61
47
  discoverGateways,
62
48
  discoverRoutes,
63
49
  encode,
64
50
  encodeRelay,
65
51
  errorMapper,
66
- gatewaysOf,
67
- guardsOf,
68
- isCompressibleType,
69
- isErrorFilter,
70
- isGateway,
71
52
  joinPath,
72
53
  markGateway,
73
54
  markHandler,
@@ -76,15 +57,17 @@ import {
76
57
  metaKey,
77
58
  metaOf,
78
59
  negotiate,
79
- normalizePath,
80
- normalizePrefix,
81
60
  observe,
82
- preflight,
83
- routesOf,
84
61
  toErrorMapper,
85
- withCors,
86
62
  withUpgradeRoutes
87
- } from "./chunk-ywdpxbkf.js";
63
+ } from "./chunk-f6pw36av.js";
64
+ import {
65
+ HttpStatusCode,
66
+ __decorateElement,
67
+ __decoratorMetadata,
68
+ __decoratorStart,
69
+ __runInitializers
70
+ } from "./chunk-sz4pvqxy.js";
88
71
  // src/server/client-address.ts
89
72
  import { AppError } from "@dunx/core";
90
73
  var trustedHops = (setting) => {
@@ -94,6 +77,8 @@ var trustedHops = (setting) => {
94
77
  return 0;
95
78
  return Number.isFinite(setting) ? Math.max(0, Math.trunc(setting)) : 0;
96
79
  };
80
+ var IPV4_MAPPED = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i;
81
+ var unmap = (address) => address === undefined ? undefined : IPV4_MAPPED.exec(address)?.[1] ?? address;
97
82
  var sources = new WeakMap;
98
83
 
99
84
  class ClientAddress {
@@ -107,9 +92,9 @@ class ClientAddress {
107
92
  const entries = (req.headers.get("x-forwarded-for") ?? "").split(",").map((entry2) => entry2.trim()).filter((entry2) => entry2.length > 0);
108
93
  const entry = entries[Math.max(0, entries.length - hops)];
109
94
  if (entry)
110
- return entry;
95
+ return unmap(entry);
111
96
  }
112
- return source.server.requestIP(req)?.address;
97
+ return unmap(source.server.requestIP(req)?.address);
113
98
  }
114
99
  }
115
100
  var attachAddressSource = (target, source) => {
@@ -1538,13 +1523,11 @@ export {
1538
1523
  Get,
1539
1524
  HEALTH_REPORT_SCHEMA,
1540
1525
  HIDDEN,
1541
- HandlerKind,
1542
1526
  HealthController,
1543
1527
  HealthIndicator,
1544
1528
  HealthModule,
1545
1529
  HealthOptions,
1546
1530
  HealthRegistry,
1547
- HiddenHealthController,
1548
1531
  HttpError,
1549
1532
  HttpFactory,
1550
1533
  HttpStatusCode,
@@ -1593,43 +1576,10 @@ export {
1593
1576
  UNMATCHED,
1594
1577
  UseGuards,
1595
1578
  ValidationError,
1596
- assertNoCollisions,
1597
- assertNoGatewayCollisions,
1598
- buildContext,
1599
- buildGateways,
1600
- buildRoutes,
1601
- buildRuntime,
1602
- buildWebSocket,
1603
- compose,
1604
- composeSocket,
1605
- decode,
1606
- decodeRelay,
1607
1579
  defaultErrorMapper,
1608
- defaultRelayUrl,
1609
- defaultStatusFor,
1610
- discoverGateway,
1611
- discoverGateways,
1612
- discoverRoutes,
1613
- encode,
1614
- encodeRelay,
1615
1580
  errorMapper,
1616
- gatewaysOf,
1617
- guardsOf,
1618
- isCompressibleType,
1619
- isErrorFilter,
1620
- isGateway,
1621
- joinPath,
1622
1581
  mergeMeta,
1623
1582
  meta,
1624
1583
  metaKey,
1625
- metaOf,
1626
- negotiate,
1627
- normalizePath,
1628
- normalizePrefix,
1629
- observe,
1630
- preflight,
1631
- routesOf,
1632
- toErrorMapper,
1633
- withCors,
1634
- withUpgradeRoutes
1584
+ metaOf
1635
1585
  };
@@ -1,9 +1,9 @@
1
1
  /**
2
- * What the framework calls on itself. Every symbol here is still reachable from
3
- * the package barrel, deprecated, and leaves it in 4.0.
2
+ * What the framework calls on itself, and the only place it is exported from.
4
3
  *
5
- * The barrel is a semver promise, and 173 of them was more than this package
6
- * meant to make. What stays public is the surface an app writes against:
4
+ * The barrel was a semver promise 173 symbols wide, which is more than this
5
+ * package meant to make. What stays public there is the surface an app writes
6
+ * against:
7
7
  * decorators, options, contracts, errors, modules and the metadata helpers a
8
8
  * user's own guard reads. What is here is route-table construction, the
9
9
  * middleware fold, the relay codec and the discovery readers - things
package/dist/internal.js CHANGED
@@ -1,10 +1,12 @@
1
1
  // @bun
2
2
  import {
3
+ HIDDEN,
3
4
  HandlerKind,
4
5
  HiddenHealthController,
6
+ PUBLIC,
7
+ ROLES,
5
8
  assertNoCollisions,
6
9
  assertNoGatewayCollisions,
7
- backoffDelay,
8
10
  buildContext,
9
11
  buildGateways,
10
12
  buildRoutes,
@@ -21,28 +23,91 @@ import {
21
23
  discoverRoutes,
22
24
  encode,
23
25
  encodeRelay,
24
- executeWithRetry,
25
- gatewaysOf,
26
26
  guardsOf,
27
27
  isCompressibleType,
28
28
  isErrorFilter,
29
29
  isGateway,
30
- isJsonBody,
31
- isPlainObject,
32
- isRetryableStatus,
33
30
  joinPath,
34
31
  negotiate,
35
32
  normalizePath,
36
33
  normalizePrefix,
37
34
  observe,
38
35
  preflight,
39
- retryAfterMs,
40
- routesOf,
41
- safeStringify,
42
36
  toErrorMapper,
43
37
  withCors,
44
38
  withUpgradeRoutes
45
- } from "./chunk-ywdpxbkf.js";
39
+ } from "./chunk-f6pw36av.js";
40
+ import {
41
+ backoffDelay,
42
+ executeWithRetry,
43
+ isJsonBody,
44
+ isPlainObject,
45
+ isRetryableStatus,
46
+ retryAfterMs,
47
+ safeStringify
48
+ } from "./chunk-b699cfes.js";
49
+ import"./chunk-sz4pvqxy.js";
50
+ // src/inspect.ts
51
+ import {
52
+ collectModules,
53
+ dependenciesOf,
54
+ readControllers
55
+ } from "@dunx/core";
56
+ var vendorOf = (schema) => schema?.["~standard"]?.vendor;
57
+ var validatesIn = (options) => {
58
+ const body = vendorOf(options?.body);
59
+ const query = vendorOf(options?.query);
60
+ const params = vendorOf(options?.params);
61
+ return {
62
+ ...body === undefined ? {} : { body },
63
+ ...query === undefined ? {} : { query },
64
+ ...params === undefined ? {} : { params }
65
+ };
66
+ };
67
+ var rolesIn = (route) => {
68
+ const roles = route.meta?.get(ROLES.id);
69
+ if (roles === undefined || roles === null)
70
+ return null;
71
+ return (Array.isArray(roles) ? roles : [roles]).map(String);
72
+ };
73
+ var nodeFor = (route, module) => ({
74
+ method: route.method,
75
+ path: route.path,
76
+ controller: route.controller,
77
+ handler: route.handlerName,
78
+ module,
79
+ public: route.meta?.get(PUBLIC.id) === true,
80
+ roles: rolesIn(route),
81
+ guards: (route.guards ?? []).map((guard) => guard.name),
82
+ hidden: route.meta?.get(HIDDEN.id) === true,
83
+ validates: validatesIn(route.options),
84
+ status: route.options?.status ?? null,
85
+ responses: Object.keys(route.options?.response ?? {}).map(Number)
86
+ });
87
+ var routesOf = (root) => collectModules(root).flatMap((module) => readControllers(module).flatMap((controller) => {
88
+ const { prototype } = controller;
89
+ return discoverRoutes(Object.create(prototype)).map((route) => nodeFor(route, module.name));
90
+ }));
91
+ var gatewayFor = (ctor, module) => {
92
+ const { name, path, handlers } = discoverGateway(Object.create(ctor.prototype));
93
+ return {
94
+ name,
95
+ path,
96
+ module,
97
+ dependencies: dependenciesOf(ctor),
98
+ handlers: handlers.map((handler) => ({
99
+ kind: handler.kind,
100
+ event: handler.event ?? null,
101
+ method: handler.method
102
+ }))
103
+ };
104
+ };
105
+ var classOf = (entry) => {
106
+ if (typeof entry === "function")
107
+ return entry;
108
+ return entry.provider.kind === "class" ? entry.provider.ctor : undefined;
109
+ };
110
+ var gatewaysOf = (root) => collectModules(root).flatMap((module) => (module.options.providers ?? []).map(classOf).filter((ctor) => ctor !== undefined).filter(isGateway).map((ctor) => gatewayFor(ctor, module.name)));
46
111
  export {
47
112
  HandlerKind,
48
113
  HiddenHealthController,
@@ -1,5 +1,5 @@
1
1
  import type { BunRequest, Server } from 'bun';
2
- export interface AddressSource {
2
+ interface AddressSource {
3
3
  readonly server: Server<unknown>;
4
4
  readonly trustProxy: boolean | number;
5
5
  }
@@ -8,6 +8,9 @@ export interface AddressSource {
8
8
  * right of `X-Forwarded-For` by the number of trusted hops, never from the left: a
9
9
  * client can send anything, and only the entries a proxy appended carry weight.
10
10
  *
11
+ * An IPv4-mapped IPv6 address is returned in its IPv4 form: `::ffff:10.0.0.1`
12
+ * comes back as `10.0.0.1`, from the header and from the socket alike.
13
+ *
11
14
  * Bound by `HttpFactory`'s global wrapper, which is not optional under module
12
15
  * scoping - an unbound class self-binds into whichever scope asks first, so a
13
16
  * second module injecting it was a boot error.
@@ -17,3 +20,4 @@ export declare class ClientAddress {
17
20
  }
18
21
  /** Internal: `listen()` hands the bound server to the resolved singleton. */
19
22
  export declare const attachAddressSource: (target: ClientAddress, source: AddressSource) => void;
23
+ export {};
@@ -1,4 +1,4 @@
1
- import { type Deps, type DynamicModule, type FactoryProvider } from '@dunx/core';
1
+ import { type Deps, type DynamicModule, type AsyncModuleConfig } from '@dunx/core';
2
2
  import { type StaticOptionsInit } from './options.js';
3
3
  /**
4
4
  * Serves a directory. Like the dashboard, it does not register itself:
@@ -46,7 +46,5 @@ import { type StaticOptionsInit } from './options.js';
46
46
  export declare class StaticModule {
47
47
  static forRoot(init: StaticOptionsInit): DynamicModule;
48
48
  /** `forRoot` with the root read off the container - a config value, usually. */
49
- static forRootAsync<const D extends Deps>(config: FactoryProvider<StaticOptionsInit, D> & {
50
- readonly imports?: DynamicModule['imports'];
51
- }): DynamicModule;
49
+ static forRootAsync<const D extends Deps>(config: AsyncModuleConfig<StaticOptionsInit, D>): DynamicModule;
52
50
  }
@@ -1,4 +1,4 @@
1
- import { type Deps, type DynamicModule, type FactoryProvider } from '@dunx/core';
1
+ import { type Deps, type DynamicModule, type AsyncModuleConfig } from '@dunx/core';
2
2
  import { type ThrottleOptionsInit } from './options.js';
3
3
  /**
4
4
  * The decorator, the guard, the counter and its options.
@@ -27,7 +27,5 @@ import { type ThrottleOptionsInit } from './options.js';
27
27
  export declare class ThrottleModule {
28
28
  static forRoot(init: ThrottleOptionsInit): DynamicModule;
29
29
  /** `forRoot` with the limit read off the container - a config value, usually. */
30
- static forRootAsync<const D extends Deps>(config: FactoryProvider<ThrottleOptionsInit, D> & {
31
- readonly imports?: DynamicModule['imports'];
32
- }): DynamicModule;
30
+ static forRootAsync<const D extends Deps>(config: AsyncModuleConfig<ThrottleOptionsInit, D>): DynamicModule;
33
31
  }
@@ -31,10 +31,11 @@ export interface WebSocketRuntime {
31
31
  */
32
32
  readonly warnings: readonly string[];
33
33
  }
34
- export interface GatewaySummary {
34
+ interface GatewaySummary {
35
35
  readonly name: string;
36
36
  readonly path: string;
37
37
  /** `@OnMessage('name')` events. A raw catch-all has no name to report. */
38
38
  readonly events: readonly string[];
39
39
  }
40
40
  export declare const buildWebSocket: (discovered: readonly DiscoveredGateway[], options?: SocketOptions, middleware?: readonly SocketMiddleware[]) => WebSocketRuntime;
41
+ export {};
@@ -1,4 +1,4 @@
1
- import { type Ctor, type InjectionToken, type ResolvedModule } from '@dunx/core';
1
+ import { type InjectionToken, type ResolvedModule } from '@dunx/core';
2
2
  import { type HandlerKind } from './marker.js';
3
3
  /**
4
4
  * A discovered handler, already bound to its instance. Every kind has a different
@@ -26,12 +26,6 @@ export declare const normalizePath: (path: string) => string;
26
26
  * handler is bound off the instance.
27
27
  */
28
28
  export declare const discoverGateway: (instance: object) => DiscoveredGateway;
29
- /**
30
- * The name of the first handler a class declares, without constructing it. A
31
- * provider that declares one but is not a gateway would silently never receive a
32
- * frame, so that becomes a boot error naming the method.
33
- */
34
- export declare const findHandlerMethod: (ctor: Ctor<unknown>) => string | undefined;
35
29
  /**
36
30
  * Gateways are declared in `@Module({ providers })` like any other injectable and
37
31
  * found here by their marker - the same discovery-by-inspection controllers get,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunx/http",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Bun.serve adapter for the dunx framework: controllers, middleware and WebSocket gateways",
5
5
  "keywords": [
6
6
  "bun",
@@ -62,7 +62,7 @@
62
62
  "@dunx/core": "workspace:*"
63
63
  },
64
64
  "peerDependencies": {
65
- "@dunx/core": "^3.0.0",
65
+ "@dunx/core": "^3.0.2",
66
66
  "@types/bun": ">=1.3.0"
67
67
  },
68
68
  "peerDependenciesMeta": {