@digilogiclabs/platform-core 1.6.0 → 1.8.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/auth.d.mts CHANGED
@@ -1,2 +1,175 @@
1
- export { aq as AllowlistConfig, j as ApiError, A as ApiErrorCode, n as ApiErrorCodeType, p as ApiPaginatedResponse, Z as ApiSecurityConfig, $ as ApiSecurityContext, o as ApiSuccessResponse, aN as AuditRequest, L as AuthCookiesConfig, V as AuthMethod, C as CommonApiErrors, ax as CommonRateLimits, ad as DateRangeInput, a6 as DateRangeSchema, al as DeploymentStage, ab as EmailInput, a0 as EmailSchema, aW as EnvValidationConfig, aX as EnvValidationResult, an as FlagDefinition, ao as FlagDefinitions, am as FlagValue, K as KEYCLOAK_DEFAULT_ROLES, I as KeycloakCallbacksConfig, B as KeycloakConfig, J as KeycloakJwtFields, D as KeycloakTokenSet, af as LoginInput, a8 as LoginSchema, aI as OpsAuditActor, aK as OpsAuditEvent, aM as OpsAuditLoggerOptions, aL as OpsAuditRecord, aJ as OpsAuditResource, ac as PaginationInput, a5 as PaginationSchema, a1 as PasswordSchema, a4 as PersonNameSchema, a3 as PhoneSchema, az as RateLimitCheckResult, aB as RateLimitOptions, Y as RateLimitPreset, ay as RateLimitRule, aA as RateLimitStore, R as RedirectCallbackConfig, ap as ResolvedFlags, X as RouteAuditConfig, ae as SearchQueryInput, a7 as SearchQuerySchema, _ as SecuritySession, ag as SignupInput, a9 as SignupSchema, a2 as SlugSchema, aO as StandardAuditActionType, aH as StandardAuditActions, S as StandardRateLimitPresets, T as TokenRefreshResult, W as WrapperPresets, aj as buildAllowlist, F as buildAuthCookies, Q as buildErrorBody, E as buildKeycloakCallbacks, m as buildPagination, O as buildRateLimitHeaders, av as buildRateLimitResponseHeaders, G as buildRedirectCallback, w as buildTokenRefreshParams, aU as checkEnvVars, ar as checkRateLimit, l as classifyError, f as constantTimeEqual, a as containsHtml, c as containsUrls, aD as createAuditActor, aC as createAuditLogger, ah as createFeatureFlags, au as createMemoryRateLimitStore, aa as createSafeTextSchema, ai as detectStage, e as escapeHtml, aE as extractAuditIp, aG as extractAuditRequestId, aF as extractAuditUserAgent, N as extractClientIp, aR as getBoolEnv, h as getCorrelationId, y as getEndSessionEndpoint, aV as getEnvSummary, aS as getIntEnv, aQ as getOptionalEnv, as as getRateLimitStatus, aP as getRequiredEnv, x as getTokenEndpoint, u as hasAllRoles, t as hasAnyRole, r as hasRole, ak as isAllowlisted, k as isApiError, v as isTokenExpired, q as parseKeycloakRoles, z as refreshKeycloakToken, at as resetRateLimitForKey, aw as resolveIdentifier, M as resolveRateLimitIdentifier, g as sanitizeApiError, s as stripHtml, aT as validateEnvVars } from './index-CkyVz0hQ.mjs';
1
+ import { R as RateLimitStore, a as RateLimitRule, b as RateLimitOptions } from './env-jqNJdZVt.mjs';
2
+ export { as as AllowlistConfig, A as ApiError, k as ApiErrorCode, m as ApiErrorCodeType, o as ApiPaginatedResponse, _ as ApiSecurityConfig, a0 as ApiSecurityContext, n as ApiSuccessResponse, aK as AuditRequest, P as AuthCookiesConfig, W as AuthMethod, aS as BetaClientConfig, C as CommonApiErrors, ay as CommonRateLimits, aj as DateRangeInput, ad as DateRangeSchema, an as DeploymentStage, ah as EmailInput, a6 as EmailSchema, E as EnvValidationConfig, x as EnvValidationResult, ap as FlagDefinition, aq as FlagDefinitions, ao as FlagValue, z as KEYCLOAK_DEFAULT_ROLES, N as KeycloakCallbacksConfig, K as KeycloakConfig, O as KeycloakJwtFields, y as KeycloakTokenSet, al as LoginInput, af as LoginSchema, aF as OpsAuditActor, aH as OpsAuditEvent, aJ as OpsAuditLoggerOptions, aI as OpsAuditRecord, aG as OpsAuditResource, ai as PaginationInput, ac as PaginationSchema, a7 as PasswordSchema, aa as PersonNameSchema, a9 as PhoneSchema, ax as RateLimitCheckResult, Y as RateLimitPreset, S as RedirectCallbackConfig, ar as ResolvedFlags, X as RouteAuditConfig, ak as SearchQueryInput, ae as SearchQuerySchema, $ as SecuritySession, am as SignupInput, ag as SignupSchema, a8 as SlugSchema, aM as StandardAuditActionType, aL as StandardAuditActions, Z as StandardRateLimitPresets, T as TokenRefreshResult, a5 as WrapperPresets, av as buildAllowlist, Q as buildAuthCookies, a4 as buildErrorBody, V as buildKeycloakCallbacks, l as buildPagination, a3 as buildRateLimitHeaders, aD as buildRateLimitResponseHeaders, U as buildRedirectCallback, I as buildTokenRefreshParams, u as checkEnvVars, aA as checkRateLimit, i as classifyError, aY as clearStoredBetaCode, c as constantTimeEqual, f as containsHtml, d as containsUrls, aQ as createAuditActor, aR as createAuditLogger, aT as createBetaClient, au as createFeatureFlags, az as createMemoryRateLimitStore, ab as createSafeTextSchema, at as detectStage, e as escapeHtml, aN as extractAuditIp, aP as extractAuditRequestId, aO as extractAuditUserAgent, a2 as extractClientIp, aU as fetchBetaSettings, r as getBoolEnv, h as getCorrelationId, L as getEndSessionEndpoint, w as getEnvSummary, t as getIntEnv, q as getOptionalEnv, aB as getRateLimitStatus, p as getRequiredEnv, aX as getStoredBetaCode, J as getTokenEndpoint, G as hasAllRoles, F as hasAnyRole, D as hasRole, aw as isAllowlisted, j as isApiError, H as isTokenExpired, B as parseKeycloakRoles, M as refreshKeycloakToken, aC as resetRateLimitForKey, aE as resolveIdentifier, a1 as resolveRateLimitIdentifier, g as sanitizeApiError, aW as storeBetaCode, s as stripHtml, aV as validateBetaCode, v as validateEnvVars } from './env-jqNJdZVt.mjs';
2
3
  import 'zod';
