@dunx/http 3.5.1 → 3.7.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.
Files changed (39) hide show
  1. package/README.md +14 -4
  2. package/dist/chunk-08k9vq31.js +94 -0
  3. package/dist/{chunk-p9hdmkm6.js → chunk-1jt27yka.js} +8 -83
  4. package/dist/chunk-3eecdh6d.js +160 -0
  5. package/dist/client/json.d.ts +12 -11
  6. package/dist/client/options.d.ts +3 -3
  7. package/dist/client/retry.d.ts +17 -31
  8. package/dist/client/service.d.ts +21 -12
  9. package/dist/client/sse.d.ts +39 -0
  10. package/dist/client.d.ts +10 -1
  11. package/dist/client.js +166 -108
  12. package/dist/connect/middleware.d.ts +25 -0
  13. package/dist/connect/module.d.ts +29 -0
  14. package/dist/connect/options.d.ts +64 -0
  15. package/dist/connect/registry.d.ts +47 -0
  16. package/dist/connect.d.ts +12 -0
  17. package/dist/connect.js +208 -0
  18. package/dist/index.d.ts +4 -1
  19. package/dist/index.js +253 -184
  20. package/dist/internal.d.ts +8 -10
  21. package/dist/internal.js +7 -3
  22. package/dist/route/claims.d.ts +11 -0
  23. package/dist/route/metadata.d.ts +11 -0
  24. package/dist/route/prefix.d.ts +6 -0
  25. package/dist/server/application.d.ts +1 -1
  26. package/dist/server/binding.d.ts +4 -2
  27. package/dist/server/claimed-routes.d.ts +15 -0
  28. package/dist/server/cors.d.ts +2 -2
  29. package/dist/server/middleware.d.ts +14 -2
  30. package/dist/server/options-provider.d.ts +3 -0
  31. package/dist/server/options.d.ts +9 -1
  32. package/dist/server/routes.d.ts +7 -2
  33. package/dist/sse/decorators.d.ts +28 -0
  34. package/dist/sse/event.d.ts +19 -0
  35. package/dist/sse/stream.d.ts +35 -0
  36. package/dist/static/files.d.ts +7 -0
  37. package/dist/static/options.d.ts +2 -2
  38. package/dist/throttle/guard.d.ts +3 -1
  39. package/package.json +19 -2
