@spfn/core 0.2.0-beta.9 → 0.3.0-beta.10

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.
Files changed (119) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +693 -279
  3. package/dist/app-config/index.d.ts +96 -0
  4. package/dist/app-config/index.js +58 -0
  5. package/dist/app-config/index.js.map +1 -0
  6. package/dist/authz/index.d.ts +34 -0
  7. package/dist/authz/index.js +430 -0
  8. package/dist/authz/index.js.map +1 -0
  9. package/dist/boss-BiDCbbAQ.d.ts +337 -0
  10. package/dist/cache/index.js +42 -30
  11. package/dist/cache/index.js.map +1 -1
  12. package/dist/codegen/index.d.ts +121 -13
  13. package/dist/codegen/index.js +212 -15
  14. package/dist/codegen/index.js.map +1 -1
  15. package/dist/config/index.d.ts +576 -30
  16. package/dist/config/index.js +136 -17
  17. package/dist/config/index.js.map +1 -1
  18. package/dist/contract/index.d.ts +221 -0
  19. package/dist/contract/index.js +558 -0
  20. package/dist/contract/index.js.map +1 -0
  21. package/dist/db/index.d.ts +704 -94
  22. package/dist/db/index.js +1105 -260
  23. package/dist/db/index.js.map +1 -1
  24. package/dist/define-middleware-CVKgqo8S.d.ts +167 -0
  25. package/dist/env/index.d.ts +26 -2
  26. package/dist/env/index.js +15 -5
  27. package/dist/env/index.js.map +1 -1
  28. package/dist/env/loader.d.ts +26 -19
  29. package/dist/env/loader.js +55 -25
  30. package/dist/env/loader.js.map +1 -1
  31. package/dist/errors/index.d.ts +10 -0
  32. package/dist/errors/index.js +40 -7
  33. package/dist/errors/index.js.map +1 -1
  34. package/dist/event/index.d.ts +33 -3
  35. package/dist/event/index.js +24 -3
  36. package/dist/event/index.js.map +1 -1
  37. package/dist/event/sse/client.d.ts +55 -3
  38. package/dist/event/sse/client.js +164 -45
  39. package/dist/event/sse/client.js.map +1 -1
  40. package/dist/event/sse/index.d.ts +12 -5
  41. package/dist/event/sse/index.js +280 -32
  42. package/dist/event/sse/index.js.map +1 -1
  43. package/dist/event/ws/client.d.ts +59 -0
  44. package/dist/event/ws/client.js +273 -0
  45. package/dist/event/ws/client.js.map +1 -0
  46. package/dist/event/ws/index.d.ts +94 -0
  47. package/dist/event/ws/index.js +272 -0
  48. package/dist/event/ws/index.js.map +1 -0
  49. package/dist/job/index.d.ts +48 -3
  50. package/dist/job/index.js +265 -74
  51. package/dist/job/index.js.map +1 -1
  52. package/dist/logger/index.d.ts +5 -0
  53. package/dist/logger/index.js +14 -12
  54. package/dist/logger/index.js.map +1 -1
  55. package/dist/middleware/index.d.ts +352 -10
  56. package/dist/middleware/index.js +1079 -13
  57. package/dist/middleware/index.js.map +1 -1
  58. package/dist/nextjs/index.d.ts +39 -3
  59. package/dist/nextjs/index.js +82 -29
  60. package/dist/nextjs/index.js.map +1 -1
  61. package/dist/nextjs/server.d.ts +69 -52
  62. package/dist/nextjs/server.js +140 -60
  63. package/dist/nextjs/server.js.map +1 -1
  64. package/dist/ops/index.d.ts +208 -0
  65. package/dist/ops/index.js +800 -0
  66. package/dist/ops/index.js.map +1 -0
  67. package/dist/route/index.d.ts +10 -694
  68. package/dist/route/index.js +112 -23
  69. package/dist/route/index.js.map +1 -1
  70. package/dist/route-builder-2ani2jEI.d.ts +553 -0
  71. package/dist/router-DJdpwuB6.d.ts +127 -0
  72. package/dist/security/index.d.ts +83 -0
  73. package/dist/security/index.js +173 -0
  74. package/dist/security/index.js.map +1 -0
  75. package/dist/server/index.d.ts +619 -31
  76. package/dist/server/index.js +2583 -360
  77. package/dist/server/index.js.map +1 -1
  78. package/dist/token-manager-BT5EnUAR.d.ts +278 -0
  79. package/dist/types-2AbaW4Ie.d.ts +205 -0
  80. package/dist/{types-BOPTApC2.d.ts → types-9oszaJqp.d.ts} +7 -2
  81. package/dist/types-ClQVomgV.d.ts +115 -0
  82. package/dist/types-ZQODsBft.d.ts +282 -0
  83. package/docs/file-upload.md +195 -333
  84. package/package.json +250 -208
  85. package/src/cache/README.md +330 -0
  86. package/src/codegen/README.md +516 -0
  87. package/src/config/README.md +326 -0
  88. package/src/contract/README.md +326 -0
  89. package/src/db/README.md +589 -0
  90. package/src/db/manager/README.md +500 -0
  91. package/src/db/schema/README.md +354 -0
  92. package/src/db/transaction/README.md +822 -0
  93. package/src/env/README.md +651 -0
  94. package/src/errors/README.md +429 -0
  95. package/src/event/README.md +741 -0
  96. package/src/job/README.md +613 -0
  97. package/src/logger/README.md +321 -0
  98. package/src/middleware/README.md +634 -0
  99. package/src/nextjs/README.md +608 -0
  100. package/src/route/README.md +738 -0
  101. package/src/security/README.md +100 -0
  102. package/src/server/README.md +704 -0
  103. package/dist/boss-DI1r4kTS.d.ts +0 -244
  104. package/dist/router-Di7ENoah.d.ts +0 -151
  105. package/dist/types-B-e_f2dQ.d.ts +0 -121
  106. package/docs/cache.md +0 -133
  107. package/docs/codegen.md +0 -74
  108. package/docs/database.md +0 -346
  109. package/docs/entity.md +0 -539
  110. package/docs/env.md +0 -477
  111. package/docs/errors.md +0 -319
  112. package/docs/event.md +0 -116
  113. package/docs/job.md +0 -131
  114. package/docs/logger.md +0 -108
  115. package/docs/middleware.md +0 -337
  116. package/docs/nextjs.md +0 -241
  117. package/docs/repository.md +0 -496
  118. package/docs/route.md +0 -497
  119. package/docs/server.md +0 -307
