open-nest 0.0.0-stage → 0.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,958 @@
1
+ import { BadRequestException, HttpException, Injectable, PayloadTooLargeException, RequestMethod, StreamableFile, VERSION_NEUTRAL, VersioningType, mixin } from "@nestjs/common";
2
+ import { AbstractHttpAdapter, NestFactory } from "@nestjs/core";
3
+ import { Readable } from "node:stream";
4
+ //#region src/lib/events.ts
5
+ var Emitter = class {
6
+ listeners = /* @__PURE__ */ new Map();
7
+ on(event, fn) {
8
+ let set = this.listeners.get(event);
9
+ if (!set) {
10
+ set = /* @__PURE__ */ new Set();
11
+ this.listeners.set(event, set);
12
+ }
13
+ set.add(fn);
14
+ return this;
15
+ }
16
+ once(event, fn) {
17
+ const wrapped = (...args) => {
18
+ this.removeListener(event, fn);
19
+ fn(...args);
20
+ };
21
+ wrapped.original = fn;
22
+ return this.on(event, wrapped);
23
+ }
24
+ removeListener(event, fn) {
25
+ const set = this.listeners.get(event);
26
+ if (!set) return this;
27
+ for (const listener of set) if (listener === fn || listener.original === fn) set.delete(listener);
28
+ return this;
29
+ }
30
+ emit(event, ...args) {
31
+ const set = this.listeners.get(event);
32
+ if (!set) return;
33
+ for (const fn of Array.from(set)) fn(...args);
34
+ }
35
+ };
36
+ //#endregion
37
+ //#region src/lib/request.ts
38
+ var FetchSocket = class extends Emitter {
39
+ destroyed = false;
40
+ readable = true;
41
+ writable = true;
42
+ setKeepAlive() {}
43
+ setNoDelay() {}
44
+ setTimeout() {}
45
+ close() {
46
+ if (this.destroyed) return;
47
+ this.destroyed = true;
48
+ this.emit("close");
49
+ }
50
+ };
51
+ function createRequest(input, socket) {
52
+ const url = new URL(input.url);
53
+ const headers = {};
54
+ input.headers.forEach((value, key) => {
55
+ const prev = headers[key];
56
+ if (prev == null) headers[key] = value;
57
+ else if (Array.isArray(prev)) prev.push(value);
58
+ else headers[key] = [prev, value];
59
+ });
60
+ const query = {};
61
+ for (const key of new Set(url.searchParams.keys())) {
62
+ const all = url.searchParams.getAll(key);
63
+ const first = all[0];
64
+ if (first == null) continue;
65
+ query[key] = all.length > 1 ? all : first;
66
+ }
67
+ const forwarded = input.headers.get("x-forwarded-for")?.split(",")[0]?.trim();
68
+ const host = input.headers.get("host") ?? url.hostname;
69
+ return {
70
+ raw: input,
71
+ method: input.method.toUpperCase(),
72
+ url: url.pathname + url.search,
73
+ originalUrl: url.pathname + url.search,
74
+ path: url.pathname,
75
+ headers,
76
+ query,
77
+ params: {},
78
+ body: void 0,
79
+ ip: forwarded ?? "",
80
+ hostname: host.split(":")[0] ?? "",
81
+ socket
82
+ };
83
+ }
84
+ //#endregion
85
+ //#region src/lib/response.ts
86
+ var FetchResponse = class extends Emitter {
87
+ statusCode = 200;
88
+ headersSent = false;
89
+ writableEnded = false;
90
+ destroyed = false;
91
+ writable = true;
92
+ socket;
93
+ headers = new Headers();
94
+ controller;
95
+ wrote = false;
96
+ streamClosed = false;
97
+ drainWaiters = [];
98
+ resolveReady;
99
+ readyPromise;
100
+ stream = new ReadableStream({
101
+ start: (controller) => {
102
+ this.controller = controller;
103
+ },
104
+ pull: () => {
105
+ const waiters = this.drainWaiters.splice(0);
106
+ for (const resume of waiters) resume();
107
+ this.emit("drain");
108
+ },
109
+ cancel: () => {
110
+ this.destroy();
111
+ }
112
+ });
113
+ constructor(socket) {
114
+ super();
115
+ this.socket = socket;
116
+ this.readyPromise = new Promise((resolve) => {
117
+ this.resolveReady = resolve;
118
+ });
119
+ }
120
+ ready() {
121
+ return this.readyPromise;
122
+ }
123
+ setHeader(name, value) {
124
+ this.headers.set(name, value);
125
+ }
126
+ appendHeader(name, value) {
127
+ this.headers.append(name, value);
128
+ }
129
+ getHeader(name) {
130
+ return this.headers.get(name);
131
+ }
132
+ removeHeader(name) {
133
+ this.headers.delete(name);
134
+ }
135
+ getHeaders() {
136
+ return Object.fromEntries(this.headers.entries());
137
+ }
138
+ status(code) {
139
+ this.statusCode = code;
140
+ return this;
141
+ }
142
+ writeHead(status, headers) {
143
+ this.statusCode = status;
144
+ if (headers) for (const [name, value] of Object.entries(headers)) if (Array.isArray(value)) for (const item of value) this.headers.append(name, String(item));
145
+ else this.headers.set(name, String(value));
146
+ this.commit();
147
+ }
148
+ flushHeaders() {
149
+ this.commit();
150
+ }
151
+ write(chunk, encoding, cb) {
152
+ if (typeof encoding === "function") {
153
+ cb = encoding;
154
+ encoding = void 0;
155
+ }
156
+ if (this.writableEnded) {
157
+ cb?.();
158
+ return false;
159
+ }
160
+ if (!this.headersSent) this.writeHead(this.statusCode);
161
+ const bytes = chunk instanceof Uint8Array ? chunk : new TextEncoder().encode(typeof chunk === "string" ? chunk : String(chunk));
162
+ this.controller.enqueue(bytes);
163
+ this.wrote = true;
164
+ if (!(this.stream.locked && (this.controller.desiredSize ?? 0) <= 0)) {
165
+ cb?.();
166
+ return true;
167
+ }
168
+ if (cb) this.drainWaiters.push(() => cb?.());
169
+ return false;
170
+ }
171
+ end(chunk, encoding, cb) {
172
+ if (typeof chunk === "function") {
173
+ cb = chunk;
174
+ chunk = void 0;
175
+ } else if (typeof encoding === "function") {
176
+ cb = encoding;
177
+ encoding = void 0;
178
+ }
179
+ if (this.writableEnded) {
180
+ cb?.();
181
+ return;
182
+ }
183
+ if (chunk != null) this.write(chunk, encoding);
184
+ this.writableEnded = true;
185
+ this.writable = false;
186
+ if (!this.headersSent) this.commit();
187
+ else if (this.wrote) this.closeStream();
188
+ this.emit("finish");
189
+ this.emit("close");
190
+ cb?.();
191
+ }
192
+ closeStream() {
193
+ if (this.streamClosed) return;
194
+ this.streamClosed = true;
195
+ try {
196
+ this.controller.close();
197
+ } catch {}
198
+ }
199
+ send(body) {
200
+ this.end(body);
201
+ }
202
+ json(body) {
203
+ if (!this.headers.has("content-type")) this.setHeader("content-type", "application/json; charset=utf-8");
204
+ this.end(JSON.stringify(body));
205
+ }
206
+ destroy() {
207
+ if (this.destroyed) return;
208
+ this.destroyed = true;
209
+ this.writable = false;
210
+ this.socket.close();
211
+ if (!this.headersSent) {
212
+ this.headersSent = true;
213
+ this.writableEnded = true;
214
+ this.closeStream();
215
+ this.resolveReady(new Response(null, { status: 499 }));
216
+ }
217
+ this.emit("close");
218
+ }
219
+ commit() {
220
+ if (this.headersSent) return;
221
+ this.headersSent = true;
222
+ const empty = this.writableEnded && !this.wrote;
223
+ if (empty) this.closeStream();
224
+ this.resolveReady(new Response(empty ? null : this.stream, {
225
+ status: this.statusCode,
226
+ headers: this.headers
227
+ }));
228
+ }
229
+ };
230
+ //#endregion
231
+ //#region src/lib/express.ts
232
+ var ExpressRequest = class extends Readable {
233
+ raw;
234
+ method;
235
+ originalUrl;
236
+ headers;
237
+ query;
238
+ params;
239
+ body;
240
+ _body;
241
+ rawBody;
242
+ ip;
243
+ hostname;
244
+ socket;
245
+ file;
246
+ files;
247
+ urlValue;
248
+ started = false;
249
+ resumeRead;
250
+ constructor(input, socket) {
251
+ super();
252
+ const base = createRequest(input, socket);
253
+ this.raw = base.raw;
254
+ this.method = base.method;
255
+ this.originalUrl = base.originalUrl;
256
+ this.headers = base.headers;
257
+ this.query = base.query;
258
+ this.params = base.params;
259
+ this.body = base.body;
260
+ this.ip = base.ip;
261
+ this.hostname = base.hostname;
262
+ this.socket = base.socket;
263
+ this.urlValue = base.url;
264
+ if (input.body && this.headers["content-length"] == null && this.headers["transfer-encoding"] == null) this.headers["transfer-encoding"] = "chunked";
265
+ this.on("end", () => {
266
+ this._body = true;
267
+ });
268
+ }
269
+ get finished() {
270
+ return this._body === true;
271
+ }
272
+ get url() {
273
+ return this.urlValue;
274
+ }
275
+ set url(value) {
276
+ this.urlValue = value;
277
+ }
278
+ get path() {
279
+ const query = this.urlValue.indexOf("?");
280
+ return (query === -1 ? this.urlValue : this.urlValue.slice(0, query)) || "/";
281
+ }
282
+ get(name) {
283
+ const value = this.headers[name.toLowerCase()];
284
+ if (Array.isArray(value)) return value[0];
285
+ return value;
286
+ }
287
+ header(name) {
288
+ return this.get(name);
289
+ }
290
+ _read() {
291
+ if (!this.started) {
292
+ this.started = true;
293
+ this.drain();
294
+ return;
295
+ }
296
+ this.resumeRead?.();
297
+ this.resumeRead = void 0;
298
+ }
299
+ async drain() {
300
+ const body = this.raw.body;
301
+ if (!body) {
302
+ this.push(null);
303
+ return;
304
+ }
305
+ const reader = body.getReader();
306
+ try {
307
+ for (;;) {
308
+ const { done, value } = await reader.read();
309
+ if (done) break;
310
+ const chunk = Buffer.from(value);
311
+ if (!this.push(chunk)) await new Promise((resolve) => {
312
+ this.resumeRead = resolve;
313
+ });
314
+ }
315
+ this.push(null);
316
+ } catch (error) {
317
+ this.destroy(error instanceof Error ? error : new Error(String(error)));
318
+ }
319
+ }
320
+ };
321
+ var ExpressResponse = class extends FetchResponse {
322
+ req;
323
+ constructor(socket, req) {
324
+ super(socket);
325
+ this.req = req;
326
+ }
327
+ send(body) {
328
+ if (body == null || body === "") {
329
+ this.end();
330
+ return;
331
+ }
332
+ if (typeof body === "string") {
333
+ if (!this.getHeader("content-type")) this.setHeader("content-type", "text/html; charset=utf-8");
334
+ this.end(body);
335
+ return;
336
+ }
337
+ if (body instanceof Uint8Array) {
338
+ if (!this.getHeader("content-type")) this.setHeader("content-type", "application/octet-stream");
339
+ this.end(body);
340
+ return;
341
+ }
342
+ this.json(body);
343
+ }
344
+ set(field, value) {
345
+ if (typeof field === "string") {
346
+ this.writeHeader(field, value ?? "");
347
+ return this;
348
+ }
349
+ for (const [name, item] of Object.entries(field)) this.writeHeader(name, item);
350
+ return this;
351
+ }
352
+ redirect(statusOrUrl, url) {
353
+ const status = typeof statusOrUrl === "number" ? statusOrUrl : 302;
354
+ const location = typeof statusOrUrl === "string" ? statusOrUrl : url ?? "/";
355
+ this.status(status);
356
+ this.setHeader("location", location);
357
+ this.end();
358
+ }
359
+ writeHeader(name, value) {
360
+ if (Array.isArray(value)) {
361
+ for (const item of value) this.appendHeader(name, String(item));
362
+ return;
363
+ }
364
+ this.setHeader(name, String(value));
365
+ }
366
+ };
367
+ function errorStatus(err) {
368
+ if (!err || typeof err !== "object") return void 0;
369
+ const record = err;
370
+ if (typeof record.status === "number") return record.status;
371
+ if (typeof record.statusCode === "number") return record.statusCode;
372
+ }
373
+ function asHttpException(err) {
374
+ if (err instanceof HttpException) return err;
375
+ const status = errorStatus(err);
376
+ if (status == null) return err;
377
+ const message = err && typeof err === "object" && "message" in err && typeof err.message === "string" ? err.message : "Error";
378
+ return new HttpException(message, status);
379
+ }
380
+ function mountedUrl(url, mount) {
381
+ const query = url.indexOf("?");
382
+ const pathname = query === -1 ? url : url.slice(0, query);
383
+ const search = query === -1 ? "" : url.slice(query);
384
+ let rest = pathname.slice(mount.length);
385
+ if (!rest) rest = "/";
386
+ else if (!rest.startsWith("/")) rest = `/${rest}`;
387
+ return rest + search;
388
+ }
389
+ //#endregion
390
+ //#region src/lib/router.ts
391
+ const TOKEN = /:([A-Za-z_][A-Za-z0-9_]*)(\?)?|\{\*([A-Za-z_][A-Za-z0-9_]*)\}|\*([A-Za-z_][A-Za-z0-9_]*)/g;
392
+ function normalizeMount(path) {
393
+ let source = path.endsWith("$") ? path.slice(0, -1) : path;
394
+ if (!source.startsWith("/")) source = `/${source}`;
395
+ if (source.length > 1 && source.endsWith("/")) source = source.slice(0, -1);
396
+ return source;
397
+ }
398
+ function escapeLiteral(value) {
399
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
400
+ }
401
+ function compile(path, kind) {
402
+ const exact = kind === "exact" || path.endsWith("$");
403
+ let source = path.endsWith("$") ? path.slice(0, -1) : path;
404
+ if (!source.startsWith("/")) source = `/${source}`;
405
+ if (/[()+]/.test(source) || /(?:^|\/)\*(?![A-Za-z_{])/.test(source)) throw new TypeError(`Unsupported route path "${path}". Use :param, :param?, {*name}, or *name.`);
406
+ let pattern = "^";
407
+ let cursor = 0;
408
+ for (const token of source.matchAll(TOKEN)) {
409
+ const index = token.index ?? 0;
410
+ pattern += escapeLiteral(source.slice(cursor, index));
411
+ const braceSplat = token[3];
412
+ const starSplat = token[4];
413
+ const name = token[1] ?? braceSplat ?? starSplat ?? "path";
414
+ const optional = token[2] === "?";
415
+ if (braceSplat != null || optional) {
416
+ if (pattern.endsWith("/")) pattern = pattern.slice(0, -1);
417
+ pattern += braceSplat != null ? `(?:/(?<${name}>.*))?` : `(?:/(?<${name}>[^/]+))?`;
418
+ } else if (starSplat != null) pattern += `(?<${name}>.*)`;
419
+ else pattern += `(?<${name}>[^/]+)`;
420
+ cursor = index + token[0].length;
421
+ }
422
+ pattern += escapeLiteral(source.slice(cursor));
423
+ if (source === "/") pattern = exact ? "^/?$" : "^/.*$";
424
+ else pattern += exact ? "/?$" : "(?:/.*)?$";
425
+ const re = new RegExp(pattern);
426
+ return (pathname) => {
427
+ const found = re.exec(pathname);
428
+ if (!found) return null;
429
+ const params = {};
430
+ for (const [key, value] of Object.entries(found.groups ?? {})) if (value != null) params[key] = value;
431
+ return params;
432
+ };
433
+ }
434
+ var Router = class {
435
+ layers = [];
436
+ use(pathOrHandler, handler) {
437
+ if (Array.isArray(pathOrHandler)) {
438
+ for (const path of pathOrHandler) this.add(null, path, handler, "prefix");
439
+ return;
440
+ }
441
+ this.add(null, pathOrHandler, handler, "prefix");
442
+ }
443
+ get(path, handler) {
444
+ this.add("GET", path, handler, "exact");
445
+ }
446
+ post(path, handler) {
447
+ this.add("POST", path, handler, "exact");
448
+ }
449
+ head(path, handler) {
450
+ this.add("HEAD", path, handler, "exact");
451
+ }
452
+ delete(path, handler) {
453
+ this.add("DELETE", path, handler, "exact");
454
+ }
455
+ put(path, handler) {
456
+ this.add("PUT", path, handler, "exact");
457
+ }
458
+ patch(path, handler) {
459
+ this.add("PATCH", path, handler, "exact");
460
+ }
461
+ options(path, handler) {
462
+ this.add("OPTIONS", path, handler, "exact");
463
+ }
464
+ all(path, handler) {
465
+ this.add(null, path, handler, "exact");
466
+ }
467
+ propfind(path, handler) {
468
+ this.add("PROPFIND", path, handler, "exact");
469
+ }
470
+ proppatch(path, handler) {
471
+ this.add("PROPPATCH", path, handler, "exact");
472
+ }
473
+ mkcol(path, handler) {
474
+ this.add("MKCOL", path, handler, "exact");
475
+ }
476
+ copy(path, handler) {
477
+ this.add("COPY", path, handler, "exact");
478
+ }
479
+ move(path, handler) {
480
+ this.add("MOVE", path, handler, "exact");
481
+ }
482
+ lock(path, handler) {
483
+ this.add("LOCK", path, handler, "exact");
484
+ }
485
+ unlock(path, handler) {
486
+ this.add("UNLOCK", path, handler, "exact");
487
+ }
488
+ search(path, handler) {
489
+ this.add("SEARCH", path, handler, "exact");
490
+ }
491
+ query(path, handler) {
492
+ this.add("QUERY", path, handler, "exact");
493
+ }
494
+ add(method, path, handler, kind) {
495
+ const fn = typeof path === "function" ? path : handler;
496
+ const route = typeof path === "function" ? "/" : path;
497
+ if (!fn) return;
498
+ const mount = kind === "prefix" ? normalizeMount(route) : null;
499
+ this.layers.push({
500
+ method,
501
+ mount,
502
+ match: compile(route, kind),
503
+ handler: fn,
504
+ error: fn.length >= 4
505
+ });
506
+ }
507
+ handle(req, res) {
508
+ const dispatch = (index, err) => {
509
+ const layer = this.layers[index];
510
+ if (!layer) {
511
+ if (!res.headersSent) {
512
+ const status = err ? errorStatus(err) ?? 500 : 404;
513
+ const message = err && typeof err === "object" && "message" in err && typeof err.message === "string" ? err.message : err ? "Internal server error" : "Not Found";
514
+ res.status(status).json({
515
+ statusCode: status,
516
+ message
517
+ });
518
+ }
519
+ return;
520
+ }
521
+ if (err) {
522
+ if (!layer.error) return dispatch(index + 1, err);
523
+ Promise.resolve().then(() => layer.handler(err, req, res, (nextErr) => dispatch(index + 1, nextErr))).catch((nextErr) => dispatch(index + 1, nextErr));
524
+ return;
525
+ }
526
+ if (layer.error) return dispatch(index + 1);
527
+ if (layer.method && layer.method !== req.method) return dispatch(index + 1);
528
+ const params = layer.match(req.path);
529
+ if (!params) return dispatch(index + 1);
530
+ req.params = params;
531
+ const previous = req.url;
532
+ if (layer.mount && layer.mount !== "/") req.url = mountedUrl(previous, layer.mount);
533
+ const restore = () => {
534
+ req.url = previous;
535
+ };
536
+ Promise.resolve().then(() => layer.handler(req, res, (nextErr) => {
537
+ restore();
538
+ dispatch(index + 1, nextErr);
539
+ })).catch((nextErr) => {
540
+ restore();
541
+ dispatch(index + 1, nextErr);
542
+ });
543
+ };
544
+ dispatch(0);
545
+ }
546
+ };
547
+ //#endregion
548
+ //#region src/lib/version.ts
549
+ function headerValue(headers, name) {
550
+ const value = headers[name.toLowerCase()];
551
+ if (Array.isArray(value)) return value[0];
552
+ return value;
553
+ }
554
+ function matches(version, found) {
555
+ if (found == null) return Array.isArray(version) && version.includes(VERSION_NEUTRAL);
556
+ if (Array.isArray(version)) return version.includes(found);
557
+ return version === found;
558
+ }
559
+ function matchesCustom(version, extracted) {
560
+ const values = Array.isArray(extracted) ? extracted : [extracted];
561
+ if (values.length === 0) return Array.isArray(version) && version.includes(VERSION_NEUTRAL);
562
+ if (Array.isArray(version)) return values.some((value) => version.includes(value));
563
+ return typeof version === "string" && values.includes(version);
564
+ }
565
+ function mediaTypeVersion(accept, key) {
566
+ for (const range of accept?.split(",") ?? []) for (const parameter of range.split(";").slice(1)) {
567
+ const trimmed = parameter.trim();
568
+ if (trimmed.startsWith(key)) return trimmed.slice(key.length);
569
+ }
570
+ }
571
+ function applyVersionFilter(handler, version, options) {
572
+ if (version === VERSION_NEUTRAL || options.type === VersioningType.URI) return (req, res, next) => handler(req, res, next);
573
+ return (req, res, next) => {
574
+ if (options.type === VersioningType.HEADER) {
575
+ if (matches(version, headerValue(req.headers, options.header))) return handler(req, res, next);
576
+ return next();
577
+ }
578
+ if (options.type === VersioningType.MEDIA_TYPE) {
579
+ if (matches(version, mediaTypeVersion(headerValue(req.headers, "accept"), options.key))) return handler(req, res, next);
580
+ return next();
581
+ }
582
+ if (options.type === VersioningType.CUSTOM) {
583
+ if (matchesCustom(version, options.extractor(req))) return handler(req, res, next);
584
+ return next();
585
+ }
586
+ throw new Error("Unsupported versioning options");
587
+ };
588
+ }
589
+ //#endregion
590
+ //#region \0@oxc-project+runtime@0.148.0/helpers/esm/decorate.js
591
+ function __decorate(decorators, target, key, desc) {
592
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
593
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
594
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
595
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
596
+ }
597
+ //#endregion
598
+ //#region src/lib/multipart/index.ts
599
+ async function readForm(req, limits) {
600
+ if (!(req.raw.headers.get("content-type") ?? "").toLowerCase().includes("multipart/form-data")) throw new BadRequestException("Expected multipart/form-data");
601
+ const form = await req.raw.formData();
602
+ const body = {};
603
+ const files = [];
604
+ let fields = 0;
605
+ for (const [fieldname, value] of form.entries()) {
606
+ if (typeof value === "string") {
607
+ fields += 1;
608
+ if (limits?.fields != null && fields > limits.fields) throw new PayloadTooLargeException();
609
+ const prev = body[fieldname];
610
+ if (prev == null) body[fieldname] = value;
611
+ else if (Array.isArray(prev)) prev.push(value);
612
+ else body[fieldname] = [prev, value];
613
+ continue;
614
+ }
615
+ if (limits?.files != null && files.length >= limits.files) throw new PayloadTooLargeException();
616
+ const buffer = new Uint8Array(await value.arrayBuffer());
617
+ if (limits?.fileSize != null && buffer.byteLength > limits.fileSize) throw new PayloadTooLargeException();
618
+ files.push({
619
+ fieldname,
620
+ originalname: value.name,
621
+ encoding: "7bit",
622
+ mimetype: value.type,
623
+ buffer,
624
+ size: buffer.byteLength
625
+ });
626
+ }
627
+ req.body = body;
628
+ return files;
629
+ }
630
+ function FileInterceptor(field, options) {
631
+ let MixinInterceptor = class MixinInterceptor {
632
+ async intercept(context, next) {
633
+ const req = context.switchToHttp().getRequest();
634
+ const file = (await readForm(req, options?.limits)).find((item) => item.fieldname === field);
635
+ if (file) req.file = file;
636
+ return next.handle();
637
+ }
638
+ };
639
+ MixinInterceptor = __decorate([Injectable()], MixinInterceptor);
640
+ return mixin(MixinInterceptor);
641
+ }
642
+ function FilesInterceptor(field, maxCount, options) {
643
+ let MixinInterceptor = class MixinInterceptor {
644
+ async intercept(context, next) {
645
+ const req = context.switchToHttp().getRequest();
646
+ const matched = (await readForm(req, options?.limits)).filter((item) => item.fieldname === field);
647
+ if (maxCount != null && matched.length > maxCount) throw new PayloadTooLargeException();
648
+ req.files = matched;
649
+ return next.handle();
650
+ }
651
+ };
652
+ MixinInterceptor = __decorate([Injectable()], MixinInterceptor);
653
+ return mixin(MixinInterceptor);
654
+ }
655
+ function AnyFilesInterceptor(options) {
656
+ let MixinInterceptor = class MixinInterceptor {
657
+ async intercept(context, next) {
658
+ const req = context.switchToHttp().getRequest();
659
+ req.files = await readForm(req, options?.limits);
660
+ return next.handle();
661
+ }
662
+ };
663
+ MixinInterceptor = __decorate([Injectable()], MixinInterceptor);
664
+ return mixin(MixinInterceptor);
665
+ }
666
+ //#endregion
667
+ //#region src/fetch/index.ts
668
+ const BODY_LIMIT = 1048576;
669
+ var FetchAdapter = class extends AbstractHttpAdapter {
670
+ bodyLimit = BODY_LIMIT;
671
+ rawBody = false;
672
+ shuttingDown = false;
673
+ parsersReady = false;
674
+ constructor() {
675
+ super(new Router());
676
+ }
677
+ get router() {
678
+ return this.getInstance();
679
+ }
680
+ handle(input) {
681
+ if (this.shuttingDown) return Promise.resolve(new Response("Service Unavailable", {
682
+ status: 503,
683
+ headers: { connection: "close" }
684
+ }));
685
+ const socket = new FetchSocket();
686
+ const req = new ExpressRequest(input, socket);
687
+ const res = new ExpressResponse(socket, req);
688
+ const onAbort = () => {
689
+ socket.close();
690
+ queueMicrotask(() => {
691
+ if (!res.headersSent) res.end();
692
+ });
693
+ };
694
+ if (input.signal.aborted) onAbort();
695
+ else input.signal.addEventListener("abort", onAbort, { once: true });
696
+ this.router.handle(req, res);
697
+ return res.ready();
698
+ }
699
+ listen() {
700
+ throw new Error("FetchAdapter does not listen. Pass createFetcher() to the runtime fetch handler.");
701
+ }
702
+ initHttpServer(options) {
703
+ this.rawBody = options.rawBody === true;
704
+ if (options.return503OnClosing) this.router.use((req, res, next) => {
705
+ if (!this.shuttingDown) return next();
706
+ res.status(503).send("Service Unavailable");
707
+ });
708
+ }
709
+ beforeClose() {
710
+ this.shuttingDown = true;
711
+ }
712
+ close() {}
713
+ useStaticAssets(_root, _options) {
714
+ return this;
715
+ }
716
+ setViewEngine() {
717
+ return this;
718
+ }
719
+ getRequestHostname(request) {
720
+ return request.hostname;
721
+ }
722
+ getRequestMethod(request) {
723
+ return request.method;
724
+ }
725
+ getRequestUrl(request) {
726
+ return request.originalUrl;
727
+ }
728
+ status(response, statusCode) {
729
+ return response.status(statusCode);
730
+ }
731
+ reply(response, body, statusCode) {
732
+ if (statusCode != null) response.status(statusCode);
733
+ if (body == null) {
734
+ response.end();
735
+ return;
736
+ }
737
+ if (body instanceof StreamableFile) {
738
+ const headers = body.getHeaders();
739
+ if (!response.getHeader("content-type")) response.setHeader("content-type", headers.type);
740
+ if (headers.disposition && !response.getHeader("content-disposition")) {
741
+ const disposition = Array.isArray(headers.disposition) ? headers.disposition.join("; ") : headers.disposition;
742
+ response.setHeader("content-disposition", disposition);
743
+ }
744
+ if (headers.length != null && !response.getHeader("content-length")) response.setHeader("content-length", String(headers.length));
745
+ const stream = body.getStream();
746
+ stream.once("error", (err) => {
747
+ if (!response.headersSent) body.errorHandler(err, response);
748
+ else body.errorLogger(err);
749
+ });
750
+ response.once("close", () => {
751
+ if (!stream.readableEnded) stream.destroy();
752
+ });
753
+ stream.pipe(response);
754
+ return;
755
+ }
756
+ if (typeof body === "object") {
757
+ response.json(body);
758
+ return;
759
+ }
760
+ const text = typeof body === "string" ? body : typeof body === "number" || typeof body === "boolean" || typeof body === "bigint" ? String(body) : "";
761
+ response.send(text);
762
+ }
763
+ end(response, message) {
764
+ response.end(message);
765
+ }
766
+ render() {
767
+ throw new Error("FetchAdapter has no view engine.");
768
+ }
769
+ redirect(response, statusCode, url) {
770
+ response.status(statusCode);
771
+ response.setHeader("location", url);
772
+ response.end();
773
+ }
774
+ isHeadersSent(response) {
775
+ return response.headersSent;
776
+ }
777
+ getHeader(response, name) {
778
+ return response.getHeader(name);
779
+ }
780
+ setHeader(response, name, value) {
781
+ response.setHeader(name, value);
782
+ }
783
+ appendHeader(response, name, value) {
784
+ response.appendHeader(name, value);
785
+ }
786
+ setErrorHandler(handler) {
787
+ this.router.use(function(err, req, res, next) {
788
+ return handler(asHttpException(err), req, res, next);
789
+ });
790
+ }
791
+ setNotFoundHandler(handler) {
792
+ this.router.use((req, res, next) => handler(req, res, next));
793
+ }
794
+ getType() {
795
+ return "fetch";
796
+ }
797
+ isRouteOrderSensitive() {
798
+ return true;
799
+ }
800
+ applyVersionFilter(handler, version, versioningOptions) {
801
+ return applyVersionFilter(handler, version, versioningOptions);
802
+ }
803
+ createMiddlewareFactory(method) {
804
+ return (path, callback) => {
805
+ const exact = path.endsWith("$");
806
+ const verb = method === RequestMethod.ALL ? null : RequestMethod[method];
807
+ this.router.add(verb, exact ? path.slice(0, -1) : path, callback, exact ? "exact" : "prefix");
808
+ };
809
+ }
810
+ registerParserMiddleware() {
811
+ if (this.parsersReady) return;
812
+ this.parsersReady = true;
813
+ this.router.use(async (req, res, next) => {
814
+ if (req._body || req.method === "GET" || req.method === "HEAD" || !req.raw.body) return next();
815
+ const type = req.raw.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
816
+ if (type.startsWith("multipart/")) return next();
817
+ const json = type === "application/json" || type.endsWith("+json");
818
+ const urlencoded = type === "application/x-www-form-urlencoded";
819
+ if (!json && !urlencoded) {
820
+ req.body = req.raw.body;
821
+ return next();
822
+ }
823
+ if (!(req instanceof ExpressRequest)) return next();
824
+ let bytes;
825
+ try {
826
+ bytes = await readLimited(req, this.bodyLimit);
827
+ } catch (error) {
828
+ return next(error);
829
+ }
830
+ if (this.rawBody) req.rawBody = bytes;
831
+ const text = new TextDecoder().decode(bytes);
832
+ if (urlencoded) {
833
+ const params = new URLSearchParams(text);
834
+ const body = {};
835
+ for (const key of new Set(params.keys())) {
836
+ const all = params.getAll(key);
837
+ const first = all[0];
838
+ if (first == null) continue;
839
+ body[key] = all.length > 1 ? all : first;
840
+ }
841
+ req.body = body;
842
+ req._body = true;
843
+ return next();
844
+ }
845
+ try {
846
+ req.body = text ? JSON.parse(text) : {};
847
+ } catch {
848
+ return next(new BadRequestException("Invalid JSON"));
849
+ }
850
+ req._body = true;
851
+ next();
852
+ });
853
+ }
854
+ enableCors(options) {
855
+ this.router.use((req, res, next) => {
856
+ const allowed = allowedOrigin(headerString(req.headers.origin), options?.origin, options?.credentials === true);
857
+ if (allowed) {
858
+ res.setHeader("access-control-allow-origin", allowed);
859
+ if (options?.credentials) res.setHeader("access-control-allow-credentials", "true");
860
+ if (allowed !== "*") res.appendHeader("vary", "Origin");
861
+ }
862
+ const methods = options?.methods ?? "GET,HEAD,PUT,PATCH,POST,DELETE";
863
+ const requestHeaders = headerString(req.headers["access-control-request-headers"]);
864
+ const allowHeaders = options?.allowedHeaders ?? requestHeaders ?? "";
865
+ res.setHeader("access-control-allow-methods", Array.isArray(methods) ? methods.join(",") : methods);
866
+ if (allowHeaders) res.setHeader("access-control-allow-headers", Array.isArray(allowHeaders) ? allowHeaders.join(",") : allowHeaders);
867
+ if (options?.exposedHeaders) {
868
+ const exposed = options.exposedHeaders;
869
+ res.setHeader("access-control-expose-headers", Array.isArray(exposed) ? exposed.join(",") : exposed);
870
+ }
871
+ if (options?.maxAge != null) res.setHeader("access-control-max-age", String(options.maxAge));
872
+ if (req.method === "OPTIONS" && req.headers["access-control-request-method"]) {
873
+ res.status(204).end();
874
+ return;
875
+ }
876
+ next();
877
+ });
878
+ }
879
+ setBodyLimit(limit) {
880
+ this.bodyLimit = limit;
881
+ }
882
+ };
883
+ function headerString(value) {
884
+ return Array.isArray(value) ? value[0] : value;
885
+ }
886
+ function allowedOrigin(origin, rule, credentials) {
887
+ const fallback = credentials ? origin : "*";
888
+ if (rule == null || rule === true || rule === "*") return fallback;
889
+ if (rule === false || !origin) return void 0;
890
+ if (rule instanceof RegExp) return rule.test(origin) ? origin : void 0;
891
+ if (typeof rule === "string") return rule === origin ? origin : void 0;
892
+ if (Array.isArray(rule)) return rule.some((item) => item instanceof RegExp ? item.test(origin) : item === origin) ? origin : void 0;
893
+ return rule(origin) ? origin : void 0;
894
+ }
895
+ function readLimited(req, limit) {
896
+ return new Promise((resolve, reject) => {
897
+ const chunks = [];
898
+ let total = 0;
899
+ let settled = false;
900
+ const fail = (error) => {
901
+ if (settled) return;
902
+ settled = true;
903
+ req.destroy();
904
+ reject(error);
905
+ };
906
+ req.on("data", (chunk) => {
907
+ total += chunk.byteLength;
908
+ if (total > limit) {
909
+ fail(new PayloadTooLargeException());
910
+ return;
911
+ }
912
+ chunks.push(chunk);
913
+ });
914
+ req.on("end", () => {
915
+ if (settled) return;
916
+ settled = true;
917
+ const bytes = new Uint8Array(total);
918
+ let offset = 0;
919
+ for (const chunk of chunks) {
920
+ bytes.set(chunk, offset);
921
+ offset += chunk.byteLength;
922
+ }
923
+ resolve(bytes);
924
+ });
925
+ req.on("error", (error) => {
926
+ if (settled) return;
927
+ settled = true;
928
+ reject(error);
929
+ });
930
+ req.resume();
931
+ });
932
+ }
933
+ function createFetcher({ module, configure, opts, bodyLimit }, adapter = new FetchAdapter()) {
934
+ if (bodyLimit != null) adapter.setBodyLimit(bodyLimit);
935
+ let pending;
936
+ const instance = () => {
937
+ if (pending) return pending;
938
+ pending = (async () => {
939
+ const app = await NestFactory.create(module, adapter, opts);
940
+ await configure?.(app);
941
+ await app.init();
942
+ return app;
943
+ })();
944
+ return pending;
945
+ };
946
+ const handler = (async (request) => {
947
+ await instance();
948
+ return adapter.handle(request);
949
+ });
950
+ handler.app = instance;
951
+ handler.close = async () => {
952
+ if (pending) await (await pending).close();
953
+ pending = void 0;
954
+ };
955
+ return handler;
956
+ }
957
+ //#endregion
958
+ export { FilesInterceptor as a, FileInterceptor as i, createFetcher as n, AnyFilesInterceptor as r, FetchAdapter as t };