@@ -0,0 +1,208 @@
1
+ // @bun
2
+ import {
3
+ UNMATCHED2,
4
+ REQUEST_SERVER,
5
+ normalizePrefix
6
+ } from "./chunk-1jt27yka.js";
7
+ import {
8
+ HttpStatusCode2
9
+ } from "./chunk-bg0dr54z.js";
10
+ import {
11
+ __decoratorStart,
12
+ __decoratorMetadata,
13
+ __runInitializers,
14
+ __decorateElement,
15
+ PathClaims
16
+ } from "./chunk-08k9vq31.js";
17
+
18
+ // src/connect/registry.ts
19
+ import {
20
+ createConnectRouter
21
+ } from "@connectrpc/connect";
22
+ import { createFetchHandler } from "@connectrpc/connect/protocol";
23
+
24
+ // src/connect/options.ts
25
+ var connectService = (service, useClass) => ({ service, useClass });
26
+
27
+ class ConnectOptions {
28
+ services;
29
+ prefix;
30
+ connect;
31
+ grpcWeb;
32
+ streamTimeout;
33
+ router;
34
+ constructor(init) {
35
+ const {
36
+ services,
37
+ prefix,
38
+ connect,
39
+ grpcWeb,
40
+ streamTimeout,
41
+ imports: _imports,
42
+ ...router
43
+ } = init;
44
+ this.services = services;
45
+ const mounted = normalizePrefix(prefix ?? "");
46
+ this.prefix = mounted === "/" ? "" : mounted;
47
+ this.connect = connect ?? true;
48
+ this.grpcWeb = grpcWeb ?? true;
49
+ this.streamTimeout = streamTimeout ?? 0;
50
+ if (!Number.isFinite(this.streamTimeout) || this.streamTimeout < 0) {
51
+ throw new Error(`ConnectModule streamTimeout must be a non-negative number of seconds, got ${String(streamTimeout)}.`);
52
+ }
53
+ this.router = router;
54
+ if (!this.connect && !this.grpcWeb) {
55
+ throw new Error("ConnectModule needs at least one protocol, and both connect and " + "grpcWeb are false. Native gRPC is not a third option here: it " + "carries grpc-status in an HTTP trailer and Bun.serve sends none.");
56
+ }
57
+ if (services.length === 0) {
58
+ throw new Error("ConnectModule.forRoot was given no services. Pass at least one " + "connectService(Desc, Impl), or drop the module.");
59
+ }
60
+ }
61
+ }
62
+ Object.defineProperty(ConnectOptions, Symbol.for("dunx.deps"), { value: () => [{ unresolved: "init: ConnectOptionsInit" }] });
63
+
64
+ // src/connect/registry.ts
65
+ class ConnectRegistry {
66
+ #routes = new Map;
67
+ get paths() {
68
+ return [...this.#routes.keys()];
69
+ }
70
+ streamTimeout;
71
+ #methods = [];
72
+ #stopping = new AbortController;
73
+ constructor(options, implementations) {
74
+ this.streamTimeout = options.streamTimeout;
75
+ const router = createConnectRouter({
76
+ ...options.router,
77
+ connect: options.connect,
78
+ grpcWeb: options.grpcWeb,
79
+ grpc: false,
80
+ shutdownSignal: this.#stopping.signal
81
+ });
82
+ options.services.forEach((registration, index) => {
83
+ const implementation = implementations[index];
84
+ if (implementation === undefined) {
85
+ throw new Error(`No instance was resolved for ${registration.useClass.name}, which ` + `serves ${registration.service.typeName}.`);
86
+ }
87
+ router.service(registration.service, implementation);
88
+ });
89
+ const claims = new PathClaims("RPC", "Register each service once, or give one its own prefix.");
90
+ for (const handler of router.handlers) {
91
+ const path = `${options.prefix}${handler.requestPath}`;
92
+ const rpc = `${handler.service.typeName}.${handler.method.name}`;
93
+ claims.claim(path, rpc);
94
+ this.#routes.set(path, {
95
+ handle: createFetchHandler(handler),
96
+ streaming: handler.method.methodKind !== "unary"
97
+ });
98
+ this.#methods.push({
99
+ path,
100
+ service: handler.service.typeName,
101
+ method: handler.method.name,
102
+ kind: handler.method.methodKind,
103
+ protocols: handler.protocolNames
104
+ });
105
+ }
106
+ }
107
+ get methods() {
108
+ return this.#methods;
109
+ }
110
+ routeFor(path) {
111
+ return this.#routes.get(path);
112
+ }
113
+ onShutdown() {
114
+ this.#stopping.abort();
115
+ }
116
+ }
117
+ Object.defineProperty(ConnectRegistry, Symbol.for("dunx.deps"), { value: () => [ConnectOptions, { unresolved: "implementations: readonly object[]" }] });
118
+
119
+ // src/connect/middleware.ts
120
+ var NATIVE_GRPC = /^\s*application\/grpc\s*(?:[;+]|$)/i;
121
+ var grpcUnsupported = () => Response.json({
122
+ code: "unimplemented",
123
+ message: "This endpoint serves Connect and gRPC-Web, not gRPC. gRPC carries " + "grpc-status in an HTTP trailer and Bun.serve sends no trailers, so a " + "gRPC client would read every call as a protocol error. Use a Connect " + "or gRPC-Web transport, or put a proxy in front that translates."
124
+ }, { status: HttpStatusCode2.UNSUPPORTED_MEDIA_TYPE });
125
+
126
+ class ConnectMiddleware {
127
+ #registry;
128
+ constructor(registry) {
129
+ this.#registry = registry;
130
+ }
131
+ claimedPaths() {
132
+ return this.#registry.paths;
133
+ }
134
+ handle(req, ctx, next) {
135
+ if (ctx.get(UNMATCHED2) !== true)
136
+ return next();
137
+ const route = this.#registry.routeFor(ctx.path);
138
+ if (route === undefined)
139
+ return next();
140
+ const contentType = req.headers.get("content-type");
141
+ if (contentType !== null && NATIVE_GRPC.test(contentType)) {
142
+ return Promise.resolve(grpcUnsupported());
143
+ }
144
+ if (route.streaming) {
145
+ ctx.get(REQUEST_SERVER)?.timeout(req, this.#registry.streamTimeout);
146
+ }
147
+ return route.handle(req);
148
+ }
149
+ }
150
+ Object.defineProperty(ConnectMiddleware, Symbol.for("dunx.deps"), { value: () => [ConnectRegistry] });
151
+ // src/connect/module.ts
152
+ import {
153
+ Module,
154
+ provide
155
+ } from "@dunx/core";
156
+ var build = (services, options, imports) => {
157
+ const implementations = services.map((registration) => registration.useClass);
158
+ return {
159
+ module: ConnectModule,
160
+ imports,
161
+ exports: [ConnectOptions, ConnectRegistry, ConnectMiddleware],
162
+ providers: [
163
+ ...implementations,
164
+ options,
165
+ provide(ConnectRegistry, {
166
+ useFactory: (...deps) => {
167
+ const [resolved, ...instances] = deps;
168
+ return new ConnectRegistry(resolved, instances);
169
+ },
170
+ inject: [ConnectOptions, ...implementations]
171
+ }),
172
+ provide(ConnectMiddleware, {
173
+ useFactory: (registry) => new ConnectMiddleware(registry),
174
+ inject: [ConnectRegistry]
175
+ })
176
+ ]
177
+ };
178
+ };
179
+ var _dec = [
180
+ Module({})
181
+ ];
182
+ var _init = __decoratorStart(undefined);
183
+
184
+ class ConnectModule {
185
+ static forRoot(init) {
186
+ return build(init.services, provide(ConnectOptions, { useValue: new ConnectOptions(init) }), init.imports ?? []);
187
+ }
188
+ static forRootAsync(services, config) {
189
+ return build(services, provide(ConnectOptions, {
190
+ useFactory: async (...deps) => new ConnectOptions({
191
+ ...await config.useFactory(...deps),
192
+ services
193
+ }),
194
+ inject: config.inject ?? []
195
+ }), config.imports ?? []);
196
+ }
197
+ }
198
+ ConnectModule = __decorateElement(_init, 0, "ConnectModule", _dec, ConnectModule);
199
+ __runInitializers(_init, 1, ConnectModule);
200
+ __decoratorMetadata(_init, ConnectModule);
201
+ let _ConnectModule = ConnectModule;
202
+ export {
203
+ ConnectMiddleware,
204
+ ConnectModule,
205
+ ConnectOptions,
206
+ ConnectRegistry,
207
+ connectService
208
+ };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Controller, Delete, Get, Patch, Post, Put, } from './route/decorators.js';
2
2
  export type { HttpMethod, RoutePath } from './route/marker.js';
