@zudojs/http 1.2.0 → 1.4.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/README.md +221 -0
- package/dist/httpAdapter/http.adapters.d.ts +24 -3
- package/dist/httpAdapter/http.adapters.js +20 -11
- package/dist/httpAdapter/node/httpNode.adapter.d.ts +2 -1
- package/dist/httpAdapter/node/httpNode.adapter.js +17 -2
- package/dist/httpAdapter/node/httpNode.request.js +7 -1
- package/dist/httpAdapter/node/httpNode.type.d.ts +14 -0
- package/dist/httpAgent/http.agent.d.ts +22 -3
- package/dist/httpAgent/http.agent.js +52 -14
- package/dist/httpCacheControl/httpCacheControl.freshness.d.ts +7 -1
- package/dist/httpCacheControl/httpCacheControl.freshness.js +30 -3
- package/dist/httpClient/httpClient.retry.d.ts +17 -12
- package/dist/httpClient/httpClient.retry.js +35 -10
- package/dist/httpClient/httpClient.type.d.ts +14 -0
- package/dist/httpErrors/httpError.base.js +2 -2
- package/dist/httpErrors/httpError.util.d.ts +8 -0
- package/dist/httpErrors/httpError.util.js +12 -0
- package/dist/httpFetchMount/httpFetchMount.core.d.ts +25 -0
- package/dist/httpFetchMount/httpFetchMount.core.js +84 -0
- package/dist/httpFetchMount/httpFetchMount.request.d.ts +21 -0
- package/dist/httpFetchMount/httpFetchMount.request.js +100 -0
- package/dist/httpFetchMount/httpFetchMount.type.d.ts +56 -0
- package/dist/httpFetchMount/httpFetchMount.type.js +5 -0
- package/dist/httpFetchMount/index.d.ts +11 -0
- package/dist/httpFetchMount/index.js +10 -0
- package/dist/httpKeepAlive/httpKeepAlive.core.js +14 -2
- package/dist/httpMiddleware/builtin/logging/httpMiddleware.logging.d.ts +18 -0
- package/dist/httpMiddleware/builtin/logging/httpMiddleware.logging.js +17 -1
- package/dist/httpMiddleware/builtin/rateLimit/httpMiddleware.rateLimit.d.ts +6 -3
- package/dist/httpMiddleware/builtin/rateLimit/httpMiddleware.rateLimit.js +34 -6
- package/dist/httpMiddleware/builtin/security/httpMiddleware.security.d.ts +11 -0
- package/dist/httpMiddleware/builtin/security/httpMiddleware.security.js +25 -12
- package/dist/httpMiddleware/httpMiddleware.type.d.ts +9 -1
- package/dist/httpMiddleware/pipeline/httpPipeline.execution.js +22 -45
- package/dist/httpMiddleware/pipeline/httpPipeline.guardResponse.d.ts +36 -0
- package/dist/httpMiddleware/pipeline/httpPipeline.guardResponse.js +57 -0
- package/dist/httpMiddleware/pipeline/httpPipeline.helper.d.ts +2 -1
- package/dist/httpMiddleware/pipeline/httpPipeline.helper.js +10 -0
- package/dist/httpMiddleware/pipeline/index.d.ts +1 -0
- package/dist/httpMiddleware/pipeline/index.js +1 -0
- package/dist/httpNegotiation/httpNegotiation.core.d.ts +13 -0
- package/dist/httpNegotiation/httpNegotiation.core.js +60 -8
- package/dist/httpOpenApi/httpOpenApi.document.d.ts +44 -0
- package/dist/httpOpenApi/httpOpenApi.document.js +61 -0
- package/dist/httpOpenApi/httpOpenApi.mount.d.ts +31 -0
- package/dist/httpOpenApi/httpOpenApi.mount.js +58 -0
- package/dist/httpOpenApi/httpOpenApi.type.d.ts +54 -0
- package/dist/httpOpenApi/httpOpenApi.type.js +5 -0
- package/dist/httpOpenApi/index.d.ts +13 -0
- package/dist/httpOpenApi/index.js +12 -0
- package/dist/httpOpenApi/routeTable/index.d.ts +11 -0
- package/dist/httpOpenApi/routeTable/index.js +11 -0
- package/dist/httpOpenApi/routeTable/routeTable.collect.d.ts +19 -0
- package/dist/httpOpenApi/routeTable/routeTable.collect.js +89 -0
- package/dist/httpOpenApi/routeTable/routeTable.merge.d.ts +15 -0
- package/dist/httpOpenApi/routeTable/routeTable.merge.js +37 -0
- package/dist/httpOpenApi/routeTable/routeTable.template.d.ts +30 -0
- package/dist/httpOpenApi/routeTable/routeTable.template.js +67 -0
- package/dist/httpProxy/http.proxy.d.ts +9 -0
- package/dist/httpProxy/http.proxy.js +35 -3
- package/dist/httpQuery/index.d.ts +11 -2
- package/dist/httpQuery/index.js +11 -2
- package/dist/httpQuery/queryParse/index.d.ts +10 -0
- package/dist/httpQuery/queryParse/index.js +10 -0
- package/dist/httpQuery/queryParse/queryParse.flat.d.ts +13 -0
- package/dist/httpQuery/queryParse/queryParse.flat.js +44 -0
- package/dist/httpQuery/queryParse/queryParse.nested.d.ts +25 -0
- package/dist/httpQuery/queryParse/queryParse.nested.js +112 -0
- package/dist/httpQuery/queryParse/queryParse.tokenizer.d.ts +37 -0
- package/dist/httpQuery/queryParse/queryParse.tokenizer.js +95 -0
- package/dist/httpQuery/queryRequest/index.d.ts +9 -0
- package/dist/httpQuery/queryRequest/index.js +9 -0
- package/dist/httpQuery/queryRequest/query.request.d.ts +43 -0
- package/dist/httpQuery/queryRequest/query.request.js +96 -0
- package/dist/httpQuery/querySerialize/index.d.ts +10 -0
- package/dist/httpQuery/querySerialize/index.js +10 -0
- package/dist/httpQuery/querySerialize/query.util.d.ts +21 -0
- package/dist/httpQuery/querySerialize/query.util.js +67 -0
- package/dist/httpQuery/querySerialize/querySerialize.core.d.ts +12 -0
- package/dist/httpQuery/querySerialize/querySerialize.core.js +97 -0
- package/dist/httpQuery/queryTypes/index.d.ts +11 -0
- package/dist/httpQuery/queryTypes/index.js +9 -0
- package/dist/httpQuery/queryTypes/query.container.d.ts +16 -0
- package/dist/httpQuery/queryTypes/query.container.js +51 -0
- package/dist/httpQuery/queryTypes/query.limit.d.ts +25 -0
- package/dist/httpQuery/queryTypes/query.limit.js +32 -0
- package/dist/httpQuery/queryTypes/query.type.d.ts +62 -0
- package/dist/httpQuery/queryTypes/query.type.js +2 -0
- package/dist/httpRedirect/http.redirect.d.ts +6 -0
- package/dist/httpRedirect/http.redirect.js +53 -2
- package/dist/httpRequest/http.request.d.ts +61 -2
- package/dist/httpRequest/http.request.js +86 -35
- package/dist/httpRequest/httpRequest.context.d.ts +8 -0
- package/dist/httpRequest/httpRequest.context.js +23 -18
- package/dist/httpRequest/index.d.ts +1 -0
- package/dist/httpRequest/index.js +1 -0
- package/dist/httpRequest/requestId/httpRequest.requestId.d.ts +25 -0
- package/dist/httpRequest/requestId/httpRequest.requestId.js +34 -0
- package/dist/httpRequest/requestId/index.d.ts +7 -0
- package/dist/httpRequest/requestId/index.js +7 -0
- package/dist/httpRequest/target/httpRequest.target.d.ts +2 -2
- package/dist/httpRequest/target/httpRequest.target.js +23 -5
- package/dist/httpResponse/httpResponse.writer.js +15 -0
- package/dist/httpRouter/core/factory/httpRoute.factory.base.d.ts +24 -4
- package/dist/httpRouter/core/factory/httpRoute.factory.base.js +73 -17
- package/dist/httpRouter/core/factory/httpRoute.factory.js +3 -3
- package/dist/httpRouter/core/group/httpRouterGroup.core.js +13 -0
- package/dist/httpRouter/core/register/httpRouter.register.js +19 -21
- package/dist/httpRouter/core/types/httpRouter.type.d.ts +37 -1
- package/dist/httpRouter/core/util/httpRoute.util.d.ts +55 -0
- package/dist/httpRouter/core/util/httpRoute.util.js +101 -4
- package/dist/httpRouter/dispatch/httpRoute.dispatcher.d.ts +11 -0
- package/dist/httpRouter/dispatch/httpRoute.dispatcher.js +25 -6
- package/dist/httpRouter/matching/httpRoute.matcher.core.js +51 -6
- package/dist/httpRouter/matching/httpRoute.matcher.d.ts +0 -1
- package/dist/httpRouter/matching/httpRoute.matcher.js +64 -26
- package/dist/httpRouter/pattern/httpRoute.pattern.parse.d.ts +16 -0
- package/dist/httpRouter/pattern/httpRoute.pattern.parse.js +40 -11
- package/dist/httpRouter/pattern/index.d.ts +1 -1
- package/dist/httpRouter/pattern/index.js +1 -1
- package/dist/httpSecurity/httpSecurity.config.js +4 -1
- package/dist/httpSecurity/httpSecurity.validator.js +16 -7
- package/dist/httpServer/factory/httpServer.factory.d.ts +10 -9
- package/dist/httpServer/factory/httpServer.factory.js +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +11 -8
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - `/assets/*path` trailing wildcard
|
|
14
14
|
*/
|
|
15
15
|
import { InvalidRoutePatternError } from "../core/error/httpRouter.error.js";
|
|
16
|
-
import {
|
|
16
|
+
import { hasTrailingSlash, splitRoutePattern, validateParameterName, } from "../core/util/httpRoute.util.js";
|
|
17
17
|
const SEGMENT_SCORE_LITERAL = 3;
|
|
18
18
|
const SEGMENT_SCORE_PARAMETER = 2;
|
|
19
19
|
const SEGMENT_SCORE_WILDCARD = 1;
|
|
@@ -22,7 +22,7 @@ const SEGMENT_SCORE_WILDCARD = 1;
|
|
|
22
22
|
*/
|
|
23
23
|
export function compileRouteSegments(path) {
|
|
24
24
|
const segments = [];
|
|
25
|
-
const parts =
|
|
25
|
+
const parts = splitRoutePattern(path);
|
|
26
26
|
for (const part of parts) {
|
|
27
27
|
if (part.startsWith(":")) {
|
|
28
28
|
segments.push(parseParameter(part, path));
|
|
@@ -56,6 +56,7 @@ export function compileRoute(path, strictTrailingSlash) {
|
|
|
56
56
|
segments,
|
|
57
57
|
score: scoreSegments(segments),
|
|
58
58
|
strictTrailingSlash,
|
|
59
|
+
expectsTrailingSlash: hasTrailingSlash(path),
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
@@ -64,18 +65,46 @@ export function compileRoute(path, strictTrailingSlash) {
|
|
|
64
65
|
export function scoreSegments(segments) {
|
|
65
66
|
let score = 0;
|
|
66
67
|
for (const segment of segments) {
|
|
67
|
-
|
|
68
|
-
score += SEGMENT_SCORE_LITERAL;
|
|
69
|
-
}
|
|
70
|
-
else if (segment.type === "parameter") {
|
|
71
|
-
score += SEGMENT_SCORE_PARAMETER;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
score += SEGMENT_SCORE_WILDCARD;
|
|
75
|
-
}
|
|
68
|
+
score += segmentScore(segment);
|
|
76
69
|
}
|
|
77
70
|
return score;
|
|
78
71
|
}
|
|
72
|
+
function segmentScore(segment) {
|
|
73
|
+
if (segment === undefined) {
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
if (segment.type === "literal") {
|
|
77
|
+
return SEGMENT_SCORE_LITERAL;
|
|
78
|
+
}
|
|
79
|
+
if (segment.type === "parameter") {
|
|
80
|
+
return SEGMENT_SCORE_PARAMETER;
|
|
81
|
+
}
|
|
82
|
+
return SEGMENT_SCORE_WILDCARD;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Compares two compiled patterns by specificity, most specific first.
|
|
86
|
+
*
|
|
87
|
+
* Segments are compared left to right by kind (literal, then parameter, then
|
|
88
|
+
* wildcard), which is how a router is expected to rank patterns. Summing the
|
|
89
|
+
* kinds into one scalar — as this used to — let a longer but entirely
|
|
90
|
+
* parameterised pattern such as `/:p/:q/:r/:s` outrank a literal-anchored
|
|
91
|
+
* `/admin/*rest`, so a request to `/admin/a/b/c` bypassed the admin route and
|
|
92
|
+
* every guard registered on it.
|
|
93
|
+
*
|
|
94
|
+
* @param left - The first pattern's segments.
|
|
95
|
+
* @param right - The second pattern's segments.
|
|
96
|
+
* @returns A negative number when `left` is more specific.
|
|
97
|
+
*/
|
|
98
|
+
export function compareSegmentSpecificity(left, right) {
|
|
99
|
+
const length = Math.max(left.length, right.length);
|
|
100
|
+
for (let index = 0; index < length; index += 1) {
|
|
101
|
+
const difference = segmentScore(right[index]) - segmentScore(left[index]);
|
|
102
|
+
if (difference !== 0) {
|
|
103
|
+
return difference;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
79
108
|
function parseParameter(segment, path) {
|
|
80
109
|
let value = segment.slice(1);
|
|
81
110
|
let optional = false;
|
|
@@ -14,6 +14,6 @@ export { parseSegments } from "./core/httpPattern.segmentParsing.js";
|
|
|
14
14
|
export { buildRegex } from "./core/httpPattern.regexBuilding.js";
|
|
15
15
|
export { testRoutePattern, matchRoutePattern, matchRoutePatterns, testRoutePatterns, } from "./core/httpPattern.matching.js";
|
|
16
16
|
export { createRoutePattern, createStrictRoutePattern, createCaseInsensitiveRoutePattern, } from "./httpPattern.factory.js";
|
|
17
|
-
export { compileRoute, compileRouteSegments, scoreSegments, } from "./httpRoute.pattern.parse.js";
|
|
17
|
+
export { compileRoute, compileRouteSegments, scoreSegments, compareSegmentSpecificity, } from "./httpRoute.pattern.parse.js";
|
|
18
18
|
export type { CompiledRoutePath } from "./httpRoute.pattern.parse.js";
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -13,5 +13,5 @@ export { parseSegments } from "./core/httpPattern.segmentParsing.js";
|
|
|
13
13
|
export { buildRegex } from "./core/httpPattern.regexBuilding.js";
|
|
14
14
|
export { testRoutePattern, matchRoutePattern, matchRoutePatterns, testRoutePatterns, } from "./core/httpPattern.matching.js";
|
|
15
15
|
export { createRoutePattern, createStrictRoutePattern, createCaseInsensitiveRoutePattern, } from "./httpPattern.factory.js";
|
|
16
|
-
export { compileRoute, compileRouteSegments, scoreSegments, } from "./httpRoute.pattern.parse.js";
|
|
16
|
+
export { compileRoute, compileRouteSegments, scoreSegments, compareSegmentSpecificity, } from "./httpRoute.pattern.parse.js";
|
|
17
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* adapter has its own, separately named timeout options, and those are the
|
|
13
13
|
* ones that take effect.
|
|
14
14
|
*/
|
|
15
|
+
import { INCOMING_REQUEST_ID_PATTERN } from "../httpRequest/requestId/httpRequest.requestId.js";
|
|
15
16
|
/** Default security configuration. */
|
|
16
17
|
export const DEFAULT_SECURITY_CONFIG = Object.freeze({
|
|
17
18
|
maxBodySize: 1_048_576, // 1MB
|
|
@@ -23,7 +24,9 @@ export const DEFAULT_SECURITY_CONFIG = Object.freeze({
|
|
|
23
24
|
requireHost: true,
|
|
24
25
|
trustProxy: false,
|
|
25
26
|
maxRequestIdLength: 128,
|
|
26
|
-
|
|
27
|
+
// Same rule the adapter uses to reuse an incoming x-request-id, so an id
|
|
28
|
+
// it would accept (trace ids like `svc.a:123`) is not refused here first.
|
|
29
|
+
requestIdPattern: INCOMING_REQUEST_ID_PATTERN,
|
|
27
30
|
enableCrlfProtection: true,
|
|
28
31
|
enableSmugglingProtection: true,
|
|
29
32
|
});
|
|
@@ -20,14 +20,23 @@ export function validateHeaders(headers, config) {
|
|
|
20
20
|
if (entries.length > cfg.maxHeaders) {
|
|
21
21
|
errors.push(`Too many headers: ${entries.length} > ${cfg.maxHeaders}`);
|
|
22
22
|
}
|
|
23
|
+
/*
|
|
24
|
+
* `IncomingMessage.headers` returns an array for `set-cookie` and for any
|
|
25
|
+
* header a non-Node caller supplies as a list. Checking only `typeof value
|
|
26
|
+
* === "string"` let every one of those values past the size cap and the
|
|
27
|
+
* CRLF filter while the guard still reported `allowed: true`.
|
|
28
|
+
*/
|
|
23
29
|
for (const [key, value] of entries) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
for (const element of Array.isArray(value) ? value : [value]) {
|
|
31
|
+
if (typeof element !== "string") {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (element.length > cfg.maxHeaderValueSize) {
|
|
35
|
+
errors.push(`Header "${key}" value too large: ${element.length} > ${cfg.maxHeaderValueSize}`);
|
|
36
|
+
}
|
|
37
|
+
if (cfg.enableCrlfProtection && /[\r\n]/.test(element)) {
|
|
38
|
+
errors.push(`Header "${key}" contains CRLF characters`);
|
|
39
|
+
}
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
return { valid: errors.length === 0, errors };
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
* @module httpServer/factory
|
|
5
5
|
*/
|
|
6
6
|
import { HttpServer } from "../core/httpServer.core.js";
|
|
7
|
-
import type { HttpServerState, HttpServerAddress } from "../types/httpServer.type.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
import type { HttpServerState, HttpServerAddress, HttpServerOptions } from "../types/httpServer.type.js";
|
|
8
|
+
/**
|
|
9
|
+
* Creates an HTTP server around an adapter.
|
|
10
|
+
*
|
|
11
|
+
* The options are `HttpServerOptions`, so `handler: async (request) => ...`
|
|
12
|
+
* infers `request` as `HttpRequestContext` (it used to be typed `unknown`,
|
|
13
|
+
* which made the quick start fail under `strict` with TS7006), and
|
|
14
|
+
* `errorHandler` receives the thrown error and the request.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createHttpServer(options: HttpServerOptions): HttpServer;
|
|
16
17
|
export declare function startServer(server: HttpServer): Promise<HttpServer>;
|
|
17
18
|
export declare function stopServer(server: HttpServer): Promise<HttpServer>;
|
|
18
19
|
export declare function restartServer(server: HttpServer): Promise<HttpServer>;
|
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { HttpServerLifecycleError } from "@zudojs/errors";
|
|
7
7
|
import { HttpServer } from "../core/httpServer.core.js";
|
|
8
|
+
/**
|
|
9
|
+
* Creates an HTTP server around an adapter.
|
|
10
|
+
*
|
|
11
|
+
* The options are `HttpServerOptions`, so `handler: async (request) => ...`
|
|
12
|
+
* infers `request` as `HttpRequestContext` (it used to be typed `unknown`,
|
|
13
|
+
* which made the quick start fail under `strict` with TS7006), and
|
|
14
|
+
* `errorHandler` receives the thrown error and the request.
|
|
15
|
+
*/
|
|
8
16
|
export function createHttpServer(options) {
|
|
9
17
|
return new HttpServer(options);
|
|
10
18
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,8 @@ export * from "./httpAgent/index.js";
|
|
|
49
49
|
export * from "./httpProxy/index.js";
|
|
50
50
|
export * from "./httpSecurity/index.js";
|
|
51
51
|
export * from "./httpRouter/index.js";
|
|
52
|
+
export * from "./httpOpenApi/index.js";
|
|
53
|
+
export * from "./httpFetchMount/index.js";
|
|
52
54
|
/**
|
|
53
55
|
* Several sub-modules export the same name. A star export alone would make
|
|
54
56
|
* those names unavailable (TS2308), so ownership is declared explicitly here.
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,8 @@ export * from "./httpAgent/index.js";
|
|
|
49
49
|
export * from "./httpProxy/index.js";
|
|
50
50
|
export * from "./httpSecurity/index.js";
|
|
51
51
|
export * from "./httpRouter/index.js";
|
|
52
|
+
export * from "./httpOpenApi/index.js";
|
|
53
|
+
export * from "./httpFetchMount/index.js";
|
|
52
54
|
/* -------------------------------------------------------------------------- */
|
|
53
55
|
/* Ambiguous re-exports */
|
|
54
56
|
/* -------------------------------------------------------------------------- */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/http",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "HTTP primitives, request handling, routing, middleware, and server infrastructure for Zudojs applications.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -24,17 +24,20 @@
|
|
|
24
24
|
"!dist/.tsbuildinfo"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@zudojs/crypto": "1.
|
|
28
|
-
"@zudojs/errors": "1.
|
|
29
|
-
"@zudojs/logger": "1.
|
|
30
|
-
"@zudojs/
|
|
27
|
+
"@zudojs/crypto": "1.3.1",
|
|
28
|
+
"@zudojs/errors": "1.3.0",
|
|
29
|
+
"@zudojs/logger": "1.4.0",
|
|
30
|
+
"@zudojs/middleware": "1.1.0",
|
|
31
|
+
"@zudojs/openapi": "1.5.0",
|
|
32
|
+
"@zudojs/security": "1.3.0"
|
|
31
33
|
},
|
|
32
34
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^26.
|
|
35
|
+
"@types/node": "^26.6.2",
|
|
36
|
+
"@zudojs/schema": "1.2.0",
|
|
34
37
|
"fluent-ffmpeg": "^2.1.3",
|
|
35
38
|
"sharp": "^0.35.4",
|
|
36
39
|
"typescript": "7.0.2",
|
|
37
|
-
"vitest": "^
|
|
40
|
+
"vitest": "^5.0.1"
|
|
38
41
|
},
|
|
39
42
|
"engines": {
|
|
40
43
|
"node": ">=24.0.0"
|
|
@@ -49,7 +52,7 @@
|
|
|
49
52
|
"middleware",
|
|
50
53
|
"routing"
|
|
51
54
|
],
|
|
52
|
-
"homepage": "https://
|
|
55
|
+
"homepage": "https://zudojs.oyinlola.site/docs/packages-http",
|
|
53
56
|
"bugs": {
|
|
54
57
|
"url": "https://github.com/oyinlola-tech/zudo/issues"
|
|
55
58
|
},
|