@dunx/http 1.1.0 → 1.2.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/README.md +5 -5
- package/dist/chunk-5z96f3gr.js +110 -0
- package/dist/{chunk-x80f562w.js.map → chunk-5z96f3gr.js.map} +2 -2
- package/dist/client.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +309 -104
- package/dist/index.js.map +10 -6
- package/dist/inspect.d.ts +58 -0
- package/dist/server/request-logging.d.ts +18 -1
- package/dist/static/files.d.ts +35 -0
- package/dist/static/module.d.ts +27 -0
- package/dist/static/options.d.ts +46 -0
- package/package.json +2 -2
- package/dist/chunk-x80f562w.js +0 -40
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
HttpStatusCode
|
|
4
|
-
|
|
3
|
+
HttpStatusCode,
|
|
4
|
+
__decorateElement,
|
|
5
|
+
__decoratorMetadata,
|
|
6
|
+
__decoratorStart,
|
|
7
|
+
__runInitializers
|
|
8
|
+
} from "./chunk-5z96f3gr.js";
|
|
5
9
|
|
|
6
10
|
// src/route/marker.ts
|
|
7
11
|
var ROUTE = Symbol.for("dunx.route");
|
|
@@ -114,15 +118,166 @@ var discoverRoutes = (instance) => {
|
|
|
114
118
|
}
|
|
115
119
|
return routes;
|
|
116
120
|
};
|
|
121
|
+
// src/inspect.ts
|
|
122
|
+
import {
|
|
123
|
+
collectModules,
|
|
124
|
+
dependenciesOf,
|
|
125
|
+
readControllers
|
|
126
|
+
} from "@dunx/core";
|
|
127
|
+
|
|
128
|
+
// src/ws/discover.ts
|
|
129
|
+
import {
|
|
130
|
+
AppError
|
|
131
|
+
} from "@dunx/core";
|
|
132
|
+
|
|
133
|
+
// src/ws/marker.ts
|
|
134
|
+
var HANDLER = Symbol.for("dunx.ws.handler");
|
|
135
|
+
var GATEWAY = Symbol.for("dunx.ws.gateway");
|
|
136
|
+
var HandlerKind = Object.freeze({
|
|
137
|
+
UPGRADE: "upgrade",
|
|
138
|
+
OPEN: "open",
|
|
139
|
+
MESSAGE: "message",
|
|
140
|
+
CLOSE: "close",
|
|
141
|
+
DRAIN: "drain",
|
|
142
|
+
PING: "ping",
|
|
143
|
+
PONG: "pong"
|
|
144
|
+
});
|
|
145
|
+
var markHandler = (target, meta2) => {
|
|
146
|
+
Object.defineProperty(target, HANDLER, { value: meta2, configurable: true });
|
|
147
|
+
};
|
|
148
|
+
var handlerMetaOf = (value) => typeof value === "function" ? value[HANDLER] : undefined;
|
|
149
|
+
var markGateway = (target, path) => {
|
|
150
|
+
Object.defineProperty(target, GATEWAY, { value: path, configurable: true });
|
|
151
|
+
};
|
|
152
|
+
var gatewayPathOf = (target) => target[GATEWAY] ?? "/";
|
|
153
|
+
var isGateway = (target) => target[GATEWAY] !== undefined;
|
|
154
|
+
|
|
155
|
+
// src/ws/discover.ts
|
|
156
|
+
var normalizePath = (path) => {
|
|
157
|
+
const joined = `/${path}`.replace(/\/{2,}/g, "/");
|
|
158
|
+
return joined.length > 1 ? joined.replace(/\/$/, "") : "/";
|
|
159
|
+
};
|
|
160
|
+
var eachHandler = (start) => {
|
|
161
|
+
const found = [];
|
|
162
|
+
const seen = new Set;
|
|
163
|
+
for (let proto = start;proto !== null && proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
|
|
164
|
+
for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(proto))) {
|
|
165
|
+
if (name === "constructor" || seen.has(name))
|
|
166
|
+
continue;
|
|
167
|
+
const meta2 = handlerMetaOf(descriptor.value);
|
|
168
|
+
if (!meta2)
|
|
169
|
+
continue;
|
|
170
|
+
seen.add(name);
|
|
171
|
+
found.push([name, meta2]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return found;
|
|
175
|
+
};
|
|
176
|
+
var discoverGateway = (instance) => {
|
|
177
|
+
const klass = instance.constructor;
|
|
178
|
+
const members = instance;
|
|
179
|
+
return {
|
|
180
|
+
name: klass.name,
|
|
181
|
+
path: normalizePath(gatewayPathOf(klass)),
|
|
182
|
+
handlers: eachHandler(Object.getPrototypeOf(instance)).map(([name, meta2]) => ({
|
|
183
|
+
kind: meta2.kind,
|
|
184
|
+
event: meta2.event,
|
|
185
|
+
method: name,
|
|
186
|
+
invoke: members[name].bind(instance)
|
|
187
|
+
}))
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
var findHandlerMethod = (ctor) => eachHandler(ctor.prototype)[0]?.[0];
|
|
191
|
+
var classOf = (entry) => {
|
|
192
|
+
if (typeof entry === "function")
|
|
193
|
+
return { token: entry, ctor: entry };
|
|
194
|
+
return entry.provider.kind === "class" ? { token: entry.token, ctor: entry.provider.ctor } : undefined;
|
|
195
|
+
};
|
|
196
|
+
var discoverGateways = (modules, resolve) => {
|
|
197
|
+
const discovered = [];
|
|
198
|
+
for (const module of modules) {
|
|
199
|
+
for (const entry of module.options.providers ?? []) {
|
|
200
|
+
const candidate = classOf(entry);
|
|
201
|
+
if (!candidate)
|
|
202
|
+
continue;
|
|
203
|
+
if (isGateway(candidate.ctor)) {
|
|
204
|
+
discovered.push(discoverGateway(resolve(candidate.token)));
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const orphan = findHandlerMethod(candidate.ctor);
|
|
208
|
+
if (orphan !== undefined) {
|
|
209
|
+
throw new AppError(`${candidate.ctor.name}.${orphan}() is a websocket handler, but ` + `${candidate.ctor.name} is not a gateway. Decorate the class with ` + "@Gateway(path), or drop the handler decorator.");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return discovered;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/inspect.ts
|
|
217
|
+
var vendorOf = (schema) => schema?.["~standard"]?.vendor;
|
|
218
|
+
var validatesIn = (options) => {
|
|
219
|
+
const body = vendorOf(options?.body);
|
|
220
|
+
const query = vendorOf(options?.query);
|
|
221
|
+
const params = vendorOf(options?.params);
|
|
222
|
+
return {
|
|
223
|
+
...body === undefined ? {} : { body },
|
|
224
|
+
...query === undefined ? {} : { query },
|
|
225
|
+
...params === undefined ? {} : { params }
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
var rolesIn = (route) => {
|
|
229
|
+
const roles = route.meta?.get(ROLES.id);
|
|
230
|
+
if (roles === undefined || roles === null)
|
|
231
|
+
return null;
|
|
232
|
+
return (Array.isArray(roles) ? roles : [roles]).map(String);
|
|
233
|
+
};
|
|
234
|
+
var nodeFor = (route, module) => ({
|
|
235
|
+
method: route.method,
|
|
236
|
+
path: route.path,
|
|
237
|
+
controller: route.controller,
|
|
238
|
+
handler: route.handlerName,
|
|
239
|
+
module,
|
|
240
|
+
public: route.meta?.get(PUBLIC.id) === true,
|
|
241
|
+
roles: rolesIn(route),
|
|
242
|
+
guards: (route.guards ?? []).map((guard) => guard.name),
|
|
243
|
+
hidden: route.meta?.get(HIDDEN.id) === true,
|
|
244
|
+
validates: validatesIn(route.options),
|
|
245
|
+
status: route.options?.status ?? null,
|
|
246
|
+
responses: Object.keys(route.options?.response ?? {}).map(Number)
|
|
247
|
+
});
|
|
248
|
+
var routesOf = (root) => collectModules(root).flatMap((module) => readControllers(module).flatMap((controller) => {
|
|
249
|
+
const { prototype } = controller;
|
|
250
|
+
return discoverRoutes(Object.create(prototype)).map((route) => nodeFor(route, module.name));
|
|
251
|
+
}));
|
|
252
|
+
var gatewayFor = (ctor, module) => {
|
|
253
|
+
const { name, path, handlers } = discoverGateway(Object.create(ctor.prototype));
|
|
254
|
+
return {
|
|
255
|
+
name,
|
|
256
|
+
path,
|
|
257
|
+
module,
|
|
258
|
+
dependencies: dependenciesOf(ctor),
|
|
259
|
+
handlers: handlers.map((handler) => ({
|
|
260
|
+
kind: handler.kind,
|
|
261
|
+
event: handler.event ?? null,
|
|
262
|
+
method: handler.method
|
|
263
|
+
}))
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
var classOf2 = (entry) => {
|
|
267
|
+
if (typeof entry === "function")
|
|
268
|
+
return entry;
|
|
269
|
+
return entry.provider.kind === "class" ? entry.provider.ctor : undefined;
|
|
270
|
+
};
|
|
271
|
+
var gatewaysOf = (root) => collectModules(root).flatMap((module) => (module.options.providers ?? []).map(classOf2).filter((ctor) => ctor !== undefined).filter(isGateway).map((ctor) => gatewayFor(ctor, module.name)));
|
|
117
272
|
// src/server/client-address.ts
|
|
118
|
-
import { AppError } from "@dunx/core";
|
|
273
|
+
import { AppError as AppError2 } from "@dunx/core";
|
|
119
274
|
var sources = new WeakMap;
|
|
120
275
|
|
|
121
276
|
class ClientAddress {
|
|
122
277
|
of(req) {
|
|
123
278
|
const source = sources.get(this);
|
|
124
279
|
if (!source) {
|
|
125
|
-
throw new
|
|
280
|
+
throw new AppError2("ClientAddress has no server yet. The address comes from the live Bun " + "server, so it is only available once listen() has run.");
|
|
126
281
|
}
|
|
127
282
|
if (source.trustProxy) {
|
|
128
283
|
const forwarded = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim();
|
|
@@ -199,8 +354,8 @@ var preflight = (options, methods) => {
|
|
|
199
354
|
};
|
|
200
355
|
};
|
|
201
356
|
// src/server/errors.ts
|
|
202
|
-
import { AppError as
|
|
203
|
-
class HttpError extends
|
|
357
|
+
import { AppError as AppError3, ConsoleLogger } from "@dunx/core";
|
|
358
|
+
class HttpError extends AppError3 {
|
|
204
359
|
status;
|
|
205
360
|
name = "HttpError";
|
|
206
361
|
constructor(status, message, options) {
|
|
@@ -246,12 +401,12 @@ var errorMapper = (logger) => (error) => {
|
|
|
246
401
|
var defaultErrorMapper = errorMapper(new ConsoleLogger);
|
|
247
402
|
// src/server/factory.ts
|
|
248
403
|
import {
|
|
249
|
-
collectModules,
|
|
404
|
+
collectModules as collectModules2,
|
|
250
405
|
AppError as AppError8,
|
|
251
406
|
AppFactory,
|
|
252
407
|
Logger as Logger3,
|
|
253
408
|
provide,
|
|
254
|
-
readControllers,
|
|
409
|
+
readControllers as readControllers2,
|
|
255
410
|
RequestContext as RequestContext2
|
|
256
411
|
} from "@dunx/core";
|
|
257
412
|
|
|
@@ -273,35 +428,11 @@ var decode = (message) => {
|
|
|
273
428
|
};
|
|
274
429
|
|
|
275
430
|
// src/ws/runtime.ts
|
|
276
|
-
import { AppError as
|
|
277
|
-
|
|
278
|
-
// src/ws/marker.ts
|
|
279
|
-
var HANDLER = Symbol.for("dunx.ws.handler");
|
|
280
|
-
var GATEWAY = Symbol.for("dunx.ws.gateway");
|
|
281
|
-
var HandlerKind = Object.freeze({
|
|
282
|
-
UPGRADE: "upgrade",
|
|
283
|
-
OPEN: "open",
|
|
284
|
-
MESSAGE: "message",
|
|
285
|
-
CLOSE: "close",
|
|
286
|
-
DRAIN: "drain",
|
|
287
|
-
PING: "ping",
|
|
288
|
-
PONG: "pong"
|
|
289
|
-
});
|
|
290
|
-
var markHandler = (target, meta2) => {
|
|
291
|
-
Object.defineProperty(target, HANDLER, { value: meta2, configurable: true });
|
|
292
|
-
};
|
|
293
|
-
var handlerMetaOf = (value) => typeof value === "function" ? value[HANDLER] : undefined;
|
|
294
|
-
var markGateway = (target, path) => {
|
|
295
|
-
Object.defineProperty(target, GATEWAY, { value: path, configurable: true });
|
|
296
|
-
};
|
|
297
|
-
var gatewayPathOf = (target) => target[GATEWAY] ?? "/";
|
|
298
|
-
var isGateway = (target) => target[GATEWAY] !== undefined;
|
|
299
|
-
|
|
300
|
-
// src/ws/runtime.ts
|
|
431
|
+
import { AppError as AppError4 } from "@dunx/core";
|
|
301
432
|
var slotOf = (handler) => handler.kind === HandlerKind.MESSAGE && handler.event !== undefined ? `message ${JSON.stringify(handler.event)}` : handler.kind;
|
|
302
433
|
var buildRuntime = (gateway) => {
|
|
303
434
|
if (gateway.handlers.length === 0) {
|
|
304
|
-
throw new
|
|
435
|
+
throw new AppError4(`${gateway.name} is registered as a gateway but declares no handlers. ` + "Add an @OnMessage/@OnOpen/... method, or drop the @Gateway decorator.");
|
|
305
436
|
}
|
|
306
437
|
const owners = new Map;
|
|
307
438
|
const events = new Map;
|
|
@@ -309,7 +440,7 @@ var buildRuntime = (gateway) => {
|
|
|
309
440
|
const slot = slotOf(handler);
|
|
310
441
|
const existing = owners.get(slot);
|
|
311
442
|
if (existing) {
|
|
312
|
-
throw new
|
|
443
|
+
throw new AppError4(`Handler collision in ${gateway.name}: ${slot} is claimed by ` + `${existing.method}() and by ${handler.method}(). One handler per event.`);
|
|
313
444
|
}
|
|
314
445
|
owners.set(slot, handler);
|
|
315
446
|
if (handler.kind === HandlerKind.MESSAGE && handler.event !== undefined) {
|
|
@@ -335,7 +466,7 @@ var buildGateways = (discovered) => {
|
|
|
335
466
|
for (const gateway of discovered) {
|
|
336
467
|
const existing = byPath.get(gateway.path);
|
|
337
468
|
if (existing) {
|
|
338
|
-
throw new
|
|
469
|
+
throw new AppError4(`Gateway path collision: ${gateway.path} is served by ${existing.name} ` + `and by ${gateway.name}. One gateway per path.`);
|
|
339
470
|
}
|
|
340
471
|
byPath.set(gateway.path, buildRuntime(gateway));
|
|
341
472
|
}
|
|
@@ -468,70 +599,6 @@ var buildWebSocket = (discovered, options = {}) => {
|
|
|
468
599
|
};
|
|
469
600
|
};
|
|
470
601
|
|
|
471
|
-
// src/ws/discover.ts
|
|
472
|
-
import {
|
|
473
|
-
AppError as AppError4
|
|
474
|
-
} from "@dunx/core";
|
|
475
|
-
var normalizePath = (path) => {
|
|
476
|
-
const joined = `/${path}`.replace(/\/{2,}/g, "/");
|
|
477
|
-
return joined.length > 1 ? joined.replace(/\/$/, "") : "/";
|
|
478
|
-
};
|
|
479
|
-
var eachHandler = (start) => {
|
|
480
|
-
const found = [];
|
|
481
|
-
const seen = new Set;
|
|
482
|
-
for (let proto = start;proto !== null && proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
|
|
483
|
-
for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(proto))) {
|
|
484
|
-
if (name === "constructor" || seen.has(name))
|
|
485
|
-
continue;
|
|
486
|
-
const meta2 = handlerMetaOf(descriptor.value);
|
|
487
|
-
if (!meta2)
|
|
488
|
-
continue;
|
|
489
|
-
seen.add(name);
|
|
490
|
-
found.push([name, meta2]);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
return found;
|
|
494
|
-
};
|
|
495
|
-
var discoverGateway = (instance) => {
|
|
496
|
-
const klass = instance.constructor;
|
|
497
|
-
const members = instance;
|
|
498
|
-
return {
|
|
499
|
-
name: klass.name,
|
|
500
|
-
path: normalizePath(gatewayPathOf(klass)),
|
|
501
|
-
handlers: eachHandler(Object.getPrototypeOf(instance)).map(([name, meta2]) => ({
|
|
502
|
-
kind: meta2.kind,
|
|
503
|
-
event: meta2.event,
|
|
504
|
-
method: name,
|
|
505
|
-
invoke: members[name].bind(instance)
|
|
506
|
-
}))
|
|
507
|
-
};
|
|
508
|
-
};
|
|
509
|
-
var findHandlerMethod = (ctor) => eachHandler(ctor.prototype)[0]?.[0];
|
|
510
|
-
var classOf = (entry) => {
|
|
511
|
-
if (typeof entry === "function")
|
|
512
|
-
return { token: entry, ctor: entry };
|
|
513
|
-
return entry.provider.kind === "class" ? { token: entry.token, ctor: entry.provider.ctor } : undefined;
|
|
514
|
-
};
|
|
515
|
-
var discoverGateways = (modules, resolve) => {
|
|
516
|
-
const discovered = [];
|
|
517
|
-
for (const module of modules) {
|
|
518
|
-
for (const entry of module.options.providers ?? []) {
|
|
519
|
-
const candidate = classOf(entry);
|
|
520
|
-
if (!candidate)
|
|
521
|
-
continue;
|
|
522
|
-
if (isGateway(candidate.ctor)) {
|
|
523
|
-
discovered.push(discoverGateway(resolve(candidate.token)));
|
|
524
|
-
continue;
|
|
525
|
-
}
|
|
526
|
-
const orphan = findHandlerMethod(candidate.ctor);
|
|
527
|
-
if (orphan !== undefined) {
|
|
528
|
-
throw new AppError4(`${candidate.ctor.name}.${orphan}() is a websocket handler, but ` + `${candidate.ctor.name} is not a gateway. Decorate the class with ` + "@Gateway(path), or drop the handler decorator.");
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
return discovered;
|
|
533
|
-
};
|
|
534
|
-
|
|
535
602
|
// src/ws/pubsub.ts
|
|
536
603
|
import { AppError as AppError5 } from "@dunx/core";
|
|
537
604
|
|
|
@@ -726,6 +793,7 @@ class RequestLoggingMiddleware {
|
|
|
726
793
|
#requestBody;
|
|
727
794
|
#responseBody;
|
|
728
795
|
#ignore;
|
|
796
|
+
#ignorePrefix;
|
|
729
797
|
#correlateIgnored;
|
|
730
798
|
#correlate;
|
|
731
799
|
constructor(logger, context, options = {}) {
|
|
@@ -735,15 +803,23 @@ class RequestLoggingMiddleware {
|
|
|
735
803
|
this.#requestBody = options.requestBody ?? false;
|
|
736
804
|
this.#responseBody = options.responseBody ?? false;
|
|
737
805
|
this.#ignore = new Set(options.ignore ?? []);
|
|
806
|
+
this.#ignorePrefix = options.ignorePrefix ?? [];
|
|
738
807
|
this.#correlateIgnored = options.correlateIgnored ?? false;
|
|
739
808
|
this.#correlate = options.correlate ?? true;
|
|
740
809
|
}
|
|
810
|
+
#ignored(path) {
|
|
811
|
+
if (this.#ignore.size > 0 && this.#ignore.has(path))
|
|
812
|
+
return true;
|
|
813
|
+
if (this.#ignorePrefix.length === 0)
|
|
814
|
+
return false;
|
|
815
|
+
return this.#ignorePrefix.some((prefix) => path.startsWith(prefix));
|
|
816
|
+
}
|
|
741
817
|
handle(req, ctx, next) {
|
|
742
818
|
const url = req.url;
|
|
743
819
|
const from = url.indexOf("/", url.indexOf("://") + 3);
|
|
744
820
|
const mark = from === -1 ? -1 : url.indexOf("?", from);
|
|
745
821
|
const path = from === -1 ? "/" : mark === -1 ? url.slice(from) : url.slice(from, mark);
|
|
746
|
-
if (this.#
|
|
822
|
+
if (this.#ignored(path)) {
|
|
747
823
|
return this.#correlateIgnored ? this.#correlated(req, ctx, path, next) : next();
|
|
748
824
|
}
|
|
749
825
|
const started = Bun.nanoseconds();
|
|
@@ -1295,11 +1371,11 @@ class HttpFactory {
|
|
|
1295
1371
|
exports: providers.map((entry) => typeof entry === "function" ? entry : entry.token)
|
|
1296
1372
|
};
|
|
1297
1373
|
const app = await AppFactory.create(scope, options.overrides ? { overrides: options.overrides } : {});
|
|
1298
|
-
const modules =
|
|
1374
|
+
const modules = collectModules2(scope);
|
|
1299
1375
|
const discovered = [];
|
|
1300
1376
|
for (const module of modules) {
|
|
1301
1377
|
const moduleMiddleware = module.options.middleware ?? [];
|
|
1302
|
-
for (const controller of
|
|
1378
|
+
for (const controller of readControllers2(module)) {
|
|
1303
1379
|
const routes = discoverRoutes(app.get(controller, module.ref));
|
|
1304
1380
|
if (routes.length === 0) {
|
|
1305
1381
|
throw new AppError8(`${controller.name} is registered as a controller but declares no routes. ` + "Add a @Get/@Post/... method, or move it to providers.");
|
|
@@ -1319,6 +1395,129 @@ class HttpFactory {
|
|
|
1319
1395
|
return new HttpApplication(app, discovered, options, root, websocket);
|
|
1320
1396
|
}
|
|
1321
1397
|
}
|
|
1398
|
+
// src/static/files.ts
|
|
1399
|
+
import { join, normalize, resolve } from "path";
|
|
1400
|
+
|
|
1401
|
+
// src/static/options.ts
|
|
1402
|
+
class StaticOptions {
|
|
1403
|
+
root;
|
|
1404
|
+
path;
|
|
1405
|
+
maxAge;
|
|
1406
|
+
immutable;
|
|
1407
|
+
constructor(init) {
|
|
1408
|
+
this.root = init.root;
|
|
1409
|
+
this.path = normalizePrefix(init.path ?? "/");
|
|
1410
|
+
this.maxAge = init.maxAge ?? 60;
|
|
1411
|
+
this.immutable = init.immutable ?? (() => false);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
Object.defineProperty(StaticOptions, Symbol.for("dunx.deps"), {
|
|
1415
|
+
value: () => [{ unresolved: "init: StaticOptionsInit" }]
|
|
1416
|
+
});
|
|
1417
|
+
var normalizePrefix = (path) => {
|
|
1418
|
+
const trimmed = path.split("/").filter(Boolean).join("/");
|
|
1419
|
+
return trimmed === "" ? "/" : `/${trimmed}`;
|
|
1420
|
+
};
|
|
1421
|
+
|
|
1422
|
+
// src/static/files.ts
|
|
1423
|
+
class StaticFiles {
|
|
1424
|
+
#options;
|
|
1425
|
+
#root;
|
|
1426
|
+
#prefix;
|
|
1427
|
+
constructor(options) {
|
|
1428
|
+
this.#options = options;
|
|
1429
|
+
this.#root = resolve(options.root);
|
|
1430
|
+
this.#prefix = options.path === "/" ? "/" : `${options.path}/`;
|
|
1431
|
+
}
|
|
1432
|
+
resolvePath(pathname) {
|
|
1433
|
+
const relative = pathname.startsWith(this.#prefix) ? pathname.slice(this.#prefix.length) : pathname.slice(this.#options.path.length);
|
|
1434
|
+
let decoded;
|
|
1435
|
+
try {
|
|
1436
|
+
decoded = decodeURIComponent(relative);
|
|
1437
|
+
} catch {
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
if (decoded.includes("\x00"))
|
|
1441
|
+
return;
|
|
1442
|
+
const candidate = resolve(join(this.#root, normalize(decoded)));
|
|
1443
|
+
if (candidate !== this.#root && !candidate.startsWith(`${this.#root}/`)) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
return candidate;
|
|
1447
|
+
}
|
|
1448
|
+
#cacheControl(pathname) {
|
|
1449
|
+
const { immutable, maxAge } = this.#options;
|
|
1450
|
+
return immutable(pathname) ? "public, max-age=31536000, immutable" : `public, max-age=${maxAge}`;
|
|
1451
|
+
}
|
|
1452
|
+
async handle(req, _ctx, next) {
|
|
1453
|
+
const { pathname } = new URL(req.url);
|
|
1454
|
+
if (pathname !== this.#options.path && !pathname.startsWith(this.#prefix)) {
|
|
1455
|
+
return next();
|
|
1456
|
+
}
|
|
1457
|
+
if (req.method !== "GET" && req.method !== "HEAD")
|
|
1458
|
+
return next();
|
|
1459
|
+
const path = this.resolvePath(pathname);
|
|
1460
|
+
if (path === undefined)
|
|
1461
|
+
return next();
|
|
1462
|
+
const file = Bun.file(path);
|
|
1463
|
+
if (!await file.exists())
|
|
1464
|
+
return next();
|
|
1465
|
+
return new Response(file, {
|
|
1466
|
+
headers: {
|
|
1467
|
+
"cache-control": this.#cacheControl(pathname),
|
|
1468
|
+
...file.type === "" ? { "content-type": "application/octet-stream" } : {},
|
|
1469
|
+
"x-content-type-options": "nosniff"
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
Object.defineProperty(StaticFiles, Symbol.for("dunx.deps"), {
|
|
1475
|
+
value: () => [StaticOptions]
|
|
1476
|
+
});
|
|
1477
|
+
// src/static/module.ts
|
|
1478
|
+
import {
|
|
1479
|
+
Module,
|
|
1480
|
+
provide as provide2
|
|
1481
|
+
} from "@dunx/core";
|
|
1482
|
+
var files = () => provide2(StaticFiles, {
|
|
1483
|
+
useFactory: (options) => new StaticFiles(options),
|
|
1484
|
+
inject: [StaticOptions]
|
|
1485
|
+
});
|
|
1486
|
+
var _dec = [
|
|
1487
|
+
Module({})
|
|
1488
|
+
];
|
|
1489
|
+
var _init = __decoratorStart(undefined);
|
|
1490
|
+
|
|
1491
|
+
class StaticModule {
|
|
1492
|
+
static forRoot(init) {
|
|
1493
|
+
return {
|
|
1494
|
+
module: StaticModule,
|
|
1495
|
+
exports: [StaticOptions, StaticFiles],
|
|
1496
|
+
providers: [
|
|
1497
|
+
provide2(StaticOptions, { useValue: new StaticOptions(init) }),
|
|
1498
|
+
files()
|
|
1499
|
+
]
|
|
1500
|
+
};
|
|
1501
|
+
}
|
|
1502
|
+
static forRootAsync(config) {
|
|
1503
|
+
return {
|
|
1504
|
+
module: StaticModule,
|
|
1505
|
+
...config.imports && { imports: config.imports },
|
|
1506
|
+
exports: [StaticOptions, StaticFiles],
|
|
1507
|
+
providers: [
|
|
1508
|
+
provide2(StaticOptions, {
|
|
1509
|
+
useFactory: async (...deps) => new StaticOptions(await config.useFactory(...deps)),
|
|
1510
|
+
inject: config.inject ?? []
|
|
1511
|
+
}),
|
|
1512
|
+
files()
|
|
1513
|
+
]
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
StaticModule = __decorateElement(_init, 0, "StaticModule", _dec, StaticModule);
|
|
1518
|
+
__runInitializers(_init, 1, StaticModule);
|
|
1519
|
+
__decoratorMetadata(_init, StaticModule);
|
|
1520
|
+
let _StaticModule = StaticModule;
|
|
1322
1521
|
// src/ws/decorators.ts
|
|
1323
1522
|
var Gateway = (path = "/") => (target) => {
|
|
1324
1523
|
markGateway(target, path);
|
|
@@ -1435,7 +1634,9 @@ export {
|
|
|
1435
1634
|
withUpgradeRoutes,
|
|
1436
1635
|
withCors,
|
|
1437
1636
|
toErrorMapper,
|
|
1637
|
+
routesOf,
|
|
1438
1638
|
preflight,
|
|
1639
|
+
normalizePrefix,
|
|
1439
1640
|
normalizePath,
|
|
1440
1641
|
metaOf,
|
|
1441
1642
|
metaKey,
|
|
@@ -1445,6 +1646,7 @@ export {
|
|
|
1445
1646
|
isGateway,
|
|
1446
1647
|
isErrorFilter,
|
|
1447
1648
|
guardsOf,
|
|
1649
|
+
gatewaysOf,
|
|
1448
1650
|
errorMapper,
|
|
1449
1651
|
encodeRelay,
|
|
1450
1652
|
encode,
|
|
@@ -1466,6 +1668,9 @@ export {
|
|
|
1466
1668
|
ValidationError,
|
|
1467
1669
|
UseGuards,
|
|
1468
1670
|
UNMATCHED,
|
|
1671
|
+
StaticOptions,
|
|
1672
|
+
StaticModule,
|
|
1673
|
+
StaticFiles,
|
|
1469
1674
|
Roles,
|
|
1470
1675
|
RequestLoggingMiddleware,
|
|
1471
1676
|
RedisRelay,
|
|
@@ -1499,5 +1704,5 @@ export {
|
|
|
1499
1704
|
ApiHidden
|
|
1500
1705
|
};
|
|
1501
1706
|
|
|
1502
|
-
//# debugId=
|
|
1707
|
+
//# debugId=70611CF4C37807EE64756E2164756E21
|
|
1503
1708
|
//# sourceMappingURL=index.js.map
|