3
- export { ApiHidden, HIDDEN, meta, metaKey, metaOf, mergeMeta, Public, PUBLIC, Roles, ROLES, UNMATCHED, UseGuards, type MetaKey, type MetaRecord, } from './route/metadata.js';
3
+ export { ApiHidden, HIDDEN, meta, metaKey, metaOf, mergeMeta, Public, PUBLIC, Roles, ROLES, STREAMS, UNMATCHED, UseGuards, type MetaKey, type MetaRecord, } from './route/metadata.js';
4
4
  export type { InferOutput, Input, JsonSchema, ResponseMap, Returns, RouteInput, RouteSchemas, StandardSchemaIssue, StandardSchemaResult, StandardSchemaV1, } from './route/schema.js';
5
5
  export { ClientAddress } from './server/client-address.js';
6
6
  export type { RouteContext } from './server/context.js';
@@ -19,6 +19,9 @@ export { StaticOptions, type StaticOptionsInit } from './static/options.js';
19
19
  export { Compression } from './compression/compression.js';
20
20
  export { CompressionModule } from './compression/module.js';
21
21
  export { CompressionEncoding, CompressionOptions, type CompressionOptionsInit, } from './compression/options.js';
22
+ export { Sse, type SseInput, type SseResult, type SseSchemas, } from './sse/decorators.js';
23
+ export type { SseEvent } from './sse/event.js';
24
+ export { SseStream, type SseStreamOptions } from './sse/stream.js';
22
25
  export { SKIP_THROTTLE, SkipThrottle, THROTTLE, Throttle, type ThrottleLimit, } from './throttle/decorators.js';
23
26
  export { ThrottleGuard } from './throttle/guard.js';
24
27
  export { ThrottleModule } from './throttle/module.js';