@dunx/http 3.2.1 → 3.3.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.
package/dist/internal.js CHANGED
@@ -1,16 +1,16 @@
1
1
  // @bun
2
+ import"./chunk-bg0dr54z.js";
2
3
  import {
3
- HIDDEN,
4
- PUBLIC,
5
- ROLES,
6
- buildContext,
7
- defaultStatusFor,
4
+ defaultStatusFor2,
5
+ ROLES2,
6
+ PUBLIC2,
7
+ HIDDEN2,
8
+ joinPath2,
9
+ discoverRoutes2,
10
+ isGateway2,
8
11
  discoverGateway,
9
- discoverRoutes,
10
- isGateway,
11
- joinPath
12
- } from "./chunk-3nbj06q8.js";
13
- import"./chunk-sz4pvqxy.js";
12
+ buildContext2
13
+ } from "./chunk-8939brh2.js";
14
14
  // src/inspect.ts
15
15
  import {
16
16
  classOf,
@@ -31,7 +31,7 @@ var validatesIn = (options) => {
31
31
  };
32
32
  };
33
33
  var rolesIn = (route) => {
34
- const roles = route.meta?.get(ROLES.id);
34
+ const roles = route.meta?.get(ROLES2.id);
35
35
  if (roles === undefined || roles === null)
36
36
  return null;
37
37
  return (Array.isArray(roles) ? roles : [roles]).map(String);
@@ -42,16 +42,16 @@ var nodeFor = (route, module) => ({
42
42
  controller: route.controller,
43
43
  handler: route.handlerName,
44
44
  module,
45
- public: route.meta?.get(PUBLIC.id) === true,
45
+ public: route.meta?.get(PUBLIC2.id) === true,
46
46
  roles: rolesIn(route),
47
47
  guards: (route.guards ?? []).map((guard) => guard.name),
48
- hidden: route.meta?.get(HIDDEN.id) === true,
48
+ hidden: route.meta?.get(HIDDEN2.id) === true,
49
49
  validates: validatesIn(route.options),
50
50
  status: route.options?.status ?? null,
51
51
  responses: Object.keys(route.options?.response ?? {}).map(Number)
52
52
  });
53
53
  var routesOf = (root) => collectModules(root).flatMap((module) => readControllers(module).flatMap((controller) => {
54
- return discoverRoutes(inertInstance(controller)).map((route) => nodeFor(route, module.name));
54
+ return discoverRoutes2(inertInstance(controller)).map((route) => nodeFor(route, module.name));
55
55
  }));
56
56
  var gatewayFor = (ctor, module) => {
57
57
  const { name, path, handlers } = discoverGateway(inertInstance(ctor));
@@ -67,16 +67,16 @@ var gatewayFor = (ctor, module) => {
67
67
  }))
68
68
  };
69
69
  };
70
- var gatewaysOf = (root) => collectModules(root).flatMap((module) => (module.options.providers ?? []).map((entry) => classOf(entry)?.ctor).filter((ctor) => ctor !== undefined).filter(isGateway).map((ctor) => gatewayFor(ctor, module.name)));
70
+ var gatewaysOf = (root) => collectModules(root).flatMap((module) => (module.options.providers ?? []).map((entry) => classOf(entry)?.ctor).filter((ctor) => ctor !== undefined).filter(isGateway2).map((ctor) => gatewayFor(ctor, module.name)));
71
71
  // src/server/html.ts
72
72
  var embedJson = (value) => JSON.stringify(value).replaceAll("<", "\\u003c");
73
73
  export {
74
- buildContext,
75
- defaultStatusFor,
76
- discoverRoutes,
74
+ buildContext2 as buildContext,
75
+ defaultStatusFor2 as defaultStatusFor,
76
+ discoverRoutes2 as discoverRoutes,
77
77
  embedJson,
78
78
  gatewaysOf,
79
- isGateway,
80
- joinPath,
79
+ isGateway2 as isGateway,
80
+ joinPath2 as joinPath,
81
81
  routesOf
82
82
  };