@@ -1,10 +1,6 @@
1
- import { Context, Next } from 'hono';
2
-
3
- /**
4
- * Error Handler Middleware
5
- *
6
- * Handles SerializableError with automatic serialization and standard errors
7
- */
1
+ import { Context, Next, MiddlewareHandler } from 'hono';
2
+ import { N as NamedMiddlewareFactory, a as NamedMiddleware } from '../define-middleware-CVKgqo8S.js';
3
+ import { Redis, Cluster } from 'ioredis';
8
4
 
9
5
  /**
10
6
  * Options for ErrorHandler middleware
@@ -26,6 +22,43 @@ interface ErrorHandlerOptions {
26
22
  * @default true
27
23
  */
28
24
  enableLogging?: boolean;
25
+ /**
26
+ * Attach the `error` envelope to every error response
27
+ *
28
+ * The envelope is `{ code, message, requestId }` sitting next to the
29
+ * existing `__type` and `message` fields, never replacing them: a web
30
+ * client restores its error class from `__type` while a generated client
31
+ * in another language classifies by `code` alone and cannot read a
32
+ * discriminator it has no registry for.
33
+ *
34
+ * Turn it off only to keep error bodies byte-identical to an older
35
+ * release. A route reached by a generated client needs it.
36
+ *
37
+ * @default true
38
+ */
39
+ errorEnvelope?: boolean;
40
+ /**
41
+ * Callback invoked when an error occurs
42
+ *
43
+ * Called asynchronously without blocking the response.
44
+ * Useful for external error notifications (Slack, PagerDuty, etc.)
45
+ */
46
+ onError?: (err: Error, context: OnErrorContext) => Promise<void> | void;
47
+ }
48
+ /**
49
+ * Context passed to onError callback
50
+ */
51
+ interface OnErrorContext {
52
+ statusCode: number;
53
+ path: string;
54
+ method: string;
55
+ requestId?: string;
56
+ timestamp: string;
57
+ userId?: string;
58
+ request: {
59
+ headers: Record<string, string>;
60
+ query: Record<string, string>;
61
+ };
29
62
  }