4
+
5
+ /**
6
+ * Redis Rate Limit Store
7
+ *
8
+ * Production-ready `RateLimitStore` implementation using Redis sorted sets
9
+ * for accurate sliding window rate limiting. Works with ioredis or any
10
+ * Redis client that supports the required commands.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import Redis from 'ioredis'
15
+ * import {
16
+ * createRedisRateLimitStore,
17
+ * checkRateLimit,
18
+ * CommonRateLimits,
19
+ * } from '@digilogiclabs/platform-core/auth'
20
+ *
21
+ * const redis = new Redis(process.env.REDIS_URL)
22
+ * const store = createRedisRateLimitStore(redis, { keyPrefix: 'myapp:' })
23
+ *
24
+ * const result = await checkRateLimit('api-call', 'user:123', CommonRateLimits.apiGeneral, { store })
25
+ * ```
26
+ */
27
+
28
+ /**
29
+ * Minimal Redis client interface.
30
+ *
31
+ * Compatible with ioredis, node-redis v4, and @upstash/redis.
32
+ * Only the commands used by the rate limiter are required.
33
+ */
34
+ interface RedisRateLimitClient {
35
+ zremrangebyscore(key: string, min: number | string, max: number | string): Promise<number>;
36
+ zadd(key: string, score: number, member: string): Promise<number>;
37
+ zcard(key: string): Promise<number>;
38
+ expire(key: string, seconds: number): Promise<number>;
39
+ get(key: string): Promise<string | null>;
40
+ ttl(key: string): Promise<number>;
41
+ setex(key: string, seconds: number, value: string): Promise<string>;
42
+ del(...keys: string[]): Promise<number>;
43
+ }
44
+ interface RedisRateLimitStoreOptions {
45
+ /** Prefix for all Redis keys (e.g., 'myapp:') */
46
+ keyPrefix?: string;
47
+ }
48
+ /**
49
+ * Create a Redis-backed rate limit store using sorted sets.
50
+ *
51
+ * Uses the sliding window algorithm:
52
+ * - Each request adds a timestamped entry to a sorted set
53
+ * - Old entries (outside the window) are pruned on each check
54
+ * - The set cardinality gives the request count
55
+ *
56
+ * Blocks use simple key-value with TTL.
57
+ */
58
+ declare function createRedisRateLimitStore(redis: RedisRateLimitClient, options?: RedisRateLimitStoreOptions): RateLimitStore;
59
+
60
+ /**
61
+ * Next.js API Route Helpers
62
+ *
63
+ * Shared utilities for Next.js API routes that all apps need.
64
+ * These wrap platform-core's framework-agnostic primitives into
65
+ * Next.js-specific patterns (NextResponse, NextRequest).
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * import {
70
+ * enforceRateLimit,
71
+ * zodErrorResponse,
72
+ * errorResponse,
73
+ * extractBearerToken,
74
+ * isValidBearerToken,
75
+ * } from '@digilogiclabs/platform-core/auth'
76
+ *
77
+ * export async function POST(request: NextRequest) {
78
+ * const rl = await enforceRateLimit(request, 'submit', CommonRateLimits.publicForm)
79
+ * if (rl) return rl
80
+ *
81
+ * const parsed = schema.safeParse(await request.json())
82
+ * if (!parsed.success) return zodErrorResponse(parsed.error)
83
+ *
84
+ * try { ... }
85
+ * catch (error) { return errorResponse(error) }
86
+ * }
87
+ * ```
88
+ */
89
+
90
+ /**
91
+ * Enforce rate limiting on a Next.js API request.
92
+ *
93
+ * Returns a 429 NextResponse if the limit is exceeded, or `null` if allowed.
94
+ * Apps use this at the top of route handlers for early rejection.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const rateLimited = await enforceRateLimit(request, 'sync', CommonRateLimits.adminAction)
99
+ * if (rateLimited) return rateLimited
100
+ * ```
101
+ */
102
+ declare function enforceRateLimit(request: {
103
+ headers: {
104
+ get(name: string): string | null;
105
+ };
106
+ }, operation: string, rule: RateLimitRule, options?: {
107
+ /** Override identifier (default: extracted from x-forwarded-for) */
108
+ identifier?: string;
109
+ /** User ID for per-user limiting */
110
+ userId?: string;
111
+ /** Rate limit store and options */
112
+ rateLimitOptions?: RateLimitOptions;
113
+ }): Promise<Response | null>;
114
+ /**
115
+ * Convert any error into a structured JSON response.
116
+ *
117
+ * Uses platform-core's `classifyError()` to handle ApiError,
118
+ * Zod errors, PostgreSQL errors, and generic errors consistently.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * catch (error) {
123
+ * return errorResponse(error)
124
+ * }
125
+ * ```
126
+ */
127
+ declare function errorResponse(error: unknown, options?: {
128
+ isDevelopment?: boolean;
129
+ }): Response;
130
+ /**
131
+ * Convert a Zod validation error into a user-friendly 400 response.
132
+ *
133
+ * Extracts the first issue and returns a clear error message
134
+ * with the field path (e.g., "email: Invalid email").
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const parsed = schema.safeParse(await request.json())
139
+ * if (!parsed.success) return zodErrorResponse(parsed.error)
140
+ * ```
141
+ */
142
+ declare function zodErrorResponse(error: {
143
+ issues: Array<{
144
+ path: (string | number)[];
145
+ message: string;
146
+ }>;
147
+ }): Response;
148
+ /**
149
+ * Extract a bearer token from the Authorization header.
150
+ *
151
+ * @returns The token string, or null if not present/malformed.
152
+ */
153
+ declare function extractBearerToken(request: {
154
+ headers: {
155
+ get(name: string): string | null;
156
+ };
157
+ }): string | null;
158
+ /**
159
+ * Check if a request's bearer token matches a secret.
160
+ * Uses timing-safe comparison to prevent timing attacks.
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * if (!isValidBearerToken(request, process.env.ADMIN_SECRET)) {
165
+ * return new Response('Unauthorized', { status: 401 })
166
+ * }
167
+ * ```
168
+ */
169
+ declare function isValidBearerToken(request: {
170
+ headers: {
171
+ get(name: string): string | null;
172
+ };
173
+ }, secret: string | undefined): boolean;
174
+
175
+ export { RateLimitOptions, RateLimitRule, RateLimitStore, type RedisRateLimitClient, type RedisRateLimitStoreOptions, createRedisRateLimitStore, enforceRateLimit, errorResponse, extractBearerToken, isValidBearerToken, zodErrorResponse };
package/dist/auth.d.ts CHANGED
@@ -1,2 +1,175 @@
1
- export { aq as AllowlistConfig, j as ApiError, A as ApiErrorCode, n as ApiErrorCodeType, p as ApiPaginatedResponse, Z as ApiSecurityConfig, $ as ApiSecurityContext, o as ApiSuccessResponse, aN as AuditRequest, L as AuthCookiesConfig, V as AuthMethod, C as CommonApiErrors, ax as CommonRateLimits, ad as DateRangeInput, a6 as DateRangeSchema, al as DeploymentStage, ab as EmailInput, a0 as EmailSchema, aW as EnvValidationConfig, aX as EnvValidationResult, an as FlagDefinition, ao as FlagDefinitions, am as FlagValue, K as KEYCLOAK_DEFAULT_ROLES, I as KeycloakCallbacksConfig, B as KeycloakConfig, J as KeycloakJwtFields, D as KeycloakTokenSet, af as LoginInput, a8 as LoginSchema, aI as OpsAuditActor, aK as OpsAuditEvent, aM as OpsAuditLoggerOptions, aL as OpsAuditRecord, aJ as OpsAuditResource, ac as PaginationInput, a5 as PaginationSchema, a1 as PasswordSchema, a4 as PersonNameSchema, a3 as PhoneSchema, az as RateLimitCheckResult, aB as RateLimitOptions, Y as RateLimitPreset, ay as RateLimitRule, aA as RateLimitStore, R as RedirectCallbackConfig, ap as ResolvedFlags, X as RouteAuditConfig, ae as SearchQueryInput, a7 as SearchQuerySchema, _ as SecuritySession, ag as SignupInput, a9 as SignupSchema, a2 as SlugSchema, aO as StandardAuditActionType, aH as StandardAuditActions, S as StandardRateLimitPresets, T as TokenRefreshResult, W as WrapperPresets, aj as buildAllowlist, F as buildAuthCookies, Q as buildErrorBody, E as buildKeycloakCallbacks, m as buildPagination, O as buildRateLimitHeaders, av as buildRateLimitResponseHeaders, G as buildRedirectCallback, w as buildTokenRefreshParams, aU as checkEnvVars, ar as checkRateLimit, l as classifyError, f as constantTimeEqual, a as containsHtml, c as containsUrls, aD as createAuditActor, aC as createAuditLogger, ah as createFeatureFlags, au as createMemoryRateLimitStore, aa as createSafeTextSchema, ai as detectStage, e as escapeHtml, aE as extractAuditIp, aG as extractAuditRequestId, aF as extractAuditUserAgent, N as extractClientIp, aR as getBoolEnv, h as getCorrelationId, y as getEndSessionEndpoint, aV as getEnvSummary, aS as getIntEnv, aQ as getOptionalEnv, as as getRateLimitStatus, aP as getRequiredEnv, x as getTokenEndpoint, u as hasAllRoles, t as hasAnyRole, r as hasRole, ak as isAllowlisted, k as isApiError, v as isTokenExpired, q as parseKeycloakRoles, z as refreshKeycloakToken, at as resetRateLimitForKey, aw as resolveIdentifier, M as resolveRateLimitIdentifier, g as sanitizeApiError, s as stripHtml, aT as validateEnvVars } from './index-CkyVz0hQ.js';
1
+ import { R as RateLimitStore, a as RateLimitRule, b as RateLimitOptions } from './env-jqNJdZVt.js';
2
+ export { as as AllowlistConfig, A as ApiError, k as ApiErrorCode, m as ApiErrorCodeType, o as ApiPaginatedResponse, _ as ApiSecurityConfig, a0 as ApiSecurityContext, n as ApiSuccessResponse, aK as AuditRequest, P as AuthCookiesConfig, W as AuthMethod, aS as BetaClientConfig, C as CommonApiErrors, ay as CommonRateLimits, aj as DateRangeInput, ad as DateRangeSchema, an as DeploymentStage, ah as EmailInput, a6 as EmailSchema, E as EnvValidationConfig, x as EnvValidationResult, ap as FlagDefinition, aq as FlagDefinitions, ao as FlagValue, z as KEYCLOAK_DEFAULT_ROLES, N as KeycloakCallbacksConfig, K as KeycloakConfig, O as KeycloakJwtFields, y as KeycloakTokenSet, al as LoginInput, af as LoginSchema, aF as OpsAuditActor, aH as OpsAuditEvent, aJ as OpsAuditLoggerOptions, aI as OpsAuditRecord, aG as OpsAuditResource, ai as PaginationInput, ac as PaginationSchema, a7 as PasswordSchema, aa as PersonNameSchema, a9 as PhoneSchema, ax as RateLimitCheckResult, Y as RateLimitPreset, S as RedirectCallbackConfig, ar as ResolvedFlags, X as RouteAuditConfig, ak as SearchQueryInput, ae as SearchQuerySchema, $ as SecuritySession, am as SignupInput, ag as SignupSchema, a8 as SlugSchema, aM as StandardAuditActionType, aL as StandardAuditActions, Z as StandardRateLimitPresets, T as TokenRefreshResult, a5 as WrapperPresets, av as buildAllowlist, Q as buildAuthCookies, a4 as buildErrorBody, V as buildKeycloakCallbacks, l as buildPagination, a3 as buildRateLimitHeaders, aD as buildRateLimitResponseHeaders, U as buildRedirectCallback, I as buildTokenRefreshParams, u as checkEnvVars, aA as checkRateLimit, i as classifyError, aY as clearStoredBetaCode, c as constantTimeEqual, f as containsHtml, d as containsUrls, aQ as createAuditActor, aR as createAuditLogger, aT as createBetaClient, au as createFeatureFlags, az as createMemoryRateLimitStore, ab as createSafeTextSchema, at as detectStage, e as escapeHtml, aN as extractAuditIp, aP as extractAuditRequestId, aO as extractAuditUserAgent, a2 as extractClientIp, aU as fetchBetaSettings, r as getBoolEnv, h as getCorrelationId, L as getEndSessionEndpoint, w as getEnvSummary, t as getIntEnv, q as getOptionalEnv, aB as getRateLimitStatus, p as getRequiredEnv, aX as getStoredBetaCode, J as getTokenEndpoint, G as hasAllRoles, F as hasAnyRole, D as hasRole, aw as isAllowlisted, j as isApiError, H as isTokenExpired, B as parseKeycloakRoles, M as refreshKeycloakToken, aC as resetRateLimitForKey, aE as resolveIdentifier, a1 as resolveRateLimitIdentifier, g as sanitizeApiError, aW as storeBetaCode, s as stripHtml, aV as validateBetaCode, v as validateEnvVars } from './env-jqNJdZVt.js';
2
3
  import 'zod';
