@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 +174 -1
- package/dist/auth.d.ts +174 -1
- package/dist/auth.js +233 -3
- package/dist/auth.js.map +1 -1
- package/dist/auth.mjs +220 -2
- package/dist/auth.mjs.map +1 -1
- package/dist/{index-CkyVz0hQ.d.mts → env-jqNJdZVt.d.mts} +360 -2
- package/dist/{index-CkyVz0hQ.d.ts → env-jqNJdZVt.d.ts} +360 -2
- package/dist/{index-CepDdu7h.d.mts → index-DzQ0Js5Z.d.mts} +13 -1
- package/dist/{index-CepDdu7h.d.ts → index-DzQ0Js5Z.d.ts} +13 -1
- package/dist/index.d.mts +98 -3
- package/dist/index.d.ts +98 -3
- package/dist/index.js +969 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +955 -15
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.d.ts +1 -1
- package/dist/migrations/index.js +72 -1
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/index.mjs +72 -1
- package/dist/migrations/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/auth.d.mts
CHANGED
|
@@ -1,2 +1,175 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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 };
|