@parsrun/server 0.1.27 → 0.1.29

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.
@@ -0,0 +1,744 @@
1
+ import { HonoContext, HonoNext, CorsConfig, ApiResponse } from './context.js';
2
+ import * as hono from 'hono';
3
+ import * as hono_utils_types from 'hono/utils/types';
4
+ import { ErrorTransport } from '@parsrun/core/transports';
5
+
6
+ /**
7
+ * @parsrun/server - Auth Middleware
8
+ * JWT authentication middleware
9
+ */
10
+
11
+ /**
12
+ * JWT payload structure
13
+ */
14
+ interface JwtPayload {
15
+ sub: string;
16
+ email?: string;
17
+ tenantId?: string;
18
+ role?: string;
19
+ permissions?: string[];
20
+ iat?: number;
21
+ exp?: number;
22
+ jti?: string;
23
+ }
24
+ /**
25
+ * JWT verification function type
26
+ */
27
+ type JwtVerifier = (token: string) => Promise<JwtPayload | null>;
28
+ /**
29
+ * Auth middleware options
30
+ */
31
+ interface AuthMiddlewareOptions {
32
+ /** JWT verification function */
33
+ verify: JwtVerifier;
34
+ /** Header name for token (default: Authorization) */
35
+ header?: string;
36
+ /** Token prefix (default: Bearer) */
37
+ prefix?: string;
38
+ /** Cookie name for token (alternative to header) */
39
+ cookie?: string;
40
+ /** Skip auth for certain requests */
41
+ skip?: (c: HonoContext) => boolean;
42
+ /** Custom error message */
43
+ message?: string;
44
+ }
45
+ /**
46
+ * Auth middleware - requires valid JWT
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { verifyJwt } from '@parsrun/auth';
51
+ *
52
+ * const authMiddleware = auth({
53
+ * verify: (token) => verifyJwt(token, secret),
54
+ * cookie: 'auth_token',
55
+ * });
56
+ *
57
+ * app.use('/api/*', authMiddleware);
58
+ *
59
+ * // Access user in handlers
60
+ * app.get('/api/me', (c) => {
61
+ * const user = c.get('user');
62
+ * return c.json({ user });
63
+ * });
64
+ * ```
65
+ */
66
+ declare function auth(options: AuthMiddlewareOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
67
+ /**
68
+ * Optional auth middleware - sets user if token present, but doesn't require it
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * app.use('/api/public/*', optionalAuth({
73
+ * verify: (token) => verifyJwt(token, secret),
74
+ * }));
75
+ *
76
+ * // User may or may not be present
77
+ * app.get('/api/public/items', (c) => {
78
+ * const user = c.get('user'); // may be undefined
79
+ * // Return different data based on auth status
80
+ * });
81
+ * ```
82
+ */
83
+ declare function optionalAuth(options: Omit<AuthMiddlewareOptions, "message">): (c: HonoContext, next: HonoNext) => Promise<void>;
84
+ /**
85
+ * Create auth middleware from verifier function
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const { auth, optionalAuth } = createAuthMiddleware({
90
+ * verify: async (token) => {
91
+ * return verifyJwt(token, process.env.JWT_SECRET);
92
+ * },
93
+ * cookie: 'session',
94
+ * });
95
+ *
96
+ * app.use('/api/*', auth);
97
+ * app.use('/public/*', optionalAuth);
98
+ * ```
99
+ */
100
+ declare function createAuthMiddleware(baseOptions: Omit<AuthMiddlewareOptions, "skip" | "message">): {
101
+ auth: (options?: Partial<AuthMiddlewareOptions>) => (c: HonoContext, next: HonoNext) => Promise<void>;
102
+ optionalAuth: (options?: Partial<Omit<AuthMiddlewareOptions, "message">>) => (c: HonoContext, next: HonoNext) => Promise<void>;
103
+ };
104
+
105
+ /**
106
+ * @parsrun/server - CORS Middleware
107
+ * Cross-Origin Resource Sharing configuration
108
+ */
109
+
110
+ /**
111
+ * CORS middleware
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * app.use('*', cors({
116
+ * origin: ['https://example.com', 'https://app.example.com'],
117
+ * credentials: true,
118
+ * }));
119
+ * ```
120
+ */
121
+ declare function cors(config?: Partial<CorsConfig>): (c: HonoContext, next: HonoNext) => Promise<Response | void>;
122
+
123
+ /**
124
+ * @parsrun/server - CSRF Middleware
125
+ * Cross-Site Request Forgery protection
126
+ */
127
+
128
+ /**
129
+ * CSRF options
130
+ */
131
+ interface CsrfOptions {
132
+ /** Cookie name for CSRF token */
133
+ cookieName?: string;
134
+ /** Header name for CSRF token */
135
+ headerName?: string;
136
+ /** Methods that require CSRF validation */
137
+ methods?: string[];
138
+ /** Paths to exclude from CSRF protection */
139
+ excludePaths?: string[];
140
+ /** Skip CSRF for certain requests */
141
+ skip?: (c: HonoContext) => boolean;
142
+ /** Token generator */
143
+ generateToken?: () => string;
144
+ /** Cookie options */
145
+ cookie?: {
146
+ secure?: boolean;
147
+ httpOnly?: boolean;
148
+ sameSite?: "strict" | "lax" | "none";
149
+ path?: string;
150
+ maxAge?: number;
151
+ };
152
+ }
153
+ /**
154
+ * CSRF protection middleware
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * app.use('*', csrf({
159
+ * cookieName: '_csrf',
160
+ * headerName: 'X-CSRF-Token',
161
+ * methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
162
+ * cookie: {
163
+ * secure: true,
164
+ * sameSite: 'strict',
165
+ * },
166
+ * }));
167
+ *
168
+ * // Get token in handler
169
+ * app.get('/csrf-token', (c) => {
170
+ * return c.json({ token: c.get('csrfToken') });
171
+ * });
172
+ * ```
173
+ */
174
+ declare function csrf(options?: CsrfOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
175
+ /**
176
+ * Double Submit Cookie pattern
177
+ * Generates a token and validates it matches between cookie and header
178
+ */
179
+ declare function doubleSubmitCookie(options?: CsrfOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
180
+
181
+ /**
182
+ * Base API error class
183
+ */
184
+ declare class ApiError extends Error {
185
+ readonly statusCode: number;
186
+ readonly code: string;
187
+ readonly details?: Record<string, unknown> | undefined;
188
+ constructor(statusCode: number, code: string, message: string, details?: Record<string, unknown> | undefined);
189
+ toResponse(): ApiResponse<never>;
190
+ }
191
+ /**
192
+ * 400 Bad Request
193
+ */
194
+ declare class BadRequestError extends ApiError {
195
+ constructor(message?: string, details?: Record<string, unknown>);
196
+ }
197
+ /**
198
+ * 401 Unauthorized
199
+ */
200
+ declare class UnauthorizedError extends ApiError {
201
+ constructor(message?: string, details?: Record<string, unknown>);
202
+ }
203
+ /**
204
+ * 403 Forbidden
205
+ */
206
+ declare class ForbiddenError extends ApiError {
207
+ constructor(message?: string, details?: Record<string, unknown>);
208
+ }
209
+ /**
210
+ * 404 Not Found
211
+ */
212
+ declare class NotFoundError extends ApiError {
213
+ constructor(message?: string, details?: Record<string, unknown>);
214
+ }
215
+ /**
216
+ * 409 Conflict
217
+ */
218
+ declare class ConflictError extends ApiError {
219
+ constructor(message?: string, details?: Record<string, unknown>);
220
+ }
221
+ /**
222
+ * 422 Unprocessable Entity (Validation Error)
223
+ */
224
+ declare class ValidationError extends ApiError {
225
+ constructor(message?: string, details?: Record<string, unknown>);
226
+ }
227
+ /**
228
+ * 429 Too Many Requests
229
+ */
230
+ declare class RateLimitError extends ApiError {
231
+ readonly retryAfter?: number | undefined;
232
+ constructor(message?: string, retryAfter?: number | undefined);
233
+ }
234
+ /**
235
+ * 500 Internal Server Error
236
+ */
237
+ declare class InternalError extends ApiError {
238
+ constructor(message?: string, details?: Record<string, unknown>);
239
+ }
240
+ /**
241
+ * 503 Service Unavailable
242
+ */
243
+ declare class ServiceUnavailableError extends ApiError {
244
+ constructor(message?: string, details?: Record<string, unknown>);
245
+ }
246
+ /**
247
+ * Error handler options
248
+ */
249
+ interface ErrorHandlerOptions {
250
+ /** Include stack trace in development */
251
+ includeStack?: boolean;
252
+ /** Custom error logger */
253
+ onError?: (error: Error, c: HonoContext) => void;
254
+ /**
255
+ * Error transport for external error tracking (e.g., Sentry)
256
+ * Automatically captures exceptions with request context
257
+ */
258
+ errorTransport?: ErrorTransport;
259
+ /**
260
+ * Capture all errors including 4xx client errors
261
+ * By default, only 5xx server errors are captured
262
+ * @default false
263
+ */
264
+ captureAllErrors?: boolean;
265
+ /**
266
+ * Custom function to determine if an error should be captured
267
+ * Overrides the default captureAllErrors behavior
268
+ */
269
+ shouldCapture?: (error: Error, statusCode: number) => boolean;
270
+ }
271
+ /**
272
+ * Global error handler middleware
273
+ *
274
+ * @example Basic usage
275
+ * ```typescript
276
+ * app.use('*', errorHandler({
277
+ * includeStack: process.env.NODE_ENV === 'development',
278
+ * onError: (error, c) => {
279
+ * console.error(`[${c.get('requestId')}]`, error);
280
+ * },
281
+ * }));
282
+ * ```
283
+ *
284
+ * @example With Sentry error tracking
285
+ * ```typescript
286
+ * import { SentryTransport } from '@parsrun/core/transports';
287
+ *
288
+ * const sentry = new SentryTransport({
289
+ * dsn: process.env.SENTRY_DSN!,
290
+ * environment: process.env.NODE_ENV,
291
+ * });
292
+ *
293
+ * app.use('*', errorHandler({
294
+ * errorTransport: sentry,
295
+ * captureAllErrors: false, // Only capture 5xx errors
296
+ * }));
297
+ * ```
298
+ */
299
+ declare function errorHandler(options?: ErrorHandlerOptions): (c: HonoContext, next: HonoNext) => Promise<(Response & hono.TypedResponse<{
300
+ success: boolean;
301
+ error?: {
302
+ code: string;
303
+ message: string;
304
+ details?: {
305
+ [x: string]: hono_utils_types.JSONValue;
306
+ } | undefined;
307
+ } | undefined;
308
+ meta?: {
309
+ page?: number | undefined | undefined;
310
+ limit?: number | undefined | undefined;
311
+ total?: number | undefined | undefined;
312
+ requestId?: string | undefined | undefined;
313
+ } | undefined;
314
+ }, 400, "json">) | (Response & hono.TypedResponse<{
315
+ success: boolean;
316
+ error?: {
317
+ code: string;
318
+ message: string;
319
+ details?: {
320
+ [x: string]: hono_utils_types.JSONValue;
321
+ } | undefined;
322
+ } | undefined;
323
+ meta?: {
324
+ page?: number | undefined | undefined;
325
+ limit?: number | undefined | undefined;
326
+ total?: number | undefined | undefined;
327
+ requestId?: string | undefined | undefined;
328
+ } | undefined;
329
+ }, 500, "json">) | undefined>;
330
+ /**
331
+ * Not found handler
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * app.notFound(notFoundHandler);
336
+ * ```
337
+ */
338
+ declare function notFoundHandler(c: HonoContext): Response & hono.TypedResponse<{
339
+ success: boolean;
340
+ error?: {
341
+ code: string;
342
+ message: string;
343
+ details?: {
344
+ [x: string]: hono_utils_types.JSONValue;
345
+ } | undefined;
346
+ } | undefined;
347
+ meta?: {
348
+ page?: number | undefined | undefined;
349
+ limit?: number | undefined | undefined;
350
+ total?: number | undefined | undefined;
351
+ requestId?: string | undefined | undefined;
352
+ } | undefined;
353
+ }, 404, "json">;
354
+
355
+ /**
356
+ * @parsrun/server - Rate Limit Middleware
357
+ * Request throttling with multiple storage backends
358
+ */
359
+
360
+ /**
361
+ * Rate limit storage interface
362
+ */
363
+ interface RateLimitStorage {
364
+ /** Get current count for key */
365
+ get(key: string): Promise<number>;
366
+ /** Increment count and set expiry */
367
+ increment(key: string, windowMs: number): Promise<number>;
368
+ /** Reset count for key */
369
+ reset(key: string): Promise<void>;
370
+ }
371
+ /**
372
+ * In-memory rate limit storage
373
+ * For single-instance deployments or development
374
+ */
375
+ declare class MemoryRateLimitStorage implements RateLimitStorage {
376
+ private store;
377
+ get(key: string): Promise<number>;
378
+ increment(key: string, windowMs: number): Promise<number>;
379
+ reset(key: string): Promise<void>;
380
+ /** Clean up expired entries */
381
+ cleanup(): void;
382
+ }
383
+ /**
384
+ * Rate limit options
385
+ */
386
+ interface RateLimitOptions {
387
+ /** Time window in milliseconds */
388
+ windowMs?: number;
389
+ /** Maximum requests per window */
390
+ max?: number;
391
+ /** Generate key from request (default: IP address) */
392
+ keyGenerator?: (c: HonoContext) => string;
393
+ /** Skip rate limiting for certain requests */
394
+ skip?: (c: HonoContext) => boolean;
395
+ /** Custom storage backend */
396
+ storage?: RateLimitStorage;
397
+ /** Error message */
398
+ message?: string;
399
+ /** Include rate limit headers */
400
+ headers?: boolean;
401
+ /** Handler when limit is exceeded */
402
+ onLimitReached?: (c: HonoContext, key: string) => void;
403
+ }
404
+ /**
405
+ * Rate limit middleware
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * // Basic usage - 100 requests per minute
410
+ * app.use('/api/*', rateLimit({
411
+ * windowMs: 60 * 1000,
412
+ * max: 100,
413
+ * }));
414
+ *
415
+ * // Per-user rate limiting
416
+ * app.use('/api/*', rateLimit({
417
+ * keyGenerator: (c) => c.get('user')?.id ?? getIP(c),
418
+ * max: 1000,
419
+ * }));
420
+ *
421
+ * // Strict limit for auth endpoints
422
+ * app.use('/api/auth/*', rateLimit({
423
+ * windowMs: 15 * 60 * 1000, // 15 minutes
424
+ * max: 5,
425
+ * message: 'Too many login attempts',
426
+ * }));
427
+ * ```
428
+ */
429
+ declare function rateLimit(options?: RateLimitOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
430
+ /**
431
+ * Create rate limiter for specific routes
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * const apiLimiter = createRateLimiter({
436
+ * windowMs: 60000,
437
+ * max: 100,
438
+ * });
439
+ *
440
+ * app.use('/api/*', apiLimiter.middleware);
441
+ *
442
+ * // Reset limit for a user after successful auth
443
+ * await apiLimiter.reset('user:123');
444
+ * ```
445
+ */
446
+ declare function createRateLimiter(options?: RateLimitOptions): {
447
+ middleware: (c: HonoContext, next: HonoNext) => Promise<void>;
448
+ storage: RateLimitStorage;
449
+ reset: (key: string) => Promise<void>;
450
+ get: (key: string) => Promise<number>;
451
+ };
452
+
453
+ /**
454
+ * @parsrun/server - Request Logger Middleware
455
+ * HTTP request/response logging
456
+ */
457
+
458
+ /**
459
+ * Request logger options
460
+ */
461
+ interface RequestLoggerOptions {
462
+ /** Skip logging for certain paths */
463
+ skip?: (c: HonoContext) => boolean;
464
+ /** Custom log format */
465
+ format?: "json" | "combined" | "short";
466
+ /** Include request body in logs */
467
+ includeBody?: boolean;
468
+ /** Include response body in logs (be careful with large responses) */
469
+ includeResponseBody?: boolean;
470
+ /** Maximum body length to log */
471
+ maxBodyLength?: number;
472
+ }
473
+ /**
474
+ * Request logger middleware
475
+ *
476
+ * @example
477
+ * ```typescript
478
+ * app.use('*', requestLogger({
479
+ * skip: (c) => c.req.path === '/health',
480
+ * format: 'json',
481
+ * }));
482
+ * ```
483
+ */
484
+ declare function requestLogger(options?: RequestLoggerOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
485
+
486
+ /**
487
+ * @parsrun/server - Usage Tracking Middleware
488
+ * Automatically track API usage per request
489
+ */
490
+
491
+ /**
492
+ * Usage service interface (from @parsrun/payments)
493
+ * Defined here to avoid circular dependency
494
+ */
495
+ interface UsageServiceLike {
496
+ trackUsage(options: {
497
+ tenantId: string;
498
+ customerId: string;
499
+ subscriptionId?: string;
500
+ featureKey: string;
501
+ quantity?: number;
502
+ metadata?: Record<string, unknown>;
503
+ idempotencyKey?: string;
504
+ }): Promise<unknown>;
505
+ }
506
+ /**
507
+ * Usage tracking middleware options
508
+ */
509
+ interface UsageTrackingOptions {
510
+ /**
511
+ * Usage service instance
512
+ */
513
+ usageService: UsageServiceLike;
514
+ /**
515
+ * Feature key to track
516
+ * Can be a static string or a function that extracts it from context
517
+ * @default "api_calls"
518
+ */
519
+ featureKey?: string | ((c: HonoContext) => string);
520
+ /**
521
+ * Quantity to track
522
+ * Can be a static number or a function that calculates it from context
523
+ * @default 1
524
+ */
525
+ quantity?: number | ((c: HonoContext) => number);
526
+ /**
527
+ * Skip tracking for certain requests
528
+ */
529
+ skip?: (c: HonoContext) => boolean;
530
+ /**
531
+ * When to track: before or after the request
532
+ * @default "response"
533
+ */
534
+ trackOn?: "request" | "response";
535
+ /**
536
+ * Only track successful responses (2xx)
537
+ * @default true
538
+ */
539
+ successOnly?: boolean;
540
+ /**
541
+ * Custom customer ID extractor
542
+ * @default Uses c.get("user")?.id
543
+ */
544
+ getCustomerId?: (c: HonoContext) => string | undefined;
545
+ /**
546
+ * Custom tenant ID extractor
547
+ * @default Uses c.get("tenant")?.id or c.get("user")?.tenantId
548
+ */
549
+ getTenantId?: (c: HonoContext) => string | undefined;
550
+ /**
551
+ * Custom subscription ID extractor
552
+ */
553
+ getSubscriptionId?: (c: HonoContext) => string | undefined;
554
+ /**
555
+ * Include request metadata
556
+ * @default true
557
+ */
558
+ includeMetadata?: boolean;
559
+ /**
560
+ * Generate idempotency key to prevent duplicates
561
+ */
562
+ getIdempotencyKey?: (c: HonoContext) => string | undefined;
563
+ }
564
+ /**
565
+ * Usage tracking middleware
566
+ *
567
+ * Automatically tracks API usage for authenticated requests.
568
+ *
569
+ * @example
570
+ * ```typescript
571
+ * import { usageTracking } from "@parsrun/server";
572
+ * import { createUsageService, createMemoryUsageStorage } from "@parsrun/payments";
573
+ *
574
+ * const usageService = createUsageService({
575
+ * storage: createMemoryUsageStorage(),
576
+ * });
577
+ *
578
+ * // Track all API calls
579
+ * app.use("/api/*", usageTracking({
580
+ * usageService,
581
+ * featureKey: "api_calls",
582
+ * }));
583
+ *
584
+ * // Track with custom feature key based on route
585
+ * app.use("/api/ai/*", usageTracking({
586
+ * usageService,
587
+ * featureKey: "ai_requests",
588
+ * quantity: (c) => {
589
+ * // Track tokens used from response
590
+ * return c.get("tokensUsed") ?? 1;
591
+ * },
592
+ * }));
593
+ *
594
+ * // Skip certain routes
595
+ * app.use("/api/*", usageTracking({
596
+ * usageService,
597
+ * skip: (c) => c.req.path.startsWith("/api/health"),
598
+ * }));
599
+ * ```
600
+ */
601
+ declare function usageTracking(options: UsageTrackingOptions): (c: HonoContext, next: HonoNext) => Promise<void>;
602
+ /**
603
+ * Create usage tracking middleware with pre-configured options
604
+ */
605
+ declare function createUsageTracking(baseOptions: UsageTrackingOptions): (overrides?: Partial<UsageTrackingOptions>) => (c: HonoContext, next: HonoNext) => Promise<void>;
606
+
607
+ /**
608
+ * @parsrun/server - Quota Enforcement Middleware
609
+ * Enforce usage quotas before processing requests
610
+ */
611
+
612
+ /**
613
+ * Quota check result interface (from @parsrun/payments)
614
+ */
615
+ interface QuotaCheckResult {
616
+ allowed: boolean;
617
+ currentUsage: number;
618
+ limit: number | null;
619
+ remaining: number | null;
620
+ wouldExceed: boolean;
621
+ percentAfter: number | null;
622
+ }
623
+ /**
624
+ * Quota manager interface (from @parsrun/payments)
625
+ * Defined here to avoid circular dependency
626
+ */
627
+ interface QuotaManagerLike {
628
+ checkQuota(customerId: string, featureKey: string, quantity?: number): Promise<QuotaCheckResult>;
629
+ enforceQuota(customerId: string, featureKey: string, quantity?: number): Promise<void>;
630
+ }
631
+ /**
632
+ * Quota exceeded error class
633
+ */
634
+ declare class QuotaExceededError extends Error {
635
+ readonly featureKey: string;
636
+ readonly limit: number | null;
637
+ readonly currentUsage: number;
638
+ readonly requestedQuantity: number;
639
+ readonly statusCode = 429;
640
+ readonly code = "QUOTA_EXCEEDED";
641
+ constructor(featureKey: string, limit: number | null, currentUsage: number, requestedQuantity?: number);
642
+ }
643
+ /**
644
+ * Quota enforcement middleware options
645
+ */
646
+ interface QuotaEnforcementOptions {
647
+ /**
648
+ * Quota manager instance
649
+ */
650
+ quotaManager: QuotaManagerLike;
651
+ /**
652
+ * Feature key to check
653
+ * Can be a static string or a function that extracts it from context
654
+ */
655
+ featureKey: string | ((c: HonoContext) => string);
656
+ /**
657
+ * Quantity to check (default: 1)
658
+ */
659
+ quantity?: number | ((c: HonoContext) => number);
660
+ /**
661
+ * Skip quota check for certain requests
662
+ */
663
+ skip?: (c: HonoContext) => boolean;
664
+ /**
665
+ * Custom customer ID extractor
666
+ * @default Uses c.get("user")?.id
667
+ */
668
+ getCustomerId?: (c: HonoContext) => string | undefined;
669
+ /**
670
+ * Include quota headers in response
671
+ * @default true
672
+ */
673
+ includeHeaders?: boolean;
674
+ /**
675
+ * Custom error handler
676
+ */
677
+ onQuotaExceeded?: (c: HonoContext, result: QuotaCheckResult, featureKey: string) => Response | void;
678
+ /**
679
+ * Soft limit mode - warn but don't block
680
+ * @default false
681
+ */
682
+ softLimit?: boolean;
683
+ /**
684
+ * Callback when quota is close to limit (>80%)
685
+ */
686
+ onQuotaWarning?: (c: HonoContext, result: QuotaCheckResult, featureKey: string) => void;
687
+ }
688
+ /**
689
+ * Quota enforcement middleware
690
+ *
691
+ * Checks and enforces usage quotas before processing requests.
692
+ *
693
+ * @example
694
+ * ```typescript
695
+ * import { quotaEnforcement } from "@parsrun/server";
696
+ * import { createQuotaManager, createMemoryUsageStorage } from "@parsrun/payments";
697
+ *
698
+ * const quotaManager = createQuotaManager({
699
+ * storage: createMemoryUsageStorage(),
700
+ * });
701
+ *
702
+ * // Enforce API call quota
703
+ * app.use("/api/*", quotaEnforcement({
704
+ * quotaManager,
705
+ * featureKey: "api_calls",
706
+ * }));
707
+ *
708
+ * // Enforce with dynamic feature key
709
+ * app.use("/api/*", quotaEnforcement({
710
+ * quotaManager,
711
+ * featureKey: (c) => {
712
+ * if (c.req.path.startsWith("/api/ai")) return "ai_requests";
713
+ * return "api_calls";
714
+ * },
715
+ * }));
716
+ *
717
+ * // Soft limit mode (warn but allow)
718
+ * app.use("/api/*", quotaEnforcement({
719
+ * quotaManager,
720
+ * featureKey: "api_calls",
721
+ * softLimit: true,
722
+ * onQuotaWarning: (c, result) => {
723
+ * console.warn("Quota warning:", result);
724
+ * },
725
+ * }));
726
+ * ```
727
+ */
728
+ declare function quotaEnforcement(options: QuotaEnforcementOptions): (c: HonoContext, next: HonoNext) => Promise<void | Response>;
729
+ /**
730
+ * Create quota enforcement middleware with pre-configured options
731
+ */
732
+ declare function createQuotaEnforcement(baseOptions: Omit<QuotaEnforcementOptions, "featureKey">): (featureKey: string | ((c: HonoContext) => string)) => (c: HonoContext, next: HonoNext) => Promise<void | Response>;
733
+ /**
734
+ * Multiple quota enforcement
735
+ * Check multiple features at once
736
+ */
737
+ declare function multiQuotaEnforcement(options: Omit<QuotaEnforcementOptions, "featureKey"> & {
738
+ features: Array<{
739
+ featureKey: string;
740
+ quantity?: number | ((c: HonoContext) => number);
741
+ }>;
742
+ }): (c: HonoContext, next: HonoNext) => Promise<void | Response>;
743
+
744
+ export { type AuthMiddlewareOptions as A, BadRequestError as B, type CsrfOptions as C, type QuotaCheckResult as D, type ErrorHandlerOptions as E, ForbiddenError as F, InternalError as I, type JwtPayload as J, MemoryRateLimitStorage as M, NotFoundError as N, QuotaExceededError as Q, RateLimitError as R, ServiceUnavailableError as S, UnauthorizedError as U, ValidationError as V, auth as a, type JwtVerifier as b, createAuthMiddleware as c, cors as d, csrf as e, doubleSubmitCookie as f, errorHandler as g, ApiError as h, ConflictError as i, createRateLimiter as j, type RateLimitOptions as k, type RateLimitStorage as l, requestLogger as m, notFoundHandler as n, optionalAuth as o, type RequestLoggerOptions as p, createUsageTracking as q, rateLimit as r, type UsageTrackingOptions as s, type UsageServiceLike as t, usageTracking as u, quotaEnforcement as v, createQuotaEnforcement as w, multiQuotaEnforcement as x, type QuotaEnforcementOptions as y, type QuotaManagerLike as z };