@rimelight/security 0.0.15 → 0.0.17

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.
@@ -1,3 +1,3 @@
1
- import { n as SecurityOptions, t as ConstructionOptions } from "../types-BdTXMZBc.mjs";
1
+ import { i as SecurityOptions, n as RateLimitOptions, r as RateLimiterBinding, t as ConstructionOptions } from "../types-Dcvwj-af.mjs";
2
2
  import { buildCspHeader } from "../csp.mjs";
3
- export { ConstructionOptions, SecurityOptions, buildCspHeader };
3
+ export { ConstructionOptions, RateLimitOptions, RateLimiterBinding, SecurityOptions, buildCspHeader };
package/dist/csp.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as SecurityOptions } from "./types-BdTXMZBc.mjs";
1
+ import { i as SecurityOptions } from "./types-Dcvwj-af.mjs";
2
2
  //#region src/csp.d.ts
3
3
  /**
4
4
  * Builds the Content-Security-Policy header string dynamically for a given request nonce.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { n as SecurityOptions, t as ConstructionOptions } from "./types-BdTXMZBc.mjs";
1
+ import { i as SecurityOptions, n as RateLimitOptions, r as RateLimiterBinding, t as ConstructionOptions } from "./types-Dcvwj-af.mjs";
2
2
  import { buildCspHeader } from "./csp.mjs";
3
3
  import { RimelightSecurityPlugin, SecurityPluginOptions, security } from "./vite.mjs";
4
4
  import { CONSTRUCTION_GUEST_COOKIE, construction, isConstructionGuest, signInConstructionGuest } from "./middleware/construction.mjs";
5
- export { CONSTRUCTION_GUEST_COOKIE, ConstructionOptions, RimelightSecurityPlugin, SecurityOptions, SecurityPluginOptions, buildCspHeader, construction, isConstructionGuest, security, security as sri, signInConstructionGuest };
5
+ export { CONSTRUCTION_GUEST_COOKIE, ConstructionOptions, RateLimitOptions, RateLimiterBinding, RimelightSecurityPlugin, SecurityOptions, SecurityPluginOptions, buildCspHeader, construction, isConstructionGuest, security, security as sri, signInConstructionGuest };
@@ -1,4 +1,4 @@
1
- import { t as ConstructionOptions } from "../types-BdTXMZBc.mjs";
1
+ import { t as ConstructionOptions } from "../types-Dcvwj-af.mjs";
2
2
  //#region src/middleware/construction.d.ts
3
3
  export declare const CONSTRUCTION_GUEST_COOKIE = "rimelight-construction-guest";
4
4
  /**
@@ -1,4 +1,5 @@
1
1
  import { CONSTRUCTION_GUEST_COOKIE, construction, isConstructionGuest, signInConstructionGuest } from "./construction.mjs";
2
2
  import { devOnly } from "./dev-only.mjs";
3
3
  import { security } from "./security.mjs";
4
- export { CONSTRUCTION_GUEST_COOKIE, construction, devOnly, isConstructionGuest, security, signInConstructionGuest };
4
+ import { ratelimit } from "./ratelimit.mjs";
5
+ export { CONSTRUCTION_GUEST_COOKIE, construction, devOnly, isConstructionGuest, ratelimit, security, signInConstructionGuest };
@@ -1,4 +1,5 @@
1
1
  import { CONSTRUCTION_GUEST_COOKIE, construction, isConstructionGuest, signInConstructionGuest } from "./construction.mjs";
2
2
  import { devOnly } from "./dev-only.mjs";
3
3
  import { security } from "./security.mjs";
4
- export { CONSTRUCTION_GUEST_COOKIE, construction, devOnly, isConstructionGuest, security, signInConstructionGuest };
4
+ import { ratelimit } from "./ratelimit.mjs";
5
+ export { CONSTRUCTION_GUEST_COOKIE, construction, devOnly, isConstructionGuest, ratelimit, security, signInConstructionGuest };
@@ -0,0 +1,22 @@
1
+ import { n as RateLimitOptions } from "../types-Dcvwj-af.mjs";
2
+ //#region src/middleware/ratelimit.d.ts
3
+ /**
4
+ * Middleware to enforce rate limits on sensitive endpoints using Cloudflare Rate Limiting bindings.
5
+ *
6
+ * @example
7
+ * // fetch.ts
8
+ * import { ratelimit } from "@rimelight/security/middleware"
9
+ * app.use(ratelimit())
10
+ *
11
+ * @example
12
+ * // Custom configuration
13
+ * app.use(
14
+ * ratelimit({
15
+ * routes: ["/api/checkout", "/auth/login"],
16
+ * retryAfter: 30,
17
+ * bindingName: "MY_RATE_LIMITER"
18
+ * })
19
+ * )
20
+ */
21
+ export declare const ratelimit: (options?: RateLimitOptions) => (c: any, next: () => Promise<any> | any) => Promise<Response | any>;
22
+ //#endregion
@@ -0,0 +1,74 @@
1
+ //#region src/middleware/ratelimit.ts
2
+ const DEFAULT_SENSITIVE_ROUTES = [
3
+ "/auth/sign-in",
4
+ "/auth/sign-up",
5
+ "/api/upload",
6
+ "/api/chat"
7
+ ];
8
+ /**
9
+ * Middleware to enforce rate limits on sensitive endpoints using Cloudflare Rate Limiting bindings.
10
+ *
11
+ * @example
12
+ * // fetch.ts
13
+ * import { ratelimit } from "@rimelight/security/middleware"
14
+ * app.use(ratelimit())
15
+ *
16
+ * @example
17
+ * // Custom configuration
18
+ * app.use(
19
+ * ratelimit({
20
+ * routes: ["/api/checkout", "/auth/login"],
21
+ * retryAfter: 30,
22
+ * bindingName: "MY_RATE_LIMITER"
23
+ * })
24
+ * )
25
+ */
26
+ const ratelimit = (options = {}) => {
27
+ const { bindingName = "MY_RATE_LIMITER", routes = DEFAULT_SENSITIVE_ROUTES, retryAfter = 60, fallback = "pass", keyGenerator = (c) => c.req.header("CF-Connecting-IP") || c.req.header("x-forwarded-for") || "unknown", onRateLimited = (c, retry) => {
28
+ if (typeof c.json === "function") return c.json({
29
+ error: "Too Many Requests",
30
+ message: "Rate limit exceeded. Please try again later."
31
+ }, 429, { "Retry-After": String(retry) });
32
+ return new Response(JSON.stringify({
33
+ error: "Too Many Requests",
34
+ message: "Rate limit exceeded. Please try again later."
35
+ }), {
36
+ status: 429,
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ "Retry-After": String(retry)
40
+ }
41
+ });
42
+ } } = options;
43
+ return async (c, next) => {
44
+ const path = c?.req?.path || "";
45
+ if (!(typeof routes === "function" ? routes(c) : routes.some((route) => typeof route === "string" ? path.includes(route) : route.test(path)))) return next();
46
+ const bindings = c?.env;
47
+ const limiter = options.limiter ? options.limiter(c) : bindings?.[bindingName];
48
+ if (!limiter || typeof limiter.limit !== "function") {
49
+ if (fallback === "pass") return next();
50
+ if (typeof c.json === "function") return c.json({ error: "Rate limiter not configured" }, 500);
51
+ return new Response(JSON.stringify({ error: "Rate limiter not configured" }), {
52
+ status: 500,
53
+ headers: { "Content-Type": "application/json" }
54
+ });
55
+ }
56
+ try {
57
+ const clientKey = await keyGenerator(c);
58
+ const { success } = await limiter.limit({ key: clientKey });
59
+ if (!success) return onRateLimited(c, retryAfter);
60
+ } catch (error) {
61
+ console.error("[Rate Limit Error]", error);
62
+ if (fallback !== "pass") {
63
+ if (typeof c.json === "function") return c.json({ error: "Rate limit check failed" }, 500);
64
+ return new Response(JSON.stringify({ error: "Rate limit check failed" }), {
65
+ status: 500,
66
+ headers: { "Content-Type": "application/json" }
67
+ });
68
+ }
69
+ }
70
+ return next();
71
+ };
72
+ };
73
+ //#endregion
74
+ export { ratelimit };
@@ -1,4 +1,4 @@
1
- import { n as SecurityOptions } from "../types-BdTXMZBc.mjs";
1
+ import { i as SecurityOptions } from "../types-Dcvwj-af.mjs";
2
2
  //#region src/middleware/security.d.ts
