@dunx/http 2.3.1 → 2.5.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.
- package/dist/{chunk-sz4pvqxy.js → chunk-jh7jk0bn.js} +56 -3
- package/dist/client/options.d.ts +12 -0
- package/dist/client.js +14 -5
- package/dist/compression/compression.d.ts +30 -0
- package/dist/compression/module.d.ts +20 -0
- package/dist/compression/negotiate.d.ts +12 -0
- package/dist/compression/options.d.ts +73 -0
- package/dist/health/controller.d.ts +15 -3
- package/dist/health/module.d.ts +5 -4
- package/dist/health/registry.d.ts +8 -0
- package/dist/health/report-schema.d.ts +14 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +426 -31
- package/dist/route/decorators.d.ts +6 -6
- package/dist/route/marker.d.ts +13 -0
- package/dist/route/schema.d.ts +84 -6
- package/dist/server/context.d.ts +10 -0
- package/dist/server/raw-body.d.ts +21 -0
- package/dist/server/request-logging.d.ts +40 -6
- package/dist/server/routes.d.ts +1 -1
- package/dist/server/trace-context.d.ts +51 -0
- package/package.json +3 -3
- package/dist/chunk-sz4pvqxy.js.map +0 -10
- package/dist/client.js.map +0 -15
- package/dist/index.js.map +0 -51
package/dist/index.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
HttpStatusCode,
|
|
4
|
+
TRACEPARENT_HEADER,
|
|
5
|
+
TRACESTATE_HEADER,
|
|
6
|
+
TraceContext,
|
|
4
7
|
__decorateElement,
|
|
5
8
|
__decoratorMetadata,
|
|
6
9
|
__decoratorStart,
|
|
7
10
|
__privateAdd,
|
|
8
11
|
__privateGet,
|
|
9
12
|
__runInitializers
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-jh7jk0bn.js";
|
|
11
14
|
|
|
12
15
|
// src/route/marker.ts
|
|
13
16
|
var ROUTE = Symbol.for("dunx.route");
|
|
14
17
|
var CONTROLLER = Symbol.for("dunx.controller");
|
|
18
|
+
var defaultStatusFor = (method) => method === "POST" ? HttpStatusCode.CREATED : HttpStatusCode.OK;
|
|
15
19
|
var resolvePath = (path) => typeof path === "function" ? path() : path;
|
|
16
20
|
var markRoute = (target, meta) => {
|
|
17
21
|
Object.defineProperty(target, ROUTE, { value: meta, configurable: true });
|
|
@@ -281,6 +285,7 @@ var buildContext = (route) => {
|
|
|
281
285
|
handler: route.handlerName,
|
|
282
286
|
method: route.method,
|
|
283
287
|
path: route.path,
|
|
288
|
+
parsesBody: route.options?.body !== undefined,
|
|
284
289
|
get: (key) => record.get(key.id)
|
|
285
290
|
});
|
|
286
291
|
};
|
|
@@ -970,6 +975,25 @@ import {
|
|
|
970
975
|
RequestContext as RequestContext2
|
|
971
976
|
} from "@dunx/core";
|
|
972
977
|
|
|
978
|
+
// src/server/raw-body.ts
|
|
979
|
+
var WANTED = Symbol.for("dunx.http.rawBody.wanted");
|
|
980
|
+
var TEXT = Symbol.for("dunx.http.rawBody.text");
|
|
981
|
+
|
|
982
|
+
class RawBody {
|
|
983
|
+
static want(req) {
|
|
984
|
+
req[WANTED] = true;
|
|
985
|
+
}
|
|
986
|
+
static wanted(req) {
|
|
987
|
+
return req[WANTED] === true;
|
|
988
|
+
}
|
|
989
|
+
static record(req, text) {
|
|
990
|
+
req[TEXT] = text;
|
|
991
|
+
}
|
|
992
|
+
static read(req) {
|
|
993
|
+
return req[TEXT];
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
973
997
|
// src/server/request-id.ts
|
|
974
998
|
var REQUEST_ID_HEADER = "x-request-id";
|
|
975
999
|
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -1016,6 +1040,7 @@ class RequestLoggingMiddleware {
|
|
|
1016
1040
|
#ignorePrefix;
|
|
1017
1041
|
#correlateIgnored;
|
|
1018
1042
|
#correlate;
|
|
1043
|
+
#trace;
|
|
1019
1044
|
constructor(logger, context, options = {}) {
|
|
1020
1045
|
this.logger = logger;
|
|
1021
1046
|
this.context = context;
|
|
@@ -1026,6 +1051,7 @@ class RequestLoggingMiddleware {
|
|
|
1026
1051
|
this.#ignorePrefix = options.ignorePrefix ?? [];
|
|
1027
1052
|
this.#correlateIgnored = options.correlateIgnored ?? false;
|
|
1028
1053
|
this.#correlate = options.correlate ?? true;
|
|
1054
|
+
this.#trace = options.trace ?? false;
|
|
1029
1055
|
}
|
|
1030
1056
|
#ignored(path) {
|
|
1031
1057
|
if (this.#ignore.size > 0 && this.#ignore.has(path))
|
|
@@ -1051,14 +1077,22 @@ class RequestLoggingMiddleware {
|
|
|
1051
1077
|
flow: "http",
|
|
1052
1078
|
context: `${ctx.controller}.${ctx.handler}`
|
|
1053
1079
|
};
|
|
1054
|
-
|
|
1080
|
+
if (this.#trace) {
|
|
1081
|
+
const trace = TraceContext.adopt(req, requestId);
|
|
1082
|
+
scope.traceId = trace.traceId;
|
|
1083
|
+
scope.spanId = trace.spanId;
|
|
1084
|
+
if (trace.parentSpanId !== undefined) {
|
|
1085
|
+
scope.parentSpanId = trace.parentSpanId;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return this.#correlate ? this.context.runWithContext(scope, () => this.#begin(req, ctx, url, mark, path, requestId, started, next, undefined)) : this.#begin(req, ctx, url, mark, path, requestId, started, next, scope);
|
|
1055
1089
|
}
|
|
1056
|
-
#begin(req, url, mark, path, requestId, started, next, scope) {
|
|
1090
|
+
#begin(req, ctx, url, mark, path, requestId, started, next, scope) {
|
|
1057
1091
|
const request = {};
|
|
1058
1092
|
if (mark !== -1) {
|
|
1059
1093
|
request["query"] = Object.fromEntries(new URLSearchParams(url.slice(mark + 1)));
|
|
1060
1094
|
}
|
|
1061
|
-
const body = this.#body(req);
|
|
1095
|
+
const body = this.#body(req, ctx);
|
|
1062
1096
|
if (body === undefined) {
|
|
1063
1097
|
request["userAgent"] = req.headers.get("user-agent");
|
|
1064
1098
|
return this.#dispatch(req, path, requestId, started, request, next, scope);
|
|
@@ -1070,6 +1104,18 @@ class RequestLoggingMiddleware {
|
|
|
1070
1104
|
return this.#dispatch(req, path, requestId, started, request, next, scope);
|
|
1071
1105
|
});
|
|
1072
1106
|
}
|
|
1107
|
+
#shared(req, request) {
|
|
1108
|
+
if (!this.#requestBody)
|
|
1109
|
+
return;
|
|
1110
|
+
if (request["body"] !== undefined)
|
|
1111
|
+
return;
|
|
1112
|
+
const text = RawBody.read(req);
|
|
1113
|
+
if (text === undefined)
|
|
1114
|
+
return;
|
|
1115
|
+
const value = parse(text, this.#limit);
|
|
1116
|
+
if (value !== undefined)
|
|
1117
|
+
request["body"] = value;
|
|
1118
|
+
}
|
|
1073
1119
|
#correlated(req, ctx, path, next) {
|
|
1074
1120
|
const requestId = RequestIds.assign(req);
|
|
1075
1121
|
const stamp = (response) => {
|
|
@@ -1100,6 +1146,7 @@ class RequestLoggingMiddleware {
|
|
|
1100
1146
|
});
|
|
1101
1147
|
}
|
|
1102
1148
|
#failed(req, path, started, request, error, scope) {
|
|
1149
|
+
this.#shared(req, request);
|
|
1103
1150
|
const status = error instanceof HttpError ? error.status : HttpStatusCode.INTERNAL_SERVER_ERROR;
|
|
1104
1151
|
const entry = {
|
|
1105
1152
|
...scope,
|
|
@@ -1116,6 +1163,7 @@ class RequestLoggingMiddleware {
|
|
|
1116
1163
|
}
|
|
1117
1164
|
}
|
|
1118
1165
|
#succeeded(req, path, requestId, started, request, response, scope) {
|
|
1166
|
+
this.#shared(req, request);
|
|
1119
1167
|
const body = this.#responseFields(response);
|
|
1120
1168
|
if (body === undefined) {
|
|
1121
1169
|
this.logger.info(`${req.method} ${path} ${response.status}`, {
|
|
@@ -1139,7 +1187,7 @@ class RequestLoggingMiddleware {
|
|
|
1139
1187
|
return response;
|
|
1140
1188
|
});
|
|
1141
1189
|
}
|
|
1142
|
-
#body(req) {
|
|
1190
|
+
#body(req, ctx) {
|
|
1143
1191
|
if (!this.#requestBody)
|
|
1144
1192
|
return;
|
|
1145
1193
|
if (req.method === "GET" || req.method === "HEAD")
|
|
@@ -1147,6 +1195,10 @@ class RequestLoggingMiddleware {
|
|
|
1147
1195
|
if (!(req.headers.get("content-type") ?? "").includes("application/json")) {
|
|
1148
1196
|
return;
|
|
1149
1197
|
}
|
|
1198
|
+
if (ctx.parsesBody) {
|
|
1199
|
+
RawBody.want(req);
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1150
1202
|
return req.clone().text().then((text) => parse(text, this.#limit));
|
|
1151
1203
|
}
|
|
1152
1204
|
#responseFields(response) {
|
|
@@ -1230,7 +1282,11 @@ var bodyFill = (schema) => (draft) => {
|
|
|
1230
1282
|
if (parse2 === undefined) {
|
|
1231
1283
|
throw new HttpError(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE, `Unsupported content type "${media}". Declared bodies accept ` + "application/json, application/x-www-form-urlencoded, multipart/form-data or text/*.");
|
|
1232
1284
|
}
|
|
1233
|
-
|
|
1285
|
+
const read = parse2 === asJson && RawBody.wanted(draft.req) ? draft.req.text().then((text) => {
|
|
1286
|
+
RawBody.record(draft.req, text);
|
|
1287
|
+
return JSON.parse(text);
|
|
1288
|
+
}) : parse2(draft.req);
|
|
1289
|
+
return read.then((value) => fillWith(draft, "body", schema, value), (error) => {
|
|
1234
1290
|
throw new HttpError(HttpStatusCode.BAD_REQUEST, `Malformed ${media} body`, { cause: error });
|
|
1235
1291
|
});
|
|
1236
1292
|
};
|
|
@@ -1277,7 +1333,7 @@ var toResponse = (value, status) => {
|
|
|
1277
1333
|
}
|
|
1278
1334
|
return Response.json(value, { status });
|
|
1279
1335
|
};
|
|
1280
|
-
var statusFor = (route) => route.options?.status ?? (route.method
|
|
1336
|
+
var statusFor = (route) => route.options?.status ?? defaultStatusFor(route.method);
|
|
1281
1337
|
var assertNoCollisions = (discovered) => {
|
|
1282
1338
|
const owners = new Map;
|
|
1283
1339
|
for (const route of discovered) {
|
|
@@ -1309,6 +1365,7 @@ var unmatchedContext = (req, isPublic) => Object.freeze({
|
|
|
1309
1365
|
handler: "(none)",
|
|
1310
1366
|
method: req.method,
|
|
1311
1367
|
path: new URL(req.url).pathname,
|
|
1368
|
+
parsesBody: false,
|
|
1312
1369
|
get: (key) => {
|
|
1313
1370
|
if (key.id === UNMATCHED.id)
|
|
1314
1371
|
return true;
|
|
@@ -1767,6 +1824,274 @@ StaticModule = __decorateElement(_init, 0, "StaticModule", _dec, StaticModule);
|
|
|
1767
1824
|
__runInitializers(_init, 1, StaticModule);
|
|
1768
1825
|
__decoratorMetadata(_init, StaticModule);
|
|
1769
1826
|
let _StaticModule = StaticModule;
|
|
1827
|
+
// src/compression/negotiate.ts
|
|
1828
|
+
var quality = (params) => {
|
|
1829
|
+
for (const param of params) {
|
|
1830
|
+
const [key, value] = param.split("=");
|
|
1831
|
+
if (key?.trim().toLowerCase() !== "q")
|
|
1832
|
+
continue;
|
|
1833
|
+
const q = Number.parseFloat(value ?? "");
|
|
1834
|
+
return Number.isFinite(q) && q >= 0 && q <= 1 ? q : 1;
|
|
1835
|
+
}
|
|
1836
|
+
return 1;
|
|
1837
|
+
};
|
|
1838
|
+
var negotiate = (header, offered) => {
|
|
1839
|
+
if (header === null)
|
|
1840
|
+
return;
|
|
1841
|
+
const accepted = new Map;
|
|
1842
|
+
for (const element of header.split(",")) {
|
|
1843
|
+
const [name, ...params] = element.split(";");
|
|
1844
|
+
const token = name?.trim().toLowerCase();
|
|
1845
|
+
if (token === undefined || token === "")
|
|
1846
|
+
continue;
|
|
1847
|
+
accepted.set(token, quality(params));
|
|
1848
|
+
}
|
|
1849
|
+
const wildcard = accepted.get("*");
|
|
1850
|
+
let best;
|
|
1851
|
+
let bestQuality = 0;
|
|
1852
|
+
for (const encoding of offered) {
|
|
1853
|
+
const q = accepted.get(encoding) ?? wildcard ?? 0;
|
|
1854
|
+
if (q > bestQuality) {
|
|
1855
|
+
best = encoding;
|
|
1856
|
+
bestQuality = q;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return best;
|
|
1860
|
+
};
|
|
1861
|
+
|
|
1862
|
+
// src/compression/options.ts
|
|
1863
|
+
var CompressionEncoding = Object.freeze({
|
|
1864
|
+
ZSTD: "zstd",
|
|
1865
|
+
GZIP: "gzip"
|
|
1866
|
+
});
|
|
1867
|
+
var COMPRESSIBLE = new Set([
|
|
1868
|
+
"application/graphql",
|
|
1869
|
+
"application/graphql-response+json",
|
|
1870
|
+
"application/javascript",
|
|
1871
|
+
"application/json",
|
|
1872
|
+
"application/manifest+json",
|
|
1873
|
+
"application/wasm",
|
|
1874
|
+
"application/x-javascript",
|
|
1875
|
+
"application/x-ndjson",
|
|
1876
|
+
"application/xml",
|
|
1877
|
+
"image/svg+xml"
|
|
1878
|
+
]);
|
|
1879
|
+
var isCompressibleType = (contentType) => {
|
|
1880
|
+
if (contentType === null)
|
|
1881
|
+
return false;
|
|
1882
|
+
const type = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
1883
|
+
if (type.startsWith("text/"))
|
|
1884
|
+
return true;
|
|
1885
|
+
if (type.endsWith("+json") || type.endsWith("+xml"))
|
|
1886
|
+
return true;
|
|
1887
|
+
return COMPRESSIBLE.has(type);
|
|
1888
|
+
};
|
|
1889
|
+
var encodable = (encoding) => {
|
|
1890
|
+
const sync = encoding === CompressionEncoding.ZSTD ? Bun.zstdCompressSync : Bun.gzipSync;
|
|
1891
|
+
if (typeof sync !== "function")
|
|
1892
|
+
return false;
|
|
1893
|
+
try {
|
|
1894
|
+
new CompressionStream(encoding);
|
|
1895
|
+
return true;
|
|
1896
|
+
} catch {
|
|
1897
|
+
return false;
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
|
|
1901
|
+
class CompressionOptions {
|
|
1902
|
+
encodings;
|
|
1903
|
+
threshold;
|
|
1904
|
+
filter;
|
|
1905
|
+
constructor(init = {}) {
|
|
1906
|
+
this.encodings = init.encodings ?? [
|
|
1907
|
+
CompressionEncoding.ZSTD,
|
|
1908
|
+
CompressionEncoding.GZIP
|
|
1909
|
+
];
|
|
1910
|
+
const missing = this.encodings.filter((encoding) => !encodable(encoding));
|
|
1911
|
+
if (missing.length > 0) {
|
|
1912
|
+
throw new Error(`Bun ${Bun.version} cannot encode ${missing.join(", ")}. ` + "Pass `encodings` without it, or upgrade Bun.");
|
|
1913
|
+
}
|
|
1914
|
+
this.threshold = init.threshold ?? 1024;
|
|
1915
|
+
this.filter = init.filter ?? isCompressibleType;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
Object.defineProperty(CompressionOptions, Symbol.for("dunx.deps"), {
|
|
1919
|
+
value: () => [{ unresolved: "init: CompressionOptionsInit = {}" }]
|
|
1920
|
+
});
|
|
1921
|
+
|
|
1922
|
+
// src/compression/compression.ts
|
|
1923
|
+
var BODYLESS = new Set([204, 205, 304]);
|
|
1924
|
+
var BUFFER_LIMIT = 1024 * 1024;
|
|
1925
|
+
var buffer = async (body, limit) => {
|
|
1926
|
+
const reader = body.getReader();
|
|
1927
|
+
const chunks = [];
|
|
1928
|
+
let size = 0;
|
|
1929
|
+
for (;; ) {
|
|
1930
|
+
const { done, value } = await reader.read();
|
|
1931
|
+
if (done)
|
|
1932
|
+
break;
|
|
1933
|
+
chunks.push(value);
|
|
1934
|
+
size += value.byteLength;
|
|
1935
|
+
if (size > limit) {
|
|
1936
|
+
return {
|
|
1937
|
+
rest: new ReadableStream({
|
|
1938
|
+
start: (controller) => {
|
|
1939
|
+
for (const chunk of chunks)
|
|
1940
|
+
controller.enqueue(chunk);
|
|
1941
|
+
},
|
|
1942
|
+
pull: async (controller) => {
|
|
1943
|
+
const next = await reader.read();
|
|
1944
|
+
if (next.done)
|
|
1945
|
+
controller.close();
|
|
1946
|
+
else
|
|
1947
|
+
controller.enqueue(next.value);
|
|
1948
|
+
},
|
|
1949
|
+
cancel: (reason) => reader.cancel(reason)
|
|
1950
|
+
})
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
const bytes = new Uint8Array(size);
|
|
1955
|
+
let offset = 0;
|
|
1956
|
+
for (const chunk of chunks) {
|
|
1957
|
+
bytes.set(chunk, offset);
|
|
1958
|
+
offset += chunk.byteLength;
|
|
1959
|
+
}
|
|
1960
|
+
return { bytes };
|
|
1961
|
+
};
|
|
1962
|
+
var declaredLength = (headers) => {
|
|
1963
|
+
const raw = headers.get("content-length");
|
|
1964
|
+
if (raw === null)
|
|
1965
|
+
return;
|
|
1966
|
+
const length = Number.parseInt(raw, 10);
|
|
1967
|
+
return Number.isFinite(length) ? length : undefined;
|
|
1968
|
+
};
|
|
1969
|
+
var weakenETag = (headers) => {
|
|
1970
|
+
const etag = headers.get("etag");
|
|
1971
|
+
if (etag !== null && !etag.startsWith("W/"))
|
|
1972
|
+
headers.set("etag", `W/${etag}`);
|
|
1973
|
+
};
|
|
1974
|
+
var varyOnEncoding = (headers) => {
|
|
1975
|
+
const existing = headers.get("vary");
|
|
1976
|
+
if (existing === null) {
|
|
1977
|
+
headers.set("vary", "accept-encoding");
|
|
1978
|
+
return;
|
|
1979
|
+
}
|
|
1980
|
+
if (existing.trim() === "*")
|
|
1981
|
+
return;
|
|
1982
|
+
const listed = existing.split(",").some((field) => field.trim().toLowerCase() === "accept-encoding");
|
|
1983
|
+
if (!listed)
|
|
1984
|
+
headers.set("vary", `${existing}, accept-encoding`);
|
|
1985
|
+
};
|
|
1986
|
+
var encodeSync = (encoding, data) => {
|
|
1987
|
+
switch (encoding) {
|
|
1988
|
+
case CompressionEncoding.ZSTD:
|
|
1989
|
+
return Bun.zstdCompressSync(data);
|
|
1990
|
+
case CompressionEncoding.GZIP:
|
|
1991
|
+
return Bun.gzipSync(data);
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
class Compression {
|
|
1996
|
+
#options;
|
|
1997
|
+
constructor(options) {
|
|
1998
|
+
this.#options = options;
|
|
1999
|
+
}
|
|
2000
|
+
#considers(res) {
|
|
2001
|
+
if (BODYLESS.has(res.status) || res.status === 206)
|
|
2002
|
+
return false;
|
|
2003
|
+
if (res.headers.has("content-encoding"))
|
|
2004
|
+
return false;
|
|
2005
|
+
if (res.headers.get("cache-control")?.includes("no-transform") === true) {
|
|
2006
|
+
return false;
|
|
2007
|
+
}
|
|
2008
|
+
return this.#options.filter(res.headers.get("content-type"));
|
|
2009
|
+
}
|
|
2010
|
+
async handle(req, _ctx, next) {
|
|
2011
|
+
const res = await next();
|
|
2012
|
+
const body = res.body;
|
|
2013
|
+
if (body === null || !this.#considers(res))
|
|
2014
|
+
return res;
|
|
2015
|
+
varyOnEncoding(res.headers);
|
|
2016
|
+
const encoding = negotiate(req.headers.get("accept-encoding"), this.#options.encodings);
|
|
2017
|
+
if (encoding === undefined)
|
|
2018
|
+
return res;
|
|
2019
|
+
const declared = declaredLength(res.headers);
|
|
2020
|
+
if (declared !== undefined && declared < this.#options.threshold)
|
|
2021
|
+
return res;
|
|
2022
|
+
const headers = new Headers(res.headers);
|
|
2023
|
+
headers.set("content-encoding", encoding);
|
|
2024
|
+
weakenETag(headers);
|
|
2025
|
+
const source = declared !== undefined && declared > BUFFER_LIMIT ? { rest: body } : await buffer(body, BUFFER_LIMIT);
|
|
2026
|
+
if ("rest" in source) {
|
|
2027
|
+
headers.delete("content-length");
|
|
2028
|
+
return new Response(source.rest.pipeThrough(new CompressionStream(encoding)), { status: res.status, statusText: res.statusText, headers });
|
|
2029
|
+
}
|
|
2030
|
+
if (source.bytes.byteLength < this.#options.threshold) {
|
|
2031
|
+
const passthrough = new Headers(res.headers);
|
|
2032
|
+
passthrough.set("content-length", String(source.bytes.byteLength));
|
|
2033
|
+
return new Response(source.bytes, {
|
|
2034
|
+
status: res.status,
|
|
2035
|
+
statusText: res.statusText,
|
|
2036
|
+
headers: passthrough
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
const encoded = encodeSync(encoding, source.bytes);
|
|
2040
|
+
headers.set("content-length", String(encoded.byteLength));
|
|
2041
|
+
return new Response(encoded, {
|
|
2042
|
+
status: res.status,
|
|
2043
|
+
statusText: res.statusText,
|
|
2044
|
+
headers
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
Object.defineProperty(Compression, Symbol.for("dunx.deps"), {
|
|
2049
|
+
value: () => [CompressionOptions]
|
|
2050
|
+
});
|
|
2051
|
+
// src/compression/module.ts
|
|
2052
|
+
import {
|
|
2053
|
+
Module as Module2,
|
|
2054
|
+
provide as provide3
|
|
2055
|
+
} from "@dunx/core";
|
|
2056
|
+
var middleware = () => provide3(Compression, {
|
|
2057
|
+
useFactory: (options) => new Compression(options),
|
|
2058
|
+
inject: [CompressionOptions]
|
|
2059
|
+
});
|
|
2060
|
+
var _dec = [
|
|
2061
|
+
Module2({})
|
|
2062
|
+
];
|
|
2063
|
+
var _init = __decoratorStart(undefined);
|
|
2064
|
+
|
|
2065
|
+
class CompressionModule {
|
|
2066
|
+
static forRoot(init = {}) {
|
|
2067
|
+
return {
|
|
2068
|
+
module: CompressionModule,
|
|
2069
|
+
exports: [CompressionOptions, Compression],
|
|
2070
|
+
providers: [
|
|
2071
|
+
provide3(CompressionOptions, { useValue: new CompressionOptions(init) }),
|
|
2072
|
+
middleware()
|
|
2073
|
+
]
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
static forRootAsync(config) {
|
|
2077
|
+
return {
|
|
2078
|
+
module: CompressionModule,
|
|
2079
|
+
...config.imports && { imports: config.imports },
|
|
2080
|
+
exports: [CompressionOptions, Compression],
|
|
2081
|
+
providers: [
|
|
2082
|
+
provide3(CompressionOptions, {
|
|
2083
|
+
useFactory: async (...deps) => new CompressionOptions(await config.useFactory(...deps)),
|
|
2084
|
+
inject: config.inject ?? []
|
|
2085
|
+
}),
|
|
2086
|
+
middleware()
|
|
2087
|
+
]
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
CompressionModule = __decorateElement(_init, 0, "CompressionModule", _dec, CompressionModule);
|
|
2092
|
+
__runInitializers(_init, 1, CompressionModule);
|
|
2093
|
+
__decoratorMetadata(_init, CompressionModule);
|
|
2094
|
+
let _CompressionModule = CompressionModule;
|
|
1770
2095
|
// src/throttle/decorators.ts
|
|
1771
2096
|
var THROTTLE = metaKey("throttle");
|
|
1772
2097
|
var SKIP_THROTTLE = metaKey("skip-throttle");
|
|
@@ -1952,20 +2277,20 @@ Object.defineProperty(ThrottleGuard, Symbol.for("dunx.deps"), {
|
|
|
1952
2277
|
// src/throttle/module.ts
|
|
1953
2278
|
import {
|
|
1954
2279
|
Logger as Logger6,
|
|
1955
|
-
Module as
|
|
1956
|
-
provide as
|
|
2280
|
+
Module as Module3,
|
|
2281
|
+
provide as provide4
|
|
1957
2282
|
} from "@dunx/core";
|
|
1958
2283
|
var EXPORTS = [ThrottleOptions, ThrottleStore, ThrottleGuard];
|
|
1959
|
-
var guard = () =>
|
|
2284
|
+
var guard = () => provide4(ThrottleGuard, {
|
|
1960
2285
|
useFactory: (options, store, address, logger) => new ThrottleGuard(options, store, address, logger),
|
|
1961
2286
|
inject: [ThrottleOptions, ThrottleStore, ClientAddress, Logger6]
|
|
1962
2287
|
});
|
|
1963
|
-
var store = () =>
|
|
2288
|
+
var store = () => provide4(ThrottleStore, {
|
|
1964
2289
|
useFactory: (options) => options.store ?? new MemoryThrottleStore,
|
|
1965
2290
|
inject: [ThrottleOptions]
|
|
1966
2291
|
});
|
|
1967
2292
|
var _dec = [
|
|
1968
|
-
|
|
2293
|
+
Module3({})
|
|
1969
2294
|
];
|
|
1970
2295
|
var _init = __decoratorStart(undefined);
|
|
1971
2296
|
|
|
@@ -1976,7 +2301,7 @@ class ThrottleModule {
|
|
|
1976
2301
|
global: true,
|
|
1977
2302
|
exports: EXPORTS,
|
|
1978
2303
|
providers: [
|
|
1979
|
-
|
|
2304
|
+
provide4(ThrottleOptions, { useValue: new ThrottleOptions(init) }),
|
|
1980
2305
|
store(),
|
|
1981
2306
|
guard()
|
|
1982
2307
|
]
|
|
@@ -1989,7 +2314,7 @@ class ThrottleModule {
|
|
|
1989
2314
|
...config.imports && { imports: config.imports },
|
|
1990
2315
|
exports: EXPORTS,
|
|
1991
2316
|
providers: [
|
|
1992
|
-
|
|
2317
|
+
provide4(ThrottleOptions, {
|
|
1993
2318
|
useFactory: async (...deps) => new ThrottleOptions(await config.useFactory(...deps)),
|
|
1994
2319
|
inject: config.inject ?? []
|
|
1995
2320
|
}),
|
|
@@ -2128,6 +2453,50 @@ class QueryProbe {
|
|
|
2128
2453
|
// src/health/controller.ts
|
|
2129
2454
|
import { inject } from "@dunx/core";
|
|
2130
2455
|
|
|
2456
|
+
// src/health/report-schema.ts
|
|
2457
|
+
var state = {
|
|
2458
|
+
type: "string",
|
|
2459
|
+
enum: ["up", "down", "unknown"],
|
|
2460
|
+
description: "`unknown` is not `down`: a probe that timed out has told you nothing."
|
|
2461
|
+
};
|
|
2462
|
+
var HEALTH_REPORT_SCHEMA = Object.freeze({
|
|
2463
|
+
$id: "HealthReport",
|
|
2464
|
+
type: "object",
|
|
2465
|
+
description: "What the probe found. `up` answers 200 and anything else answers 503.",
|
|
2466
|
+
properties: {
|
|
2467
|
+
status: state,
|
|
2468
|
+
draining: {
|
|
2469
|
+
type: "boolean",
|
|
2470
|
+
description: "The process is shutting down, or something holds it out."
|
|
2471
|
+
},
|
|
2472
|
+
uptimeMs: {
|
|
2473
|
+
type: "integer",
|
|
2474
|
+
description: "Measured on a monotonic clock, so it never goes backwards."
|
|
2475
|
+
},
|
|
2476
|
+
checks: {
|
|
2477
|
+
type: "array",
|
|
2478
|
+
items: {
|
|
2479
|
+
type: "object",
|
|
2480
|
+
properties: {
|
|
2481
|
+
name: { type: "string" },
|
|
2482
|
+
state,
|
|
2483
|
+
critical: {
|
|
2484
|
+
type: "boolean",
|
|
2485
|
+
description: "A failure here sheds traffic. Memory and disk do not."
|
|
2486
|
+
},
|
|
2487
|
+
ms: { type: "integer", description: "How long the check took." },
|
|
2488
|
+
detail: {
|
|
2489
|
+
type: "string",
|
|
2490
|
+
description: "A latency, a version, or a failure message."
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
required: ["name", "state", "critical", "ms"]
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
},
|
|
2497
|
+
required: ["status", "draining", "uptimeMs", "checks"]
|
|
2498
|
+
});
|
|
2499
|
+
|
|
2131
2500
|
// src/health/registry.ts
|
|
2132
2501
|
var bounded = async (indicator, timeoutMs) => {
|
|
2133
2502
|
let timer;
|
|
@@ -2162,12 +2531,14 @@ class HealthOptions {
|
|
|
2162
2531
|
readiness;
|
|
2163
2532
|
timeoutMs;
|
|
2164
2533
|
routes;
|
|
2534
|
+
documented;
|
|
2165
2535
|
drainDelayMs;
|
|
2166
2536
|
constructor(init = {}) {
|
|
2167
2537
|
this.liveness = init.liveness ?? [];
|
|
2168
2538
|
this.readiness = init.readiness ?? [];
|
|
2169
2539
|
this.timeoutMs = init.timeoutMs ?? 2000;
|
|
2170
2540
|
this.routes = init.routes ?? true;
|
|
2541
|
+
this.documented = init.documented ?? true;
|
|
2171
2542
|
this.drainDelayMs = Math.max(0, init.drainDelayMs ?? 0);
|
|
2172
2543
|
}
|
|
2173
2544
|
}
|
|
@@ -2230,18 +2601,20 @@ Object.defineProperty(HealthRegistry, Symbol.for("dunx.deps"), {
|
|
|
2230
2601
|
});
|
|
2231
2602
|
|
|
2232
2603
|
// src/health/controller.ts
|
|
2604
|
+
var probeResponses = {
|
|
2605
|
+
response: { 200: HEALTH_REPORT_SCHEMA, 503: HEALTH_REPORT_SCHEMA }
|
|
2606
|
+
};
|
|
2233
2607
|
var answer = (report) => Response.json(report, { status: report.status === "up" ? 200 : 503 });
|
|
2234
2608
|
var _dec = [
|
|
2235
|
-
Controller("health")
|
|
2236
|
-
ApiHidden()
|
|
2609
|
+
Controller("health")
|
|
2237
2610
|
];
|
|
2238
2611
|
var _dec2 = [
|
|
2239
2612
|
Public(),
|
|
2240
|
-
Get("/live")
|
|
2613
|
+
Get("/live", probeResponses)
|
|
2241
2614
|
];
|
|
2242
2615
|
var _dec3 = [
|
|
2243
2616
|
Public(),
|
|
2244
|
-
Get("/ready")
|
|
2617
|
+
Get("/ready", probeResponses)
|
|
2245
2618
|
];
|
|
2246
2619
|
var _health = new WeakMap;
|
|
2247
2620
|
var _init = __decoratorStart(undefined);
|
|
@@ -2264,6 +2637,18 @@ HealthController = __decorateElement(_init, 0, "HealthController", _dec, HealthC
|
|
|
2264
2637
|
__runInitializers(_init, 1, HealthController);
|
|
2265
2638
|
__decoratorMetadata(_init, HealthController);
|
|
2266
2639
|
let _HealthController = HealthController;
|
|
2640
|
+
var _dec = [
|
|
2641
|
+
ApiHidden()
|
|
2642
|
+
];
|
|
2643
|
+
var _base = HealthController;
|
|
2644
|
+
var _init = __decoratorStart(_base);
|
|
2645
|
+
|
|
2646
|
+
class HiddenHealthController extends _base {
|
|
2647
|
+
}
|
|
2648
|
+
HiddenHealthController = __decorateElement(_init, 0, "HiddenHealthController", _dec, HiddenHealthController);
|
|
2649
|
+
__runInitializers(_init, 1, HiddenHealthController);
|
|
2650
|
+
__decoratorMetadata(_init, HiddenHealthController);
|
|
2651
|
+
let _HiddenHealthController = HiddenHealthController;
|
|
2267
2652
|
// src/health/indicators.ts
|
|
2268
2653
|
import { statfs } from "fs/promises";
|
|
2269
2654
|
var ms = (started) => Math.round(performance.now() - started);
|
|
@@ -2368,8 +2753,8 @@ Object.defineProperty(DiskIndicator, Symbol.for("dunx.deps"), {
|
|
|
2368
2753
|
});
|
|
2369
2754
|
// src/health/module.ts
|
|
2370
2755
|
import {
|
|
2371
|
-
Module as
|
|
2372
|
-
provide as
|
|
2756
|
+
Module as Module4,
|
|
2757
|
+
provide as provide5
|
|
2373
2758
|
} from "@dunx/core";
|
|
2374
2759
|
|
|
2375
2760
|
// src/health/readiness.ts
|
|
@@ -2416,22 +2801,23 @@ Object.defineProperty(Readiness, Symbol.for("dunx.deps"), {
|
|
|
2416
2801
|
// src/health/module.ts
|
|
2417
2802
|
var wiring = (options) => [
|
|
2418
2803
|
...options,
|
|
2419
|
-
|
|
2804
|
+
provide5(ReadinessOptions, {
|
|
2420
2805
|
useFactory: (opts) => new ReadinessOptions({ drainDelayMs: opts.drainDelayMs }),
|
|
2421
2806
|
inject: [HealthOptions]
|
|
2422
2807
|
}),
|
|
2423
|
-
|
|
2808
|
+
provide5(Readiness, {
|
|
2424
2809
|
useFactory: (opts) => new Readiness(opts),
|
|
2425
2810
|
inject: [ReadinessOptions]
|
|
2426
2811
|
}),
|
|
2427
|
-
|
|
2812
|
+
provide5(HealthRegistry, {
|
|
2428
2813
|
useFactory: (opts, readiness) => new HealthRegistry(opts, readiness),
|
|
2429
2814
|
inject: [HealthOptions, Readiness]
|
|
2430
2815
|
})
|
|
2431
2816
|
];
|
|
2432
2817
|
var surface = [HealthOptions, HealthRegistry, Readiness];
|
|
2818
|
+
var controllerFor = (documented) => documented ? HealthController : HiddenHealthController;
|
|
2433
2819
|
var _dec = [
|
|
2434
|
-
|
|
2820
|
+
Module4({})
|
|
2435
2821
|
];
|
|
2436
2822
|
var _init = __decoratorStart(undefined);
|
|
2437
2823
|
|
|
@@ -2440,19 +2826,19 @@ class HealthModule {
|
|
|
2440
2826
|
const options = new HealthOptions(init);
|
|
2441
2827
|
return {
|
|
2442
2828
|
module: HealthModule,
|
|
2443
|
-
...options.routes ? { controllers: [
|
|
2829
|
+
...options.routes ? { controllers: [controllerFor(options.documented)] } : {},
|
|
2444
2830
|
exports: surface,
|
|
2445
|
-
providers: wiring([
|
|
2831
|
+
providers: wiring([provide5(HealthOptions, { useValue: options })])
|
|
2446
2832
|
};
|
|
2447
2833
|
}
|
|
2448
2834
|
static forRootAsync(config) {
|
|
2449
2835
|
return {
|
|
2450
2836
|
module: HealthModule,
|
|
2451
2837
|
...config.imports ? { imports: config.imports } : {},
|
|
2452
|
-
...config.routes ?? true ? { controllers: [
|
|
2838
|
+
...config.routes ?? true ? { controllers: [controllerFor(config.documented ?? true)] } : {},
|
|
2453
2839
|
exports: surface,
|
|
2454
2840
|
providers: wiring([
|
|
2455
|
-
|
|
2841
|
+
provide5(HealthOptions, {
|
|
2456
2842
|
useFactory: async (...deps) => new HealthOptions(await config.useFactory(...deps)),
|
|
2457
2843
|
inject: config.inject ?? []
|
|
2458
2844
|
})
|
|
@@ -2467,6 +2853,10 @@ let _HealthModule = HealthModule;
|
|
|
2467
2853
|
export {
|
|
2468
2854
|
ApiHidden,
|
|
2469
2855
|
ClientAddress,
|
|
2856
|
+
Compression,
|
|
2857
|
+
CompressionEncoding,
|
|
2858
|
+
CompressionModule,
|
|
2859
|
+
CompressionOptions,
|
|
2470
2860
|
Controller,
|
|
2471
2861
|
DEFAULT_RELAY_CHANNEL,
|
|
2472
2862
|
DatabaseIndicator,
|
|
@@ -2476,6 +2866,7 @@ export {
|
|
|
2476
2866
|
ErrorFilter,
|
|
2477
2867
|
Gateway,
|
|
2478
2868
|
Get,
|
|
2869
|
+
HEALTH_REPORT_SCHEMA,
|
|
2479
2870
|
HIDDEN,
|
|
2480
2871
|
HandlerKind,
|
|
2481
2872
|
HealthController,
|
|
@@ -2483,6 +2874,7 @@ export {
|
|
|
2483
2874
|
HealthModule,
|
|
2484
2875
|
HealthOptions,
|
|
2485
2876
|
HealthRegistry,
|
|
2877
|
+
HiddenHealthController,
|
|
2486
2878
|
HttpError,
|
|
2487
2879
|
HttpFactory,
|
|
2488
2880
|
HttpStatusCode,
|
|
@@ -2520,11 +2912,14 @@ export {
|
|
|
2520
2912
|
StaticModule,
|
|
2521
2913
|
StaticOptions,
|
|
2522
2914
|
THROTTLE,
|
|
2915
|
+
TRACEPARENT_HEADER,
|
|
2916
|
+
TRACESTATE_HEADER,
|
|
2523
2917
|
Throttle,
|
|
2524
2918
|
ThrottleGuard,
|
|
2525
2919
|
ThrottleModule,
|
|
2526
2920
|
ThrottleOptions,
|
|
2527
2921
|
ThrottleStore,
|
|
2922
|
+
TraceContext,
|
|
2528
2923
|
UNMATCHED,
|
|
2529
2924
|
UseGuards,
|
|
2530
2925
|
ValidationError,
|
|
@@ -2541,6 +2936,7 @@ export {
|
|
|
2541
2936
|
decodeRelay,
|
|
2542
2937
|
defaultErrorMapper,
|
|
2543
2938
|
defaultRelayUrl,
|
|
2939
|
+
defaultStatusFor,
|
|
2544
2940
|
discoverGateway,
|
|
2545
2941
|
discoverGateways,
|
|
2546
2942
|
discoverRoutes,
|
|
@@ -2549,6 +2945,7 @@ export {
|
|
|
2549
2945
|
errorMapper,
|
|
2550
2946
|
gatewaysOf,
|
|
2551
2947
|
guardsOf,
|
|
2948
|
+
isCompressibleType,
|
|
2552
2949
|
isErrorFilter,
|
|
2553
2950
|
isGateway,
|
|
2554
2951
|
joinPath,
|
|
@@ -2556,6 +2953,7 @@ export {
|
|
|
2556
2953
|
meta,
|
|
2557
2954
|
metaKey,
|
|
2558
2955
|
metaOf,
|
|
2956
|
+
negotiate,
|
|
2559
2957
|
normalizePath,
|
|
2560
2958
|
normalizePrefix,
|
|
2561
2959
|
observe,
|
|
@@ -2565,6 +2963,3 @@ export {
|
|
|
2565
2963
|
withCors,
|
|
2566
2964
|
withUpgradeRoutes
|
|
2567
2965
|
};
|
|
2568
|
-
|
|
2569
|
-
//# debugId=30A653C61AAD581564756E2164756E21
|
|
2570
|
-
//# sourceMappingURL=index.js.map
|