@@ -1,106 +1,11 @@
1
1
  import type { BunRequest } from 'bun';
2
- import { ShutdownAware, type App, type AppOptions, type Ctor, type InjectionToken, type ModuleRef, type ShutdownHookOptions, type ShutdownSignal } from '@dunx/core';
2
+ import { ShutdownAware, type App, type Ctor, type InjectionToken, type ModuleRef } from '@dunx/core';
3
3
  import { type DiscoveredRoute } from '../route/discover.js';
4
4
  import type { WebSocketRuntime } from '../ws/adapter.js';
5
- import type { SocketLoggingOptions } from '../ws/logging.js';
6
- import type { SocketMiddleware } from '../ws/middleware.js';
7
- import type { PubSubRelay, RelayOptions } from '../ws/relay.js';
8
- import type { SocketOptions } from '../ws/socket.js';
9
5
  import type { CorsOptions } from './cors.js';
10
- import { type ErrorHandler } from './errors.js';
11
6
  import type { Middleware } from './middleware.js';
12
- import { type RequestLoggingOptions } from './request-logging.js';
13
7
  import { type AppSettings } from './settings.js';
14
- export interface HttpOptions extends AppOptions {
15
- readonly port?: number;
16
- /**
17
- * Prefixes every discovered route, the same thing {@link HttpApp.setGlobalPrefix}
18
- * does. Both exist: the method is what NestJS offers and what a script reaches
19
- * for, the field is what an `HttpOptionsProvider` can answer from validated
20
- * config. A later `setGlobalPrefix` call still wins, because it happens after.
21
- *
22
- * Explicitly `| undefined`, unlike the rest: a suite running one fixture both
23
- * prefixed and unprefixed passes a variable here, and under
24
- * `exactOptionalPropertyTypes` that would otherwise need a conditional spread.
25
- * "No prefix" and "absent" mean the same thing. `@dunx/testing` relies on it.
26
- */
27
- readonly prefix?: string | undefined;
28
- /** Mounts an `OPTIONS` preflight per path, as {@link HttpApp.enableCors} does. */
29
- readonly cors?: CorsOptions;
30
- /** `app.set('trust proxy', ...)` as a field. */
31
- readonly trustProxy?: boolean;
32
- /**
33
- * Calls `enableShutdownHooks` at construction. `true` takes the default signals;
34
- * an object names them and tunes the force-exit.
35
- */
36
- readonly shutdownHooks?: boolean | {
37
- readonly signals?: readonly ShutdownSignal[];
38
- readonly options?: ShutdownHookOptions;
39
- };
40
- /** Resolved from the container, so middleware can inject(). */
41
- readonly middleware?: readonly Ctor<Middleware>[];
42
- /**
43
- * Replaces the default mapper. Prefer an `ErrorFilter` class over a bare
44
- * `ErrorMapper`: a class is resolved from the container and can inject.
45
- */
46
- readonly onError?: ErrorHandler;
47
- /**
48
- * One structured entry per request, on by default and outermost, so a request
49
- * a guard rejected is still logged with the status it got.
50
- * See {@link RequestLoggingMiddleware}.
51
- */
52
- readonly requestLogging?: boolean | RequestLoggingOptions;
53
- /**
54
- * Count requests and time them per route, readable through
55
- * {@link RequestMetrics}. Off by default; `+35.2 ns` per request when
56
- * `requestLogging` is on, because the entry it already builds shares the
57
- * timing. With `requestLogging: false` a `MetricsMiddleware` pays for its own
58
- * `.then` instead, at +175.9 ns.
59
- */
60
- readonly metrics?: boolean;
61
- /**
62
- * One entry at `listen()` naming every route and gateway served. On by default,
63
- * and switched separately from `requestLogging`: one is per process, the other
64
- * per request. `@dunx/testing` defaults it off.
65
- */
66
- readonly bootLogging?: boolean;
67
- /** Bun's `websocket` options, plus where a throwing handler goes. Server-wide;
68
- * gateways themselves are declared in `@Module({ providers })`. */
69
- readonly websocket?: SocketOptions;
70
- /**
71
- * The socket half of `middleware`. Each entry wraps every dispatched gateway
72
- * handler; `socketLogging`'s runs outermost, ahead of anything here.
73
- */
74
- readonly socketMiddleware?: readonly Ctor<SocketMiddleware>[];
75
- /**
76
- * One structured entry per socket frame, on by default at `debug` - a gateway
77
- * can take a frame per connection per tick, so it writes nothing until an app
78
- * lowers its level. See {@link SocketLoggingMiddleware}.
79
- */
80
- readonly socketLogging?: boolean | SocketLoggingOptions;
81
- /**
82
- * Multi-node websocket fan-out. Absent means `PubSub` publishes to this process
83
- * only. Anything with `publish` and `subscribe` fits; one that has to come out
84
- * of the container goes through `app.get(PubSub).relayThrough(...)` instead.
85
- */
86
- readonly relay?: PubSubRelay;
87
- /** The broker channel the relay carries frames on. @default 'dunx:ws' */
88
- readonly relayChannel?: string;
89
- /**
90
- * How hard to retry a failed subscribe. Bounded, doubling, on an unref'd timer,
91
- * so a broker that never returns cannot hold the process open.
92
- */
93
- readonly relayResubscribe?: RelayOptions['resubscribe'];
94
- /**
95
- * What an unmatched path looks like to global middleware. `'guarded'` gives the
96
- * miss no route metadata, so a global guard refuses it and a prober cannot tell
97
- * a 404 from a 401. `'public'` reports it as `@Public()` for a conventional 404.
98
- * Either way `UNMATCHED` is set, which no real route sets.
99
- *
100
- * @default 'guarded'
101
- */
102
- readonly notFound?: 'guarded' | 'public';
103
- }
8
+ import type { HttpOptions } from './options.js';
104
9
  /**
105
10
  * Everything below `listen()` configures the route table, built once when the
106
11
  * server binds. Calling any of them afterwards throws.
@@ -118,6 +23,8 @@ export interface HttpApp extends App {
118
23
  clientIp(req: BunRequest): string | undefined;
119
24
  /** Every gateway path this app upgrades on, exactly as mounted. */