4
+
5
+ /**
6
+ * Redis Rate Limit Store
7
+ *
8
+ * Production-ready `RateLimitStore` implementation using Redis sorted sets
9
+ * for accurate sliding window rate limiting. Works with ioredis or any
10
+ * Redis client that supports the required commands.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import Redis from 'ioredis'
15
+ * import {
16
+ * createRedisRateLimitStore,
17
+ * checkRateLimit,
18
+ * CommonRateLimits,
19
+ * } from '@digilogiclabs/platform-core/auth'
20
+ *
21
+ * const redis = new Redis(process.env.REDIS_URL)
22
+ * const store = createRedisRateLimitStore(redis, { keyPrefix: 'myapp:' })
23
+ *
24
+ * const result = await checkRateLimit('api-call', 'user:123', CommonRateLimits.apiGeneral, { store })
25
+ * ```
26
+ */
27
+
28
+ /**
29
+ * Minimal Redis client interface.
30
+ *
31
+ * Compatible with ioredis, node-redis v4, and @upstash/redis.
32
+ * Only the commands used by the rate limiter are required.
33
+ */
34
+ interface RedisRateLimitClient {
35
+ zremrangebyscore(key: string, min: number | string, max: number | string): Promise<number>;
36
+ zadd(key: string, score: number, member: string): Promise<number>;
37
+ zcard(key: string): Promise<number>;
38
+ expire(key: string, seconds: number): Promise<number>;
39
+ get(key: string): Promise<string | null>;
40
+ ttl(key: string): Promise<number>;
41
+ setex(key: string, seconds: number, value: string): Promise<string>;
42
+ del(...keys: string[]): Promise<number>;
43
+ }
44
+ interface RedisRateLimitStoreOptions {
45
+ /** Prefix for all Redis keys (e.g., 'myapp:') */
46
+ keyPrefix?: string;
47
+ }
48
+ /**
49
+ * Create a Redis-backed rate limit store using sorted sets.
50
+ *
51
+ * Uses the sliding window algorithm:
52
+ * - Each request adds a timestamped entry to a sorted set
53
+ * - Old entries (outside the window) are pruned on each check
54
+ * - The set cardinality gives the request count
55
+ *
56
+ * Blocks use simple key-value with TTL.
57
+ */
58
+ declare function createRedisRateLimitStore(redis: RedisRateLimitClient, options?: RedisRateLimitStoreOptions): RateLimitStore;
59
+
60
+ /**
61
+ * Next.js API Route Helpers
62
+ *
63
+ * Shared utilities for Next.js API routes that all apps need.
64
+ * These wrap platform-core's framework-agnostic primitives into
65
+ * Next.js-specific patterns (NextResponse, NextRequest).
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * import {
70
+ * enforceRateLimit,
71
+ * zodErrorResponse,
72
+ * errorResponse,
73
+ * extractBearerToken,
74
+ * isValidBearerToken,
75
+ * } from '@digilogiclabs/platform-core/auth'
76
+ *
77
+ * export async function POST(request: NextRequest) {
78
+ * const rl = await enforceRateLimit(request, 'submit', CommonRateLimits.publicForm)
79
+ * if (rl) return rl
80
+ *
81
+ * const parsed = schema.safeParse(await request.json())
82
+ * if (!parsed.success) return zodErrorResponse(parsed.error)
83
+ *
84
+ * try { ... }
85
+ * catch (error) { return errorResponse(error) }
86
+ * }
87
+ * ```
88
+ */
89
+
90
+ /**
91
+ * Enforce rate limiting on a Next.js API request.
92
+ *
93
+ * Returns a 429 NextResponse if the limit is exceeded, or `null` if allowed.
94
+ * Apps use this at the top of route handlers for early rejection.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const rateLimited = await enforceRateLimit(request, 'sync', CommonRateLimits.adminAction)
99
+ * if (rateLimited) return rateLimited
100
+ * ```
101
+ */
102
+ declare function enforceRateLimit(request: {
103
+ headers: {
104
+ get(name: string): string | null;
105
+ };
106
+ }, operation: string, rule: RateLimitRule, options?: {
107
+ /** Override identifier (default: extracted from x-forwarded-for) */
108
+ identifier?: string;
109
+ /** User ID for per-user limiting */
110
+ userId?: string;
111
+ /** Rate limit store and options */
112
+ rateLimitOptions?: RateLimitOptions;
113
+ }): Promise<Response | null>;
114
+ /**
115
+ * Convert any error into a structured JSON response.
116
+ *
117
+ * Uses platform-core's `classifyError()` to handle ApiError,
118
+ * Zod errors, PostgreSQL errors, and generic errors consistently.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * catch (error) {
123
+ * return errorResponse(error)
124
+ * }
125
+ * ```
126
+ */
127
+ declare function errorResponse(error: unknown, options?: {
128
+ isDevelopment?: boolean;
129
+ }): Response;
130
+ /**
131
+ * Convert a Zod validation error into a user-friendly 400 response.
132
+ *
133
+ * Extracts the first issue and returns a clear error message
134
+ * with the field path (e.g., "email: Invalid email").
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const parsed = schema.safeParse(await request.json())
139
+ * if (!parsed.success) return zodErrorResponse(parsed.error)
140
+ * ```
141
+ */
142
+ declare function zodErrorResponse(error: {
143
+ issues: Array<{
144
+ path: (string | number)[];
145
+ message: string;
146
+ }>;
147
+ }): Response;
148
+ /**
149
+ * Extract a bearer token from the Authorization header.
150
+ *
151
+ * @returns The token string, or null if not present/malformed.
152
+ */
153
+ declare function extractBearerToken(request: {
154
+ headers: {
155
+ get(name: string): string | null;
156
+ };
157
+ }): string | null;
158
+ /**
159
+ * Check if a request's bearer token matches a secret.
160
+ * Uses timing-safe comparison to prevent timing attacks.
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * if (!isValidBearerToken(request, process.env.ADMIN_SECRET)) {
165
+ * return new Response('Unauthorized', { status: 401 })
166
+ * }
167
+ * ```
168
+ */
169
+ declare function isValidBearerToken(request: {
170
+ headers: {
171
+ get(name: string): string | null;
172
+ };
173
+ }, secret: string | undefined): boolean;
174
+
175
+ export { RateLimitOptions, RateLimitRule, RateLimitStore, type RedisRateLimitClient, type RedisRateLimitStoreOptions, createRedisRateLimitStore, enforceRateLimit, errorResponse, extractBearerToken, isValidBearerToken, zodErrorResponse };