3
3
  /**
4
4
  * Universal Security Middleware for Hono and Web Standards (Fetch API). Injects security headers,
@@ -117,5 +117,56 @@ interface ConstructionOptions {
117
117
  redirectUrl: string;
118
118
  }) => Response | Promise<Response>;
119
119
  }
120
+ interface RateLimiterBinding {
121
+ limit(options: {
122
+ key: string;
123
+ }): Promise<{
124
+ success: boolean;
125
+ }>;
126
+ }
127
+ interface RateLimitOptions {
128
+ /**
129
+ * Name of the Cloudflare Rate Limiter binding on `c.env` / `env`.
130
+ *
131
+ * @default "MY_RATE_LIMITER"
132
+ */
133
+ bindingName?: string;
134
+ /**
135
+ * Direct rate limiter instance or binding resolver.
136
+ */
137
+ limiter?: (c: any) => RateLimiterBinding | undefined;
138
+ /**
139
+ * Routes / path prefixes or a custom predicate to check if the request should be rate limited.
140
+ * Can be an array of strings/RegExp or a matcher function `(c: any) => boolean`.
141
+ *
142
+ * @default ["/auth/sign-in", "/auth/sign-up", "/api/upload", "/api/chat"]
143
+ */
144
+ routes?: (string | RegExp)[] | ((c: any) => boolean);
145
+ /**
146
+ * Function to extract the rate limit key from the context (e.g., client IP, user ID, API key).
147
+ *
148
+ * @default c.req.header("CF-Connecting-IP") || c.req.header("x-forwarded-for") || "unknown"
149
+ */
150
+ keyGenerator?: (c: any) => string | Promise<string>;
151
+ /**
152
+ * Retry-After header value in seconds.
153
+ *
154
+ * @default 60
155
+ */
156
+ retryAfter?: number;
157
+ /**
158
+ * Behavior when no rate limiter binding exists (e.g., in local development without mock binding).
159
+ *
160
+ * - "pass": Fail open (call `next()`)
161
+ * - "block": Fail closed (return 429/500)
162
+ *
163
+ * @default "pass"
164
+ */
165
+ fallback?: "pass" | "block";
166
+ /**
167
+ * Custom handler when the rate limit is exceeded.
168
+ */
169
+ onRateLimited?: (c: any, retryAfter: number) => Response | Promise<Response>;
170
+ }
120
171
  //#endregion