30
63
  /**
31
64
  * Error handler middleware for Hono
@@ -34,6 +67,10 @@ interface ErrorHandlerOptions {
34
67
  * SerializableError instances are serialized using their toJSON() method,
35
68
  * preserving custom fields like `resource`, `fields`, etc.
36
69
  *
70
+ * Every response also carries an `error` envelope — `{ code, message,
71
+ * requestId }` — for clients that classify by a single documented field
72
+ * instead of restoring an error class from `__type`.
73
+ *
37
74
  * @param options - Configuration options
38
75
  * @returns Error handler function for Hono's onError hook
39
76
  *
@@ -53,7 +90,8 @@ interface ErrorHandlerOptions {
53
90
  * // Throw SerializableError in routes
54
91
  * app.get('/users/:id', (c) => {
55
92
  * throw new NotFoundError({ message: 'User not found', resource: 'User' });
56
- * // Response: { __type: 'NotFoundError', message: 'User not found', resource: 'User' }
93
+ * // Response: { __type: 'NotFoundError', message: 'User not found', resource: 'User',
94
+ * // error: { code: 'NotFoundError', message: 'User not found', requestId: '…' } }
57
95
  * });
58
96
  * ```
59
97
  */
@@ -68,7 +106,11 @@ interface RequestLoggerOptions {
68
106
  *
69
107
  * Supports exact match and prefix match (e.g., '/health' excludes '/health/db').
70
108
  *
71
- * @default ['/health', '/ping', '/favicon.ico']
109
+ * `/_core/health` is where the built-in health endpoint always answers, so a
110
+ * readiness probe usually points there rather than at `/health`. Leaving it
111
+ * out of the default fills the log with one line per probe interval.
112
+ *
113
+ * @default ['/_core/health', '/health', '/ping', '/favicon.ico']
72
114
  *
73
115
  * @example
74
116
  * ```typescript
@@ -139,4 +181,304 @@ declare function maskSensitiveData(obj: any, sensitiveFields: string[], seen?: W
139
181
  */
140
182
  declare function RequestLogger(options?: RequestLoggerOptions): (c: Context, next: Next) => Promise<void>;
141
183
 
142
- export { ErrorHandler, type ErrorHandlerOptions, RequestLogger, type RequestLoggerConfig, type RequestLoggerOptions, maskSensitiveData };
184
+ /**
185
+ * Proxy-guard middleware
186
+ *
187
+ * Verifies that an inbound request came through a trusted Next.js RPC proxy
188
+ * (HMAC signature) and/or from an allowed browser origin, then tags the request
189
+ * with a `clientType`. Lets the backend reject direct-to-backend calls that
190
+ * bypass the proxy.
191
+ *
192
+ * This does NOT replace user authentication (JWT) — it answers "what kind of
193
+ * client is this?", not "who is the user?". It also cannot stop a client from
194
+ * calling the proxy itself; that is the web's inherent limit (see
195
+ * PROXY-BACKEND-AUTH-SPEC.md). Mobile clients call the backend directly and are
196
+ * handled by a future attestation path, OR'd into this same check.
197
+ *
198
+ * @module middleware/proxy-guard
199
+ */
200
+
201
+ /**
202
+ * How the request reached the backend.
203
+ * - `web`: verified via a trusted proxy signature
204
+ * - `untrusted`: could not be verified (only reached handlers in `tag` mode)
205
+ * - future: `ios` | `android` once attestation lands
206
+ */
207
+ type ClientType = 'web' | 'untrusted' | (string & {});
208
+ /**
209
+ * Enforcement mode.
210
+ * - `off`: middleware is a no-op (default — keeps existing apps working).
211
+ * - `tag`: verify and set `clientType`, but never reject (observe first).
212
+ * - `strict`: reject requests that fail verification.
213
+ */
214
+ type ProxyGuardMode = 'off' | 'tag' | 'strict';
215
+ /**
216
+ * Optional replay store. Returns `true` when the nonce is fresh (and records it),
217
+ * `false` when it has been seen before. Backed by Redis in multi-instance setups.
218
+ */
219
+ interface NonceStore {
220
+ checkAndSet(nonce: string, ttlMs: number): Promise<boolean>;
221
+ }
222
+ interface ProxyGuardConfig {
223
+ /**
224
+ * Active shared HMAC secret, as `<keyId>:<secret>` (or a bare secret).
225
+ * Defaults to `env.SPFN_PROXY_SECRET`. Without it (and no previous keys),
226
+ * signatures cannot be verified and every request is tagged `untrusted`.
227
+ */
228
+ secret?: string;
229
+ /**
230
+ * Previous (grace) keys still accepted for verification during rotation, as a
231
+ * comma-separated list of `<keyId>:<secret>`. The proxy never signs with
232
+ * these — they exist only so in-flight requests signed with the prior key
233
+ * keep verifying until the rollout settles. Defaults to
234
+ * `env.SPFN_PROXY_SECRET_PREVIOUS`. Backend-only, so it can live in
235
+ * `.env.server` (never exposed to the Next.js process).
236
+ */
237
+ previousSecrets?: string;
238
+ /** Enforcement mode. @default 'off' */
239
+ mode?: ProxyGuardMode;
240
+ /** Allowed clock skew / replay window in ms. @default 30000 */
241
+ windowMs?: number;
242
+ /**
243
+ * Browser origin allowlist. When set, a request carrying an `Origin` header
244
+ * not in this list is rejected (strict) / tagged (tag). Requests without an
245
+ * `Origin` (server-to-server, mobile) skip this check and fall back to the
246
+ * signature.
247
+ */
248
+ allowedOrigins?: string[];
249
+ /** Optional nonce store for hard replay rejection. Redis (multi-instance) or in-memory (single). */
250
+ nonceStore?: NonceStore;
251
+ /**
252
+ * When the nonce store throws (e.g. Redis down), reject the request instead of
253
+ * falling back to the timestamp window. Trades availability for strictness.
254
+ * @default false (fall back to the timestamp window)
255
+ */
256
+ nonceFailClosed?: boolean;
257
+ /** Paths to skip entirely (e.g. health checks). */
258
+ skipPaths?: string[];
259
+ /**
260
+ * Reject (413) once the streamed body exceeds this many bytes. Measured AS IT
261
+ * STREAMS — Content-Length is NOT trusted, so a missing/chunked/under-reported
262
+ * length can't bypass it. Bounds the per-request memory the guard buffers.
263
+ * Undefined = no cap (default). Multipart is exempt (unsigned).
264
+ */
265
+ maxBodyBytes?: number;
266
+ }
267
+ declare module 'hono' {
268
+ interface ContextVariableMap {
269
+ clientType?: ClientType;
270
+ }
271
+ }
272
+ /**
273
+ * Create the proxy-guard middleware.
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * export default defineServerConfig()
278
+ * .proxyGuard({ mode: 'strict', allowedOrigins: ['https://app.example.com'] })
279
+ * .routes(appRouter)
280
+ * .build();
281
+ * ```
282
+ */
283
+ declare function createProxyGuard(config?: ProxyGuardConfig): MiddlewareHandler;
284
+ /** Minimal cache client (compatible with ioredis Redis | Cluster). */
285
+ type CacheClient = {
286
+ set(key: string, value: string, ...args: any[]): Promise<any>;
287
+ };
288
+ /**
289
+ * Build a Redis-backed nonce store for hard replay rejection.
290
+ *
291
+ * Uses `SET key 1 PX ttl NX` — an atomic "set if absent". A fresh nonce returns
292
+ * 'OK'; a replayed one returns null. TTL keeps the key set bounded (only nonces
293
+ * within the replay window matter).
294
+ */
295
+ declare function createCacheNonceStore(cache: CacheClient, prefix?: string): NonceStore;
296
+ /**
297
+ * In-process nonce store for hard replay rejection without Redis.
298
+ *
299
+ * Good enough for a single instance — each process only knows its own nonces, so
300
+ * across multiple instances a replay routed to a different pod isn't caught. Use a
301
+ * cache-backed store (createCacheNonceStore) for multi-instance hard rejection.
302
+ * Entries self-expire after their TTL; the map is swept opportunistically so it
303
+ * stays bounded by the request rate within the replay window.
304
+ */
305
+ declare function createInMemoryNonceStore(): NonceStore;
306
+
307
+ /** Test seam: forget every process-local window. */
308
+ declare function resetMemoryRateLimitStore(): void;
309
+ /**
310
+ * One identity dimension to limit on. A bare string uses the top-level `limit`;
311
+ * an object can carry its own `limit` so dimensions can differ (e.g. a loose
312
+ * per-IP cap alongside a tight per-account cap).
313
+ */
314
+ type RateLimitDimension = string | {
315
+ key: string;
316
+ limit?: number;
317
+ };
318
+ interface RateLimitOptions {
319
+ /** Max requests allowed per window, applied to each dimension without its own `limit`. */
320
+ limit: number;
321
+ /** Window length in milliseconds. */
322
+ windowMs: number;
323
+ /**
324
+ * Namespace for the counter keys. Defaults to `${method} ${routePath}` so
325
+ * each route is limited independently.
326
+ */
327
+ scope?: string;
328
+ /**
329
+ * Identity dimensions to limit on. Each non-empty value is counted
330
+ * separately and the strictest wins (e.g. by IP and by account). A dimension
331
+ * may override the top-level `limit` via `{ key, limit }`. Defaults to the
332
+ * client IP only.
333
+ */
334
+ by?: (c: Context) => (RateLimitDimension | null | undefined)[] | Promise<(RateLimitDimension | null | undefined)[]>;
335
+ /**
336
+ * Refuse with 429 when the shared cache is unavailable, instead of counting
337
+ * in this process. For a surface where a per-process count is not an
338
+ * acceptable substitute for a shared one.
339
+ */
340
+ failClosed?: boolean;
341
+ /** Message for the 429 response. */
342
+ message?: string;
343
+ }
344
+ /**
345
+ * Best-effort client IP for rate-limit keying.
346
+ *
347
+ * Prefers the proxy-forwarded real client IP, but ONLY when proxy-guard verified
348
+ * the request came through our proxy (`clientType` set and not 'untrusted') — on a
349
+ * verified request the proxy is the sole hop, so the value is the true client and
350
+ * isn't client-spoofable. Otherwise (no proxy-guard, or unverified/direct request)
351
+ * the forwarded header is attacker-settable, so fall back to the raw chain — whose
352
+ * leftmost hop is itself spoofable, so still pair with an account/target dimension
353
+ * for anything security-sensitive.
354
+ *
355
+ * Last resort before giving up is the TCP peer address from the Node adapter
356
+ * socket. Without it, a deployment that sets no forwarding header would collapse
357
+ * every client onto a single `'unknown'` bucket.
358
+ */
359
+ declare function getClientIp(c: Context): string;
360
+ /**
361
+ * Fixed-window rate limiter — counters in the shared cache when there is one,
362
+ * in this process otherwise.
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * route.post('/_auth/login')
367
+ * .use([rateLimit({ limit: 10, windowMs: 60_000 })])
368
+ * .handler(...);
369
+ * ```
370
+ */
371
+ declare const rateLimit: NamedMiddlewareFactory<"rateLimit", [options: RateLimitOptions]>;
372
+ /** Set the fail-closed default for named policies. Called by the server at boot. */
373
+ declare function setRateLimitFailClosedDefault(failClosed: boolean): void;
374
+ /**
375
+ * Replace the named-policy registry. Called by the server at boot; passing
376
+ * undefined clears it (so a restart without policies doesn't keep stale ones).
377
+ */
378
+ declare function setRateLimitPolicies(policies?: Record<string, RateLimitOptions>): void;
379
+ /** Look up a configured policy by name — undefined when the app didn't set it. */
380
+ declare function getRateLimitPolicy(name: string): RateLimitOptions | undefined;
381
+ /**
382
+ * Rate-limit a route under a named policy.
383
+ *
384
+ * A package author tags a sensitive route with a policy name plus a safe
385
+ * fallback; the consuming app tunes the numbers centrally via
386
+ * `defineServerConfig().rateLimit({ policies: { [name]: {...} } })`. When the
387
+ * app configures the policy, its fields override the fallback (shallow merge);
388
+ * otherwise the fallback applies, so the route is protected out of the box.
389
+ *
390
+ * LAYERS on top of the global default limiter rather than replacing it: the tag
391
+ * has a distinct name (`rateLimit:<name>`) and does not skip the global, so a
392
+ * route gets both the global per-IP floor (when enabled) and this policy's own
393
+ * bucket — whichever is stricter trips first. Opt out of the global floor on a
394
+ * route with `.skip(['rateLimit'])`.
395
+ *
396
+ * The counter scope defaults to the policy name, so (a) every route sharing a
397
+ * policy shares one bucket, and (b) the key never collides with the global
398
+ * default's per-route `${method} ${path}` scope.
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * route.post('/_auth/login')
403
+ * .use([rateLimitPolicy('auth-login', { limit: 5, windowMs: 60_000 })])
404
+ * .handler(...);
405
+ * ```
406
+ */
407
+ declare function rateLimitPolicy(name: string, fallback: RateLimitOptions): NamedMiddleware<string>;
408
+
409
+ /**
410
+ * The rate limiter's fixed-window counter as a pluggable store — the same
411
+ * pattern the clientProofV1 replay ledger and the SSE token manager already
412
+ * use: an in-memory default, a Redis/Valkey store on top of `getCache()`, and
413
+ * the cache's presence deciding which one a request gets.
414
+ *
415
+ * Why the memory default exists: without it, "no cache configured" and "cache
416
+ * down" both meant the limiter had nowhere to count, so the only choices were
417
+ * letting every request through or refusing every request. Neither is what a
418
+ * limiter is for. Counting in the process is worse than counting in Redis and
419
+ * far better than not counting.
420
+ *
421
+ * What the memory store cannot do is span processes. Behind N instances each
422
+ * keeps its own counters, so the effective limit is N times the configured one.
423
+ * That is the cost of the fallback and the reason a real deployment still
424
+ * points `CACHE_URL` at Redis.
425
+ *
426
+ * @module middleware/rate-limit-store
427
+ */
428
+
429
+ /** One window's state for a key: how many hits, and how long the window has left. */
430
+ interface RateLimitHit {
431
+ count: number;
432
+ /** Milliseconds until the window resets. */
433
+ pttl: number;
434
+ }
435
+ /** What the limiter needs from wherever the counters live. */
436
+ interface RateLimitStore {
437
+ /** Records one hit against `key` and answers the window's state after it. */
438
+ hit(key: string, windowMs: number): Promise<RateLimitHit>;
439
+ }
440
+ /**
441
+ * Counters in Redis — shared by every instance, so the configured limit is the
442
+ * limit no matter how many processes serve the traffic.
443
+ */
444
+ declare class CacheRateLimitStore implements RateLimitStore {
445
+ private readonly cache;
446
+ constructor(cache: Redis | Cluster);
447
+ hit(key: string, windowMs: number): Promise<RateLimitHit>;
448
+ }
449
+ /**
450
+ * Counters in this process.
451
+ *
452
+ * Entries are pruned lazily — a key past its window resets on its next hit, so
453
+ * the common path stays O(1). Keys nobody touches again would otherwise sit
454
+ * there forever, so a full sweep runs once the map crosses `maxKeys`; that
455
+ * bound is what keeps a limiter keyed by client IP from growing without end.
456
+ */
457
+ declare class MemoryRateLimitStore implements RateLimitStore {
458
+ private readonly maxKeys;
459
+ private readonly windows;
460
+ /** How many live windows were dropped to stay under `maxKeys`. */
461
+ private evicted;
462
+ constructor(maxKeys?: number);
463
+ hit(key: string, windowMs: number): Promise<RateLimitHit>;
464
+ /** Drops every window that has already reset. */
465
+ prune(nowMillis: number): void;
466
+ /**
467
+ * Frees a slot for a new key.
468
+ *
469
+ * Expired windows go first. If every window is still live the oldest one is
470
+ * dropped, because a hard bound is the only thing standing between a
471
+ * per-IP limiter and unbounded memory. A dropped window loses its count,
472
+ * so a caller who can mint `maxKeys` distinct identities can push another
473
+ * one out — which is why `evictionCount` is worth watching: it says this
474
+ * process is past what an in-memory limiter should be asked to hold, and
475
+ * the deployment wants a real cache.
476
+ */
477
+ private makeRoom;
478
+ get size(): number;
479
+ /** Live windows dropped for capacity — nonzero means the bound is binding. */
480
+ get evictionCount(): number;
481
+ clear(): void;
482
+ }
483
+
484
+ export { CacheRateLimitStore, type ClientType, ErrorHandler, type ErrorHandlerOptions, MemoryRateLimitStore, type NonceStore, type OnErrorContext, type ProxyGuardConfig, type ProxyGuardMode, type RateLimitDimension, type RateLimitHit, type RateLimitOptions, type RateLimitStore, RequestLogger, type RequestLoggerConfig, type RequestLoggerOptions, createCacheNonceStore, createInMemoryNonceStore, createProxyGuard, getClientIp, getRateLimitPolicy, maskSensitiveData, rateLimit, rateLimitPolicy, resetMemoryRateLimitStore, setRateLimitFailClosedDefault, setRateLimitPolicies };