@daloyjs/core 1.0.0-rc.6 → 1.0.0-rc.7
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 +3 -2
- package/dist/auto-ban.d.ts +16 -0
- package/dist/auto-ban.js +19 -9
- package/dist/bot-guard.d.ts +14 -0
- package/dist/bot-guard.js +12 -12
- package/dist/concurrency-limit.d.ts +14 -0
- package/dist/concurrency-limit.js +18 -9
- package/dist/conn-info.d.ts +65 -0
- package/dist/conn-info.js +99 -4
- package/dist/geo-block.d.ts +15 -0
- package/dist/geo-block.js +11 -11
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/ip-reputation.d.ts +14 -0
- package/dist/ip-reputation.js +10 -10
- package/dist/ip-restriction.d.ts +14 -0
- package/dist/ip-restriction.js +5 -7
- package/dist/mcp.d.ts +305 -34
- package/dist/mcp.js +554 -49
- package/dist/middleware.d.ts +31 -1
- package/dist/middleware.js +21 -19
- package/dist/sbom.cdx.json +9 -9
- package/dist/sbom.spdx.json +5 -5
- package/package.json +1 -1
package/dist/middleware.d.ts
CHANGED
|
@@ -470,8 +470,22 @@ export interface RateLimitOptions {
|
|
|
470
470
|
* Trust x-forwarded-for / x-real-ip when deriving the default key.
|
|
471
471
|
* Off by default because those headers are client-spoofable unless your
|
|
472
472
|
* reverse proxy strips and rewrites them.
|
|
473
|
+
*
|
|
474
|
+
* When enabled, the key is the **rightmost** `X-Forwarded-For` entry — the
|
|
475
|
+
* one your immediate proxy appended — never the attacker-influenceable
|
|
476
|
+
* leftmost one, so rotating spoofed left entries cannot evade the limit.
|
|
477
|
+
* Behind more than one proxy hop, set {@link trustedHops} instead.
|
|
473
478
|
*/
|
|
474
479
|
trustProxyHeaders?: boolean;
|
|
480
|
+
/**
|
|
481
|
+
* Declare exactly how many proxy hops sit between Daloy and the public
|
|
482
|
+
* internet. Implies proxy-header trust and derives the default key that
|
|
483
|
+
* many entries from the right of `X-Forwarded-For` via
|
|
484
|
+
* {@link "./conn-info.js".resolveForwardedClientIp}. Must be an integer in
|
|
485
|
+
* [1, 64]; validated at construction. Ignored when a custom `keyGenerator`
|
|
486
|
+
* is supplied.
|
|
487
|
+
*/
|
|
488
|
+
trustedHops?: number;
|
|
475
489
|
/** When true, set Retry-After header on 429. Default: true. */
|
|
476
490
|
retryAfter?: boolean;
|
|
477
491
|
/**
|
|
@@ -546,8 +560,24 @@ export interface LoginThrottleOptions {
|
|
|
546
560
|
keyGenerator?: (ctx: RateLimitContext) => string;
|
|
547
561
|
/** Shared store for the hard limit. Uses rateLimit()'s in-memory group bucket by default. */
|
|
548
562
|
store?: RateLimitStore;
|
|
549
|
-
/** Trust x-forwarded-for / x-real-ip when deriving the default key. Default: false.
|
|
563
|
+
/** Trust x-forwarded-for / x-real-ip when deriving the default key. Default: false.
|
|
564
|
+
*
|
|
565
|
+
* When enabled, the key is the **rightmost** `X-Forwarded-For` entry — the
|
|
566
|
+
* one your immediate proxy appended — never the attacker-influenceable
|
|
567
|
+
* leftmost one. Behind more than one proxy hop, set {@link trustedHops}
|
|
568
|
+
* instead.
|
|
569
|
+
*/
|
|
550
570
|
trustProxyHeaders?: boolean;
|
|
571
|
+
/**
|
|
572
|
+
* Declare exactly how many proxy hops sit between Daloy and the public
|
|
573
|
+
* internet. Implies proxy-header trust and derives the default key that
|
|
574
|
+
* many entries from the right of `X-Forwarded-For` via
|
|
575
|
+
* {@link "./conn-info.js".resolveForwardedClientIp}, so rotating spoofed
|
|
576
|
+
* left entries cannot evade the throttle. Must be an integer in [1, 64];
|
|
577
|
+
* validated at construction. Ignored when a custom `keyGenerator` is
|
|
578
|
+
* supplied.
|
|
579
|
+
*/
|
|
580
|
+
trustedHops?: number;
|
|
551
581
|
/** When true, set Retry-After header on 429. Default: true. */
|
|
552
582
|
retryAfter?: boolean;
|
|
553
583
|
/** Start slowing responses after this many attempts in the same window. Default: 2. */
|
package/dist/middleware.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { assertCookieAttributes, readRequestCookie, serializeCookie } from "./cookie.js";
|
|
8
8
|
import { TooManyRequestsError, ForbiddenError } from "./errors.js";
|
|
9
9
|
import { randomId, sanitizeHeaderName, timingSafeEqual } from "./security.js";
|
|
10
|
+
import { resolveForwardedClientIp, resolveForwardedTrust } from "./conn-info.js";
|
|
10
11
|
/**
|
|
11
12
|
* Generate or accept a stable `X-Request-ID` for every request. The id is
|
|
12
13
|
* stamped on `ctx.state.requestId`, mirrored on outgoing response headers,
|
|
@@ -775,15 +776,8 @@ export function rateLimit(opts) {
|
|
|
775
776
|
store = new MemoryStore();
|
|
776
777
|
}
|
|
777
778
|
const groupPrefix = opts.groupId ? `${opts.groupId}:` : "";
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
if (opts.trustProxyHeaders) {
|
|
781
|
-
const xff = ctx.request.headers.get("x-forwarded-for");
|
|
782
|
-
const first = xff ? xff.split(",")[0].trim() : "";
|
|
783
|
-
return first || ctx.request.headers.get("x-real-ip") || "global";
|
|
784
|
-
}
|
|
785
|
-
return "global";
|
|
786
|
-
});
|
|
779
|
+
const hops = resolveForwardedTrust("rateLimit()", opts);
|
|
780
|
+
const keyOf = opts.keyGenerator ?? defaultForwardedRateLimitKey(hops);
|
|
787
781
|
const enforce = async (ctx) => {
|
|
788
782
|
const key = `${groupPrefix}${keyOf(ctx)}`;
|
|
789
783
|
const { count, resetMs } = await store.hit(key, opts.windowMs);
|
|
@@ -811,15 +805,22 @@ function assertPositiveInteger(name, value) {
|
|
|
811
805
|
throw new Error(`loginThrottle(): ${name} must be a positive integer.`);
|
|
812
806
|
}
|
|
813
807
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
808
|
+
/**
|
|
809
|
+
* Default rate-limit / login-throttle key: the spoof-resistant forwarded client
|
|
810
|
+
* IP, or the shared `"global"` bucket when proxy-header trust is off or the
|
|
811
|
+
* request carries no trustworthy forwarded identity.
|
|
812
|
+
*
|
|
813
|
+
* @param hops - Trusted proxy hop count from
|
|
814
|
+
* {@link "./conn-info.js".resolveForwardedTrust}, or `undefined` when
|
|
815
|
+
* forwarded-header trust is disabled.
|
|
816
|
+
* @returns A key generator suitable for {@link rateLimit} and
|
|
817
|
+
* {@link loginThrottle}.
|
|
818
|
+
* @internal
|
|
819
|
+
*/
|
|
820
|
+
function defaultForwardedRateLimitKey(hops) {
|
|
821
|
+
if (hops === undefined)
|
|
822
|
+
return () => "global";
|
|
823
|
+
return (ctx) => resolveForwardedClientIp(ctx.request, hops) ?? "global";
|
|
823
824
|
}
|
|
824
825
|
function wait(ms) {
|
|
825
826
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -852,7 +853,8 @@ export function loginThrottle(opts = {}) {
|
|
|
852
853
|
assertNonNegativeInteger("delayMs", delayMs);
|
|
853
854
|
assertNonNegativeInteger("maxDelayMs", maxDelayMs);
|
|
854
855
|
const groupId = opts.groupId ?? "login";
|
|
855
|
-
const
|
|
856
|
+
const hops = resolveForwardedTrust("loginThrottle()", opts);
|
|
857
|
+
const keyGenerator = opts.keyGenerator ?? defaultForwardedRateLimitKey(hops);
|
|
856
858
|
const limiter = rateLimit({
|
|
857
859
|
windowMs,
|
|
858
860
|
max,
|
package/dist/sbom.cdx.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.5",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:01ee81d6-1bb6-55ca-b05e-3e30279d9f5c",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-07-
|
|
7
|
+
"timestamp": "2026-07-29T20:03:05.244Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "DaloyJS",
|
|
11
11
|
"name": "daloy-generate-sbom",
|
|
12
|
-
"version": "1.0.0-rc.
|
|
12
|
+
"version": "1.0.0-rc.7"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"authors": [
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
],
|
|
20
20
|
"component": {
|
|
21
21
|
"type": "library",
|
|
22
|
-
"bom-ref": "pkg:npm/@daloyjs/core@1.0.0-rc.
|
|
22
|
+
"bom-ref": "pkg:npm/@daloyjs/core@1.0.0-rc.7",
|
|
23
23
|
"name": "@daloyjs/core",
|
|
24
|
-
"version": "1.0.0-rc.
|
|
24
|
+
"version": "1.0.0-rc.7",
|
|
25
25
|
"description": "DaloyJS is a runtime-portable, contract-first TypeScript web framework with built-in OpenAPI (Hey API), typed client generation, large-scale maintainability, and security-first defaults. Hono-grade portability, Elysia-grade DX, FastAPI-grade docs, Fastify-grade ops — distributed via pnpm.",
|
|
26
|
-
"purl": "pkg:npm/@daloyjs/core@1.0.0-rc.
|
|
26
|
+
"purl": "pkg:npm/@daloyjs/core@1.0.0-rc.7",
|
|
27
27
|
"licenses": [
|
|
28
28
|
{
|
|
29
29
|
"license": {
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
}
|
|
47
47
|
],
|
|
48
48
|
"swid": {
|
|
49
|
-
"tagId": "swidtag--daloyjs-core-1.0.0-rc.
|
|
49
|
+
"tagId": "swidtag--daloyjs-core-1.0.0-rc.7",
|
|
50
50
|
"name": "@daloyjs/core",
|
|
51
|
-
"version": "1.0.0-rc.
|
|
51
|
+
"version": "1.0.0-rc.7",
|
|
52
52
|
"tagVersion": 0,
|
|
53
53
|
"patch": false
|
|
54
54
|
}
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"components": [],
|
|
58
58
|
"dependencies": [
|
|
59
59
|
{
|
|
60
|
-
"ref": "pkg:npm/@daloyjs/core@1.0.0-rc.
|
|
60
|
+
"ref": "pkg:npm/@daloyjs/core@1.0.0-rc.7",
|
|
61
61
|
"dependsOn": []
|
|
62
62
|
}
|
|
63
63
|
]
|
package/dist/sbom.spdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "@daloyjs/core-1.0.0-rc.
|
|
6
|
-
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-1.0.0-rc.
|
|
5
|
+
"name": "@daloyjs/core-1.0.0-rc.7",
|
|
6
|
+
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-1.0.0-rc.7-01ee81d6-1bb6-55ca-b05e-3e30279d9f5c",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-07-
|
|
8
|
+
"created": "2026-07-29T20:03:05.244Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: daloy-generate-sbom",
|
|
11
11
|
"Organization: DaloyJS"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"SPDXID": "SPDXRef-Package--daloyjs-core",
|
|
18
18
|
"name": "@daloyjs/core",
|
|
19
|
-
"versionInfo": "1.0.0-rc.
|
|
19
|
+
"versionInfo": "1.0.0-rc.7",
|
|
20
20
|
"downloadLocation": "https://github.com/daloyjs/daloy",
|
|
21
21
|
"filesAnalyzed": false,
|
|
22
22
|
"licenseConcluded": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
{
|
|
28
28
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
29
29
|
"referenceType": "purl",
|
|
30
|
-
"referenceLocator": "pkg:npm/@daloyjs/core@1.0.0-rc.
|
|
30
|
+
"referenceLocator": "pkg:npm/@daloyjs/core@1.0.0-rc.7"
|
|
31
31
|
}
|
|
32
32
|
]
|
|
33
33
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daloyjs/core",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.7",
|
|
4
4
|
"description": "DaloyJS is a runtime-portable, contract-first TypeScript web framework with built-in OpenAPI (Hey API), typed client generation, large-scale maintainability, and security-first defaults. Hono-grade portability, Elysia-grade DX, FastAPI-grade docs, Fastify-grade ops — distributed via pnpm.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|