121
- export { SecurityOptions as n, ConstructionOptions as t };
172
+ export { SecurityOptions as i, RateLimitOptions as n, RateLimiterBinding as r, ConstructionOptions as t };
package/dist/types.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as SecurityOptions, t as ConstructionOptions } from "./types-BdTXMZBc.mjs";
2
- export { ConstructionOptions, SecurityOptions };
1
+ import { i as SecurityOptions, n as RateLimitOptions, r as RateLimiterBinding, t as ConstructionOptions } from "./types-Dcvwj-af.mjs";
2
+ export { ConstructionOptions, RateLimitOptions, RateLimiterBinding, SecurityOptions };
package/dist/vite.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as SecurityOptions } from "./types-BdTXMZBc.mjs";
1
+ import { i as SecurityOptions } from "./types-Dcvwj-af.mjs";
2
2
  //#region src/vite.d.ts
3
3
  export interface RimelightSecurityPlugin {
4
4
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelight/security",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "private": false,
5
5
  "description": "Rimelight Entertainment's Security Package",
6
6
  "homepage": "https://rimelight.com/docs",
@@ -39,13 +39,13 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@rimelight/ui": "0.0.52"
42
+ "@rimelight/ui": "0.0.56"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@astrojs/check": "0.9.10",
46
- "@rimelight/config": "0.0.11",
47
- "astro": "7.3.2",
48
- "hono": "4.13.7",
46
+ "@rimelight/config": "0.0.13",
47
+ "astro": "7.3.3",
48
+ "hono": "4.13.8",
49
49
  "typescript": "6.0.3"
50
50
  },
51
51
  "peerDependencies": {