120
25
  readonly gatewayPaths: readonly string[];
26
+ /** The gateway port's own url, `undefined` unless `gatewayPort` split them. */
27
+ readonly gatewayUrl: string | undefined;
121
28
  listen(port?: number): Promise<string>;
122
29
  }
123
30
  export declare class HttpApplication extends ShutdownAware implements HttpApp {
@@ -137,6 +44,8 @@ export declare class HttpApplication extends ShutdownAware implements HttpApp {
137
44
  /** The one `Bun.serve` call. A gateway's upgrade is a native `GET` route in the
138
45
  * same table, so Bun's router matches it and no `fetch` handler is needed. */
139
46
  listen(port?: number): Promise<string>;
47
+ /** The gateway port's own url, when `gatewayPort` split them. */
48
+ get gatewayUrl(): string | undefined;
140
49
  /** Public so an operator can start draining without committing to a shutdown,
141
50
  * which is what a readiness probe wants during a rolling deploy. */
142
51
  drain(): Promise<void>;
@@ -0,0 +1,67 @@
1
+ import type { Server } from 'bun';
2
+ import type { SocketData } from '../ws/socket.js';
3
+ import type { WebSocketRuntime } from '../ws/adapter.js';
4
+ import type { RouteHandler } from './middleware.js';
5
+ import { type BunRoutes } from './routes.js';
6
+ /** What `listen()` computes and hands the binding, once the table is final. */
7
+ export interface BindingPlan {
8
+ readonly port: number;
9
+ readonly routes: BunRoutes;
10
+ readonly fetch: RouteHandler;
11
+ readonly websocket: WebSocketRuntime | undefined;
12
+ }
13
+ /** The protocol settings, fixed at construction. `undefined` leaves Bun's own
14
+ * default in place rather than restating it. */
15
+ export interface BindingProtocols {
16
+ readonly http2?: boolean | undefined;
17
+ readonly http1?: boolean | undefined;
18
+ /**
19
+ * A port of its own for the gateways. When set, the upgrade routes are not
20
+ * merged into the main table and a second `Bun.serve` takes them.
21
+ */
22
+ readonly gatewayPort?: number | undefined;
23
+ }
24
+ /**
25
+ * The two per-server counters a metrics reader wants, summed across however
26
+ * many servers are bound. `Server` satisfies it on its own, which is what an
27
+ * unsplit app hands over.
28
+ */
29
+ export interface ServerGauges {
30
+ readonly pendingRequests: number;
31
+ readonly pendingWebSockets: number;
32
+ }
33
+ export interface Bound {
34
+ readonly main: Server<SocketData>;
35
+ /** The server that owns the sockets, which is what `PubSub` publishes on. */
36
+ readonly sockets: Server<SocketData>;
37
+ readonly gauges: ServerGauges;
38
+ }
39
+ /**
40
+ * The one or two `Bun.serve` instances an app binds.
41
+ *
42
+ * One is the normal shape: a gateway's upgrade is a native `GET` route in the
43
+ * same table, so Bun's router matches it and nothing else is needed.
44
+ *
45
+ * Two exist for `gatewayPort`. A websocket upgrade is an HTTP/1.1 request, so a
46
+ * server with `http1: false` can serve HTTP/2 routes or gateways and never both;
47
+ * splitting the ports is what lets one app do both. The gateway server takes no
48
+ * protocol overrides, because refusing HTTP/1.x there is the thing being avoided.
49
+ *
50
+ * Both servers come from one container, which is the reason this is a second
51
+ * `Bun.serve` rather than a second `HttpFactory.create`: a second app would build
52
+ * a second container, and the gateways would inject different singletons than the
53
+ * controllers.
54
+ */
55
+ export declare class ServerBinding {
56
+ #private;
57
+ constructor(protocols: BindingProtocols);
58
+ bind(plan: BindingPlan): Bound;
59
+ get gatewayUrl(): string | undefined;
60
+ /**
61
+ * `force` is for the server that owns the sockets: a graceful stop waits for
62
+ * open connections, and a WebSocket never closes itself, so those clients see
63
+ * a 1006. Under a split the routes server holds none and stops gracefully, so
64
+ * an in-flight request there finishes rather than being cut off.
65
+ */
66
+ stop(force: boolean): Promise<void>;
67
+ }
@@ -1,6 +1,8 @@
1
1
  import { type ModuleRef } from '@dunx/core';
2
- import { type HttpApp, type HttpOptions } from './application.js';
3
- export type { HttpApp, HttpOptions } from './application.js';
2
+ import { type HttpApp } from './application.js';
3
+ import type { HttpOptions } from './options.js';
4
+ export type { HttpApp } from './application.js';
5
+ export type { HttpOptions } from './options.js';
4
6
  export declare class HttpFactory {
5
7
  #private;
6
8
  /**
@@ -1,5 +1,6 @@
1
1
  import { type HistogramSnapshot } from '@dunx/core';
2
- import type { BunRequest, Server } from 'bun';
2
+ import type { BunRequest } from 'bun';
3
+ import type { ServerGauges } from './binding.js';
3
4
  import type { RouteContext } from './context.js';
4
5
  import type { Middleware, Next } from './middleware.js';
5
6
  /** Every path Bun matched nothing for, collapsed into one series. */
@@ -53,8 +54,12 @@ export declare class RequestMetrics {
53
54
  * reflecting a deploy three days ago; who calls this is the app's decision.
54
55
  */
55
56
  reset(): void;
56
- /** Internal: `listen()` hands the bound server to the resolved singleton. */
57
- attach(server: Server<unknown>): void;
57
+ /**
58
+ * Internal: `listen()` hands the bound server's counters to the resolved
59
+ * singleton. Structural, so an app serving from two ports can hand over the
60
+ * sum rather than one server's half of it.
61
+ */
62
+ attach(server: ServerGauges): void;
58
63
  }
59
64
  /**
60
65
  * Whether `MetricsMiddleware` is the thing doing the observing.
@@ -1,5 +1,5 @@
1
1
  import type { Ctor } from '@dunx/core';
2
- import type { HttpOptions } from './application.js';
2
+ import type { HttpOptions } from './options.js';
3
3
  import type { SocketLoggingOptions } from '../ws/logging.js';
4
4
  import type { SocketMiddleware } from '../ws/middleware.js';
5
5
  import type { PubSubRelay, RelayOptions } from '../ws/relay.js';
@@ -86,6 +86,19 @@ export declare abstract class HttpOptionsProvider {
86
86
  /** Multi-node websocket fan-out. Absent publishes to this process only. */
87
87
  get relay(): PubSubRelay | undefined;
88
88
  get relayResubscribe(): RelayOptions['resubscribe'];
89
+ /**
90
+ * Serve HTTP/2 alongside HTTP/1.1 on the same port. `undefined` rather than
91
+ * `false` so an absent answer leaves Bun's own default in place instead of
92
+ * restating it. See {@link HttpOptions.http2}.
93
+ */
94
+ get http2(): boolean | undefined;
95
+ /** See {@link HttpOptions.http1}. `false` disables every gateway. */
96
+ get http1(): boolean | undefined;
97
+ /**
98
+ * A port of its own for the gateways, which is what makes `http1: false`
99
+ * usable with one. See {@link HttpOptions.gatewayPort}.
100
+ */
101
+ get gatewayPort(): number | undefined;
89
102
  }
90
103
  /**
91
104
  * The base itself, bound when no module bound a subclass. Concrete because the
@@ -0,0 +1,141 @@
1
+ import type { AppOptions, Ctor, ShutdownHookOptions, ShutdownSignal } from '@dunx/core';
2
+ import type { SocketLoggingOptions } from '../ws/logging.js';
3
+ import type { SocketMiddleware } from '../ws/middleware.js';
4
+ import type { PubSubRelay, RelayOptions } from '../ws/relay.js';
5
+ import type { SocketOptions } from '../ws/socket.js';
6
+ import type { CorsOptions } from './cors.js';
7
+ import type { ErrorHandler } from './errors.js';
8
+ import type { Middleware } from './middleware.js';
9
+ import type { RequestLoggingOptions } from './request-logging.js';
10
+ /**
11
+ * Every setting `HttpFactory.create` takes. Here rather than in
12
+ * `application.ts` so that file is the class it is named for.
13
+ *
14
+ * Each field has a twin on {@link HttpOptionsProvider}, which is the same
15
+ * settings answered from the container instead. The argument wins field by
16
+ * field; see `resolveHttpOptions`.
17
+ */
18
+ export interface HttpOptions extends AppOptions {
19
+ readonly port?: number;
20
+ /**
21
+ * Prefixes every discovered route, the same thing {@link HttpApp.setGlobalPrefix}
22
+ * does. Both exist: the method is what NestJS offers and what a script reaches
23
+ * for, the field is what an `HttpOptionsProvider` can answer from validated
24
+ * config. A later `setGlobalPrefix` call still wins, because it happens after.
25
+ *
26
+ * Explicitly `| undefined`, unlike the rest: a suite running one fixture both
27
+ * prefixed and unprefixed passes a variable here, and under
28
+ * `exactOptionalPropertyTypes` that would otherwise need a conditional spread.
29
+ * "No prefix" and "absent" mean the same thing. `@dunx/testing` relies on it.
30
+ */
31
+ readonly prefix?: string | undefined;
32
+ /** Mounts an `OPTIONS` preflight per path, as {@link HttpApp.enableCors} does. */
33
+ readonly cors?: CorsOptions;
34
+ /** `app.set('trust proxy', ...)` as a field. */
35
+ readonly trustProxy?: boolean;
36
+ /**
37
+ * Calls `enableShutdownHooks` at construction. `true` takes the default signals;
38
+ * an object names them and tunes the force-exit.
39
+ */
40
+ readonly shutdownHooks?: boolean | {
41
+ readonly signals?: readonly ShutdownSignal[];
42
+ readonly options?: ShutdownHookOptions;
43
+ };
44
+ /** Resolved from the container, so middleware can inject(). */
45
+ readonly middleware?: readonly Ctor<Middleware>[];
46
+ /**
47
+ * Replaces the default mapper. Prefer an `ErrorFilter` class over a bare
48
+ * `ErrorMapper`: a class is resolved from the container and can inject.
49
+ */
50
+ readonly onError?: ErrorHandler;
51
+ /**
52
+ * One structured entry per request, on by default and outermost, so a request
53
+ * a guard rejected is still logged with the status it got.
54
+ * See {@link RequestLoggingMiddleware}.
55
+ */
56
+ readonly requestLogging?: boolean | RequestLoggingOptions;
57
+ /**
58
+ * Count requests and time them per route, readable through
59
+ * {@link RequestMetrics}. Off by default; `+35.2 ns` per request when
60
+ * `requestLogging` is on, because the entry it already builds shares the
61
+ * timing. With `requestLogging: false` a `MetricsMiddleware` pays for its own
62
+ * `.then` instead, at +175.9 ns.
63
+ */
64
+ readonly metrics?: boolean;
65
+ /**
66
+ * One entry at `listen()` naming every route and gateway served. On by default,
67
+ * and switched separately from `requestLogging`: one is per process, the other
68
+ * per request. `@dunx/testing` defaults it off.
69
+ */
70
+ readonly bootLogging?: boolean;
71
+ /** Bun's `websocket` options, plus where a throwing handler goes. Server-wide;
72
+ * gateways themselves are declared in `@Module({ providers })`. */
73
+ readonly websocket?: SocketOptions;
74
+ /**
75
+ * The socket half of `middleware`. Each entry wraps every dispatched gateway
76
+ * handler; `socketLogging`'s runs outermost, ahead of anything here.
77
+ */
78
+ readonly socketMiddleware?: readonly Ctor<SocketMiddleware>[];
79
+ /**
80
+ * One structured entry per socket frame, on by default at `debug` - a gateway
81
+ * can take a frame per connection per tick, so it writes nothing until an app
82
+ * lowers its level. See {@link SocketLoggingMiddleware}.
83
+ */
84
+ readonly socketLogging?: boolean | SocketLoggingOptions;
85
+ /**
86
+ * Multi-node websocket fan-out. Absent means `PubSub` publishes to this process
87
+ * only. Anything with `publish` and `subscribe` fits; one that has to come out
88
+ * of the container goes through `app.get(PubSub).relayThrough(...)` instead.
89
+ */
90
+ readonly relay?: PubSubRelay;
91
+ /** The broker channel the relay carries frames on. @default 'dunx:ws' */
92
+ readonly relayChannel?: string;
93
+ /**
94
+ * How hard to retry a failed subscribe. Bounded, doubling, on an unref'd timer,
95
+ * so a broker that never returns cannot hold the process open.
96
+ */
97
+ readonly relayResubscribe?: RelayOptions['resubscribe'];
98
+ /**
99
+ * What an unmatched path looks like to global middleware. `'guarded'` gives the
100
+ * miss no route metadata, so a global guard refuses it and a prober cannot tell
101
+ * a 404 from a 401. `'public'` reports it as `@Public()` for a conventional 404.
102
+ * Either way `UNMATCHED` is set, which no real route sets.
103
+ *
104
+ * @default 'public'
105
+ */
106
+ readonly notFound?: 'guarded' | 'public';
107
+ /**
108
+ * Serve HTTP/2 on the same port, through the same routes and the same
109
+ * `fetch` fallback. Without TLS that is h2c: a client opening with the HTTP/2
110
+ * preface gets HTTP/2 and everyone else gets HTTP/1.1, which is what a proxy
111
+ * in front of the app speaks. Bun marks the option experimental.
112
+ *
113
+ * Gateways are unaffected and keep working, because a websocket upgrade is an
114
+ * HTTP/1.1 request and Bun serves both protocols on the one socket. There is
115
+ * no websocket over HTTP/2.
116
+ *
117
+ * @default false
118
+ */
119
+ readonly http2?: boolean;
120
+ /**
121
+ * Serve HTTP/1.1. `false` alongside `http2` refuses HTTP/1.x with a 505, which
122
+ * **disables every gateway**: a websocket upgrade is an HTTP/1.1 request, so
123
+ * nothing can connect to one. Only for a port that is HTTP/2 or nothing.
124
+ *
125
+ * @default true
126
+ */
127
+ readonly http1?: boolean;
128
+ /**
129
+ * A port of its own for the gateways. The routes keep {@link port} and the
130
+ * upgrades move here, on a second `Bun.serve` that takes no protocol
131
+ * overrides, so it speaks HTTP/1.1 whatever the main port is set to.
132
+ *
133
+ * This is what makes `http2` with `http1: false` usable: a websocket upgrade
134
+ * is an HTTP/1.1 request, so one port serves HTTP/2-only routes or gateways
135
+ * and never both. The pair without a `gatewayPort` is a boot error.
136
+ *
137
+ * `0` takes any free port and is the one value that does not warn when no
138
+ * gateway is declared. See docs/guide/19-deployment.md.
139
+ */
140
+ readonly gatewayPort?: number;
141
+ }
@@ -42,4 +42,20 @@ export type SocketOptions = Readonly<Pick<WebSocketHandler<SocketData>, 'backpre
42
42
  * nothing replaced it.
43
43
  */
44
44
  readonly onError?: SocketErrorHandler;
45
+ /**
46
+ * What a binary frame arrives as: `'nodebuffer'` (Bun's default),
47
+ * `'arraybuffer'`, `'uint8array'` or `'blob'`. Bun 1.4.1 added `'blob'` and
48
+ * accepts all four on a server socket.
49
+ *
50
+ * Not one of the `Pick`ed keys above, because Bun does not take it as a handler
51
+ * option - it is a mutable property on each `ServerWebSocket`. Declaring it
52
+ * here and assigning it as each connection opens is what makes it a
53
+ * server-wide setting rather than a line in every gateway's `@OnOpen`. The type
54
+ * is read off the socket, so the accepted values cannot drift from the runtime.
55
+ *
56
+ * It changes what `message` and the ping/pong payloads are at run time. Bun
57
+ * types them as the default's, so a gateway that sets this narrows the value
58
+ * itself.
59
+ */
60
+ readonly binaryType?: Socket['binaryType'];
45
61
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunx/http",
3
- "version": "3.2.1",
3
+ "version": "3.3.1",
4
4
  "description": "Bun.serve adapter for the dunx framework: controllers, middleware and WebSocket gateways",
5
5
  "keywords": [
6
6
  "bun",
@@ -65,8 +65,8 @@
65
65
  "@opentelemetry/sdk-trace-node": "2.11.0"
66
66
  },
67
67
  "peerDependencies": {
68
- "@dunx/core": "^3.2.1",
69
- "@types/bun": ">=1.3.0"
68
+ "@dunx/core": "^3.3.1",
69
+ "@types/bun": ">=1.4.1"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "@types/bun": {
@@ -74,6 +74,6 @@
74
74
  }
75
75
  },
76
76
  "engines": {
77
- "bun": ">=1.4.0"
77
+ "bun": ">=1.4.1"
78
78
  }
79
79
  }
@@ -1,108 +0,0 @@
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 };