@scalemule/nextjs 0.0.1
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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/client.d.mts +163 -0
- package/dist/client.d.ts +163 -0
- package/dist/client.js +700 -0
- package/dist/client.mjs +697 -0
- package/dist/index-BkacIKdu.d.mts +807 -0
- package/dist/index-BkacIKdu.d.ts +807 -0
- package/dist/index.d.mts +418 -0
- package/dist/index.d.ts +418 -0
- package/dist/index.js +3103 -0
- package/dist/index.mjs +3084 -0
- package/dist/server/auth.d.mts +38 -0
- package/dist/server/auth.d.ts +38 -0
- package/dist/server/auth.js +1088 -0
- package/dist/server/auth.mjs +1083 -0
- package/dist/server/index.d.mts +868 -0
- package/dist/server/index.d.ts +868 -0
- package/dist/server/index.js +2028 -0
- package/dist/server/index.mjs +1972 -0
- package/dist/server/webhook-handler.d.mts +2 -0
- package/dist/server/webhook-handler.d.ts +2 -0
- package/dist/server/webhook-handler.js +56 -0
- package/dist/server/webhook-handler.mjs +54 -0
- package/dist/testing.d.mts +109 -0
- package/dist/testing.d.ts +109 -0
- package/dist/testing.js +134 -0
- package/dist/testing.mjs +128 -0
- package/dist/webhook-handler-BPNqhuwL.d.ts +728 -0
- package/dist/webhook-handler-C-5_Ey1T.d.mts +728 -0
- package/package.json +99 -0
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
import { S as ServerConfig } from '../webhook-handler-C-5_Ey1T.mjs';
|
|
2
|
+
export { a as ScaleMuleServer, d as VideoFailedEvent, V as VideoReadyEvent, f as VideoTranscodedEvent, e as VideoUploadedEvent, W as WebhookEvent, g as WebhookRoutesConfig, c as createServerClient, h as createWebhookHandler, b as createWebhookRoutes, p as parseWebhookEvent, r as registerVideoWebhook, v as verifyWebhookSignature } from '../webhook-handler-C-5_Ey1T.mjs';
|
|
3
|
+
import { _ as ClientContext, L as LoginResponse, A as ApiError } from '../index-BkacIKdu.mjs';
|
|
4
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Client Context Extraction Utilities (Next.js)
|
|
8
|
+
*
|
|
9
|
+
* Next.js-specific helpers for extracting end user context from incoming
|
|
10
|
+
* requests so it can be forwarded to ScaleMule when making server-to-server
|
|
11
|
+
* calls. This ensures ScaleMule captures the actual end user's information
|
|
12
|
+
* (IP, user agent, device fingerprint) instead of the server's information.
|
|
13
|
+
*
|
|
14
|
+
* For non-Next.js servers (Express, Fastify, raw Node.js), use the
|
|
15
|
+
* framework-agnostic `extractClientContext()` and `buildClientContextHeaders()`
|
|
16
|
+
* exported directly from `@scalemule/sdk`.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
interface NextRequestLike {
|
|
20
|
+
headers: {
|
|
21
|
+
get(name: string): string | null;
|
|
22
|
+
};
|
|
23
|
+
ip?: string;
|
|
24
|
+
}
|
|
25
|
+
interface IncomingMessageLike {
|
|
26
|
+
headers: Record<string, string | string[] | undefined>;
|
|
27
|
+
socket?: {
|
|
28
|
+
remoteAddress?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Extract client context from a Next.js App Router request.
|
|
33
|
+
*
|
|
34
|
+
* Use this in App Router API routes (route handlers) to capture
|
|
35
|
+
* the end user's information for forwarding to ScaleMule.
|
|
36
|
+
*
|
|
37
|
+
* Supports all major cloud providers and CDNs:
|
|
38
|
+
* - Cloudflare (CF-Connecting-IP)
|
|
39
|
+
* - DigitalOcean App Platform (DO-Connecting-IP)
|
|
40
|
+
* - Vercel (X-Vercel-Forwarded-For)
|
|
41
|
+
* - Akamai (True-Client-IP)
|
|
42
|
+
* - AWS/nginx (X-Real-IP, X-Forwarded-For)
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // app/api/upload/route.ts
|
|
47
|
+
* import { NextRequest, NextResponse } from 'next/server'
|
|
48
|
+
* import { extractClientContext, createServerClient } from '@scalemule/nextjs/server'
|
|
49
|
+
*
|
|
50
|
+
* export async function POST(request: NextRequest) {
|
|
51
|
+
* const clientContext = extractClientContext(request)
|
|
52
|
+
* const scalemule = createServerClient()
|
|
53
|
+
*
|
|
54
|
+
* const result = await scalemule.storage.upload(userId, file, {
|
|
55
|
+
* clientContext
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* return NextResponse.json(result)
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function extractClientContext(request: NextRequestLike): ClientContext;
|
|
63
|
+
/**
|
|
64
|
+
* Extract client context from a Pages Router API request.
|
|
65
|
+
*
|
|
66
|
+
* Use this in Pages Router API routes to capture the end user's
|
|
67
|
+
* information for forwarding to ScaleMule.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // pages/api/upload.ts
|
|
72
|
+
* import type { NextApiRequest, NextApiResponse } from 'next'
|
|
73
|
+
* import { extractClientContextFromReq, createServerClient } from '@scalemule/nextjs/server'
|
|
74
|
+
*
|
|
75
|
+
* export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
76
|
+
* const clientContext = extractClientContextFromReq(req)
|
|
77
|
+
* const scalemule = createServerClient()
|
|
78
|
+
*
|
|
79
|
+
* const result = await scalemule.storage.upload(userId, file, {
|
|
80
|
+
* clientContext
|
|
81
|
+
* })
|
|
82
|
+
*
|
|
83
|
+
* res.json(result)
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function extractClientContextFromReq(req: IncomingMessageLike): ClientContext;
|
|
88
|
+
/**
|
|
89
|
+
* Build headers to forward client context to ScaleMule.
|
|
90
|
+
*
|
|
91
|
+
* This is used internally by the SDK to add authenticated forwarded-IP headers
|
|
92
|
+
* (and legacy compatibility headers) when client context is provided.
|
|
93
|
+
*
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
declare function buildClientContextHeaders(context: ClientContext | undefined): Record<string, string>;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Cookie Utilities for Secure Session Management
|
|
100
|
+
*
|
|
101
|
+
* Handles HTTP-only secure cookies for authentication.
|
|
102
|
+
* Tokens are never exposed to the browser.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
declare const SESSION_COOKIE_NAME = "sm_session";
|
|
106
|
+
declare const USER_ID_COOKIE_NAME = "sm_user_id";
|
|
107
|
+
interface SessionCookieOptions {
|
|
108
|
+
/** Cookie max age in seconds (default: 7 days) */
|
|
109
|
+
maxAge?: number;
|
|
110
|
+
/** Cookie domain (default: current domain) */
|
|
111
|
+
domain?: string;
|
|
112
|
+
/** Cookie path (default: '/') */
|
|
113
|
+
path?: string;
|
|
114
|
+
/** SameSite attribute (default: 'lax') */
|
|
115
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
116
|
+
/** Whether to use secure cookies (default: true in production) */
|
|
117
|
+
secure?: boolean;
|
|
118
|
+
}
|
|
119
|
+
interface SessionData {
|
|
120
|
+
sessionToken: string;
|
|
121
|
+
userId: string;
|
|
122
|
+
expiresAt: Date;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Create a Response with session cookies set
|
|
126
|
+
*
|
|
127
|
+
* Use this after successful login to set HTTP-only cookies and return user data.
|
|
128
|
+
* The session token is stored in cookies, never sent to the browser in JSON.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const result = await sm.auth.login({ email, password })
|
|
133
|
+
* if (result.success) {
|
|
134
|
+
* return withSession(result.data, { user: result.data.user })
|
|
135
|
+
* }
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
declare function withSession<T extends Record<string, unknown>>(loginResponse: LoginResponse, responseBody: T, options?: SessionCookieOptions): Response;
|
|
139
|
+
/**
|
|
140
|
+
* Create a Response that clears session cookies
|
|
141
|
+
*
|
|
142
|
+
* Use this after logout to clear HTTP-only cookies.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* await sm.auth.logout(sessionToken)
|
|
147
|
+
* return clearSession({ message: 'Logged out' })
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
declare function clearSession<T extends Record<string, unknown>>(responseBody: T, options?: SessionCookieOptions, status?: number): Response;
|
|
151
|
+
/**
|
|
152
|
+
* Get session data from request cookies
|
|
153
|
+
*
|
|
154
|
+
* Use this in API routes to get the current session.
|
|
155
|
+
* Returns null if no valid session cookie exists.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* const session = await getSession()
|
|
160
|
+
* if (!session) {
|
|
161
|
+
* return Response.json({ error: 'Not authenticated' }, { status: 401 })
|
|
162
|
+
* }
|
|
163
|
+
* const user = await sm.auth.me(session.sessionToken)
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
declare function getSession(): Promise<SessionData | null>;
|
|
167
|
+
/**
|
|
168
|
+
* Get session from a Request object (for edge/middleware)
|
|
169
|
+
*
|
|
170
|
+
* Use this when you need to read cookies from a Request directly.
|
|
171
|
+
*/
|
|
172
|
+
declare function getSessionFromRequest(request: Request): SessionData | null;
|
|
173
|
+
/**
|
|
174
|
+
* Require authentication - throws Response if not authenticated
|
|
175
|
+
*
|
|
176
|
+
* Use this at the start of protected API routes.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* export async function GET() {
|
|
181
|
+
* const session = await requireSession()
|
|
182
|
+
* // session is guaranteed to exist here
|
|
183
|
+
* const files = await sm.storage.list(session.userId)
|
|
184
|
+
* }
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
declare function requireSession(): Promise<SessionData>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Ready-Made API Route Handlers
|
|
191
|
+
*
|
|
192
|
+
* Drop-in route handlers for Next.js App Router.
|
|
193
|
+
* Just import and re-export - no custom code needed.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* // app/api/auth/[...scalemule]/route.ts
|
|
198
|
+
* import { createAuthRoutes } from '@scalemule/nextjs/server'
|
|
199
|
+
*
|
|
200
|
+
* const handlers = createAuthRoutes()
|
|
201
|
+
* export const { GET, POST, DELETE } = handlers
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
interface AuthRoutesConfig {
|
|
206
|
+
/** Server client config (optional if using env vars) */
|
|
207
|
+
client?: Partial<ServerConfig>;
|
|
208
|
+
/** Cookie options */
|
|
209
|
+
cookies?: SessionCookieOptions;
|
|
210
|
+
/** Enable CSRF validation on state-changing requests (POST/DELETE/PATCH) */
|
|
211
|
+
csrf?: boolean;
|
|
212
|
+
/** Callbacks */
|
|
213
|
+
onLogin?: (user: {
|
|
214
|
+
id: string;
|
|
215
|
+
email: string;
|
|
216
|
+
}) => void | Promise<void>;
|
|
217
|
+
onLogout?: () => void | Promise<void>;
|
|
218
|
+
onRegister?: (user: {
|
|
219
|
+
id: string;
|
|
220
|
+
email: string;
|
|
221
|
+
}) => void | Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
type RouteHandler = (request: Request, context: {
|
|
224
|
+
params: Promise<{
|
|
225
|
+
scalemule?: string[];
|
|
226
|
+
}>;
|
|
227
|
+
}) => Promise<Response>;
|
|
228
|
+
/**
|
|
229
|
+
* Create authentication API route handlers
|
|
230
|
+
*
|
|
231
|
+
* Creates handlers for all auth operations that can be mounted at a catch-all route.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* // app/api/auth/[...scalemule]/route.ts
|
|
236
|
+
* import { createAuthRoutes } from '@scalemule/nextjs/server'
|
|
237
|
+
*
|
|
238
|
+
* const handlers = createAuthRoutes({
|
|
239
|
+
* cookies: { domain: '.yourdomain.com' },
|
|
240
|
+
* onLogin: (user) => console.log('User logged in:', user.email),
|
|
241
|
+
* })
|
|
242
|
+
*
|
|
243
|
+
* export const { GET, POST, DELETE } = handlers
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* This creates the following endpoints:
|
|
247
|
+
* - POST /api/auth/register - Register new user
|
|
248
|
+
* - POST /api/auth/login - Login
|
|
249
|
+
* - POST /api/auth/logout - Logout
|
|
250
|
+
* - GET /api/auth/me - Get current user
|
|
251
|
+
* - POST /api/auth/forgot-password - Request password reset
|
|
252
|
+
* - POST /api/auth/reset-password - Reset password with token
|
|
253
|
+
* - POST /api/auth/verify-email - Verify email
|
|
254
|
+
*/
|
|
255
|
+
declare function createAuthRoutes(config?: AuthRoutesConfig): {
|
|
256
|
+
GET: RouteHandler;
|
|
257
|
+
POST: RouteHandler;
|
|
258
|
+
DELETE: RouteHandler;
|
|
259
|
+
PATCH: RouteHandler;
|
|
260
|
+
};
|
|
261
|
+
interface AnalyticsRoutesConfig {
|
|
262
|
+
/** Server client config (optional if using env vars) */
|
|
263
|
+
client?: Partial<ServerConfig>;
|
|
264
|
+
/** Called after each event is tracked */
|
|
265
|
+
onEvent?: (event: {
|
|
266
|
+
event_name: string;
|
|
267
|
+
session_id?: string;
|
|
268
|
+
}) => void | Promise<void>;
|
|
269
|
+
/**
|
|
270
|
+
* When true, this is a simple proxy endpoint that handles events directly
|
|
271
|
+
* without path routing. Use for endpoints like /api/t/e.
|
|
272
|
+
* Default: false (uses catch-all route pattern)
|
|
273
|
+
*/
|
|
274
|
+
simpleProxy?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Create analytics API route handlers
|
|
278
|
+
*
|
|
279
|
+
* Creates handlers for analytics tracking that can be mounted at a route.
|
|
280
|
+
* AUTOMATICALLY extracts and forwards the real client IP to ScaleMule.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* // app/api/analytics/[...path]/route.ts (or /api/t/[...path]/route.ts to avoid ad-blockers)
|
|
285
|
+
* import { createAnalyticsRoutes } from '@scalemule/nextjs/server'
|
|
286
|
+
*
|
|
287
|
+
* const handlers = createAnalyticsRoutes()
|
|
288
|
+
* export const { POST } = handlers
|
|
289
|
+
* ```
|
|
290
|
+
*
|
|
291
|
+
* This creates the following endpoints:
|
|
292
|
+
* - POST /api/analytics/event - Track a single event
|
|
293
|
+
* - POST /api/analytics/events - Track a single event (alias)
|
|
294
|
+
* - POST /api/analytics/batch - Track multiple events
|
|
295
|
+
* - POST /api/analytics/page-view - Track a page view
|
|
296
|
+
*
|
|
297
|
+
* Client-side usage:
|
|
298
|
+
* ```ts
|
|
299
|
+
* // Track event
|
|
300
|
+
* fetch('/api/analytics/event', {
|
|
301
|
+
* method: 'POST',
|
|
302
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
303
|
+
* body: JSON.stringify({
|
|
304
|
+
* event_name: 'button_clicked',
|
|
305
|
+
* properties: { button_id: 'signup' }
|
|
306
|
+
* })
|
|
307
|
+
* })
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
declare function createAnalyticsRoutes(config?: AnalyticsRoutesConfig): {
|
|
311
|
+
POST: RouteHandler;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Error utilities for ScaleMule API route handlers.
|
|
316
|
+
*
|
|
317
|
+
* ScaleMuleError is a throwable error with HTTP status code.
|
|
318
|
+
* unwrap() converts SDK { data, error } results into throw-on-error.
|
|
319
|
+
* errorCodeToStatus() maps error codes to HTTP status codes.
|
|
320
|
+
*/
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Throwable error with HTTP status code and machine-readable error code.
|
|
324
|
+
*
|
|
325
|
+
* Throw this from apiHandler() callbacks to return a formatted error response.
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```ts
|
|
329
|
+
* throw new ScaleMuleError('NOT_FOUND', 'Snap not found', 404)
|
|
330
|
+
* throw new ScaleMuleError('FORBIDDEN', 'Not your snap', 403)
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
declare class ScaleMuleError extends Error {
|
|
334
|
+
readonly code: string;
|
|
335
|
+
readonly status: number;
|
|
336
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
337
|
+
constructor(code: string, message: string, status?: number, details?: Record<string, unknown> | undefined);
|
|
338
|
+
}
|
|
339
|
+
declare function errorCodeToStatus(code: string): number;
|
|
340
|
+
/**
|
|
341
|
+
* Result shape accepted by unwrap().
|
|
342
|
+
* Compatible with both the base SDK's { data, error } and the
|
|
343
|
+
* Next.js SDK's { success, data, error } response contracts.
|
|
344
|
+
*/
|
|
345
|
+
type SdkResult<T> = {
|
|
346
|
+
data?: T | null;
|
|
347
|
+
error?: ApiError | null;
|
|
348
|
+
success?: boolean;
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* Convert an SDK result into throw-on-error.
|
|
352
|
+
*
|
|
353
|
+
* If the result has an error (or success === false), throws a ScaleMuleError
|
|
354
|
+
* with the appropriate HTTP status code. Otherwise returns the data, typed
|
|
355
|
+
* and non-null.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* const user = unwrap(await sm.auth.me(token))
|
|
360
|
+
* const snaps = unwrap(await sm.data.query('snaps', { ... }))
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
declare function unwrap<T>(result: SdkResult<T>): T;
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* API Route Handler Wrapper
|
|
367
|
+
*
|
|
368
|
+
* Eliminates error handling boilerplate in Next.js API routes.
|
|
369
|
+
* Catches ScaleMuleError, thrown Response objects, and unexpected errors,
|
|
370
|
+
* returning properly formatted JSON responses.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```ts
|
|
374
|
+
* import { apiHandler, unwrap, ScaleMuleError } from '@scalemule/nextjs/server'
|
|
375
|
+
*
|
|
376
|
+
* export const POST = apiHandler(async (req, { params, searchParams }) => {
|
|
377
|
+
* const { phone } = await req.json()
|
|
378
|
+
* if (!phone) throw new ScaleMuleError('VALIDATION_ERROR', 'Phone required', 400)
|
|
379
|
+
*
|
|
380
|
+
* const data = unwrap(await sm.auth.sendPhoneOtp({ phone, purpose: 'verify_phone' }))
|
|
381
|
+
* return { message: 'OTP sent', expires_in_seconds: data.expires_in_seconds }
|
|
382
|
+
* }, { csrf: true })
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
|
+
type HandlerContext = {
|
|
387
|
+
/** Resolved route params (e.g., { id: '123' }) */
|
|
388
|
+
params: Record<string, string>;
|
|
389
|
+
/** URL search params */
|
|
390
|
+
searchParams: URLSearchParams;
|
|
391
|
+
/** Session data (only present when options.auth is true) */
|
|
392
|
+
session?: SessionData;
|
|
393
|
+
};
|
|
394
|
+
type HandlerFn = (request: NextRequest, context: HandlerContext) => Promise<Response | Record<string, unknown> | void>;
|
|
395
|
+
type HandlerOptions = {
|
|
396
|
+
/** Validate CSRF token before calling handler (default: false) */
|
|
397
|
+
csrf?: boolean;
|
|
398
|
+
/** Require authentication before calling handler (default: false) */
|
|
399
|
+
auth?: boolean;
|
|
400
|
+
/** Override default error response formatting */
|
|
401
|
+
onError?: (error: ScaleMuleError) => Response | undefined;
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* Wrap a Next.js API route handler with automatic error handling.
|
|
405
|
+
*
|
|
406
|
+
* - Catches `ScaleMuleError` (from `unwrap()` or manual throws) → JSON error response
|
|
407
|
+
* - Catches thrown `Response` objects (from `requireSession()`) → passes through
|
|
408
|
+
* - Catches unexpected errors → 500 JSON response
|
|
409
|
+
* - Optionally validates CSRF tokens and requires authentication
|
|
410
|
+
* - Auto-wraps returned objects in `{ success: true, data }` responses
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```ts
|
|
414
|
+
* // Simple route
|
|
415
|
+
* export const GET = apiHandler(async (req) => {
|
|
416
|
+
* const items = unwrap(await sm.data.query('items'))
|
|
417
|
+
* return { items }
|
|
418
|
+
* })
|
|
419
|
+
*
|
|
420
|
+
* // With CSRF + auth
|
|
421
|
+
* export const DELETE = apiHandler(async (req, { params, session }) => {
|
|
422
|
+
* const snap = unwrap(await sm.data.get('snaps', params.id))
|
|
423
|
+
* if (snap.userId !== session!.userId) throw new ScaleMuleError('FORBIDDEN', 'Not yours', 403)
|
|
424
|
+
* unwrap(await sm.data.delete('snaps', params.id))
|
|
425
|
+
* return { deleted: true }
|
|
426
|
+
* }, { csrf: true, auth: true })
|
|
427
|
+
* ```
|
|
428
|
+
*/
|
|
429
|
+
declare function apiHandler(handler: HandlerFn, options?: HandlerOptions): (request: NextRequest, routeContext?: {
|
|
430
|
+
params: Promise<Record<string, string | string[]>>;
|
|
431
|
+
}) => Promise<Response>;
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Next.js Middleware Helpers
|
|
435
|
+
*
|
|
436
|
+
* Use these in middleware.ts to protect routes server-side.
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```ts
|
|
440
|
+
* // middleware.ts
|
|
441
|
+
* import { createAuthMiddleware } from '@scalemule/nextjs/server'
|
|
442
|
+
*
|
|
443
|
+
* export default createAuthMiddleware({
|
|
444
|
+
* protectedRoutes: ['/dashboard', '/settings', '/api/user'],
|
|
445
|
+
* publicRoutes: ['/login', '/register', '/'],
|
|
446
|
+
* redirectTo: '/login',
|
|
447
|
+
* })
|
|
448
|
+
*
|
|
449
|
+
* export const config = {
|
|
450
|
+
* matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
|
|
451
|
+
* }
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
|
|
455
|
+
interface AuthMiddlewareConfig {
|
|
456
|
+
/** Routes that require authentication (supports glob patterns) */
|
|
457
|
+
protectedRoutes?: string[];
|
|
458
|
+
/** Routes that are always public (supports glob patterns) */
|
|
459
|
+
publicRoutes?: string[];
|
|
460
|
+
/** Where to redirect unauthenticated users (default: '/login') */
|
|
461
|
+
redirectTo?: string;
|
|
462
|
+
/** Where to redirect authenticated users from public-only routes */
|
|
463
|
+
redirectAuthenticated?: string;
|
|
464
|
+
/** Routes where authenticated users should be redirected (e.g., login page) */
|
|
465
|
+
authOnlyPublic?: string[];
|
|
466
|
+
/** Skip validation and just check cookie presence (faster) */
|
|
467
|
+
skipValidation?: boolean;
|
|
468
|
+
/** Custom handler for unauthorized requests */
|
|
469
|
+
onUnauthorized?: (request: NextRequest) => NextResponse;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Create authentication middleware for Next.js
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* // middleware.ts
|
|
477
|
+
* import { createAuthMiddleware } from '@scalemule/nextjs/server'
|
|
478
|
+
*
|
|
479
|
+
* export default createAuthMiddleware({
|
|
480
|
+
* protectedRoutes: ['/dashboard/*', '/api/user/*'],
|
|
481
|
+
* publicRoutes: ['/login', '/register', '/api/auth/*'],
|
|
482
|
+
* redirectTo: '/login',
|
|
483
|
+
* })
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
declare function createAuthMiddleware(config?: AuthMiddlewareConfig): (request: NextRequest) => Promise<NextResponse>;
|
|
487
|
+
/**
|
|
488
|
+
* Simple authentication check middleware (no validation, just cookie presence)
|
|
489
|
+
*
|
|
490
|
+
* Faster than createAuthMiddleware with full validation.
|
|
491
|
+
* Use when you want quick protection without hitting the backend.
|
|
492
|
+
*/
|
|
493
|
+
declare function withAuth(config?: Pick<AuthMiddlewareConfig, 'redirectTo' | 'onUnauthorized'>): (request: NextRequest) => NextResponse;
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* CSRF Protection Utilities
|
|
497
|
+
*
|
|
498
|
+
* Implements the double-submit cookie pattern for CSRF protection.
|
|
499
|
+
*
|
|
500
|
+
* Usage:
|
|
501
|
+
* 1. Generate token on page load and set cookie
|
|
502
|
+
* 2. Include token in request header or body
|
|
503
|
+
* 3. Validate token matches cookie on server
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```typescript
|
|
507
|
+
* // In your API route:
|
|
508
|
+
* import { validateCSRFToken, CSRF_HEADER_NAME } from '@scalemule/nextjs/server'
|
|
509
|
+
*
|
|
510
|
+
* export async function POST(request: NextRequest) {
|
|
511
|
+
* const error = validateCSRFToken(request)
|
|
512
|
+
* if (error) {
|
|
513
|
+
* return NextResponse.json({ error }, { status: 403 })
|
|
514
|
+
* }
|
|
515
|
+
* // ... handle request
|
|
516
|
+
* }
|
|
517
|
+
* ```
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
declare const CSRF_COOKIE_NAME = "sm_csrf";
|
|
521
|
+
declare const CSRF_HEADER_NAME = "x-csrf-token";
|
|
522
|
+
/**
|
|
523
|
+
* Generate a cryptographically secure CSRF token
|
|
524
|
+
*/
|
|
525
|
+
declare function generateCSRFToken(): string;
|
|
526
|
+
/**
|
|
527
|
+
* Create a response with CSRF token cookie set.
|
|
528
|
+
* Call this on page loads or when user logs in.
|
|
529
|
+
*/
|
|
530
|
+
declare function withCSRFToken(response: NextResponse, token?: string): NextResponse;
|
|
531
|
+
/**
|
|
532
|
+
* Validate CSRF token from request.
|
|
533
|
+
* Returns error message if invalid, undefined if valid.
|
|
534
|
+
*
|
|
535
|
+
* Checks that:
|
|
536
|
+
* 1. CSRF cookie exists
|
|
537
|
+
* 2. CSRF header or body field exists
|
|
538
|
+
* 3. Values match
|
|
539
|
+
*/
|
|
540
|
+
declare function validateCSRFToken(request: NextRequest): string | undefined;
|
|
541
|
+
/**
|
|
542
|
+
* Validate CSRF token (async version that can read from body)
|
|
543
|
+
*/
|
|
544
|
+
declare function validateCSRFTokenAsync(request: NextRequest, body?: Record<string, unknown>): Promise<string | undefined>;
|
|
545
|
+
/**
|
|
546
|
+
* Middleware helper to validate CSRF on all state-changing requests
|
|
547
|
+
*/
|
|
548
|
+
declare function withCSRFProtection(handler: (request: NextRequest) => Promise<NextResponse> | NextResponse): (request: NextRequest) => Promise<NextResponse>;
|
|
549
|
+
/**
|
|
550
|
+
* Get CSRF token for the current request (server component).
|
|
551
|
+
* Use this to pass the token to client components.
|
|
552
|
+
*/
|
|
553
|
+
declare function getCSRFToken(): Promise<string>;
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* OAuth State Management Utilities
|
|
557
|
+
*
|
|
558
|
+
* Provides secure OAuth state storage using httpOnly cookies instead of sessionStorage.
|
|
559
|
+
* This prevents XSS attacks from stealing OAuth state tokens.
|
|
560
|
+
*
|
|
561
|
+
* Usage:
|
|
562
|
+
* ```typescript
|
|
563
|
+
* // In your OAuth start route:
|
|
564
|
+
* import { setOAuthState } from '@scalemule/nextjs/server'
|
|
565
|
+
*
|
|
566
|
+
* export async function POST(request: NextRequest) {
|
|
567
|
+
* const result = await sm.auth.startOAuth({ provider: 'google', ... })
|
|
568
|
+
* return setOAuthState(NextResponse.json(result), result.state)
|
|
569
|
+
* }
|
|
570
|
+
*
|
|
571
|
+
* // In your OAuth callback route:
|
|
572
|
+
* import { validateOAuthState, clearOAuthState } from '@scalemule/nextjs/server'
|
|
573
|
+
*
|
|
574
|
+
* export async function GET(request: NextRequest) {
|
|
575
|
+
* const state = request.nextUrl.searchParams.get('state')
|
|
576
|
+
* const error = validateOAuthState(request, state)
|
|
577
|
+
* if (error) {
|
|
578
|
+
* return NextResponse.json({ error }, { status: 403 })
|
|
579
|
+
* }
|
|
580
|
+
* // ... complete OAuth flow
|
|
581
|
+
* return clearOAuthState(NextResponse.redirect('/dashboard'))
|
|
582
|
+
* }
|
|
583
|
+
* ```
|
|
584
|
+
*/
|
|
585
|
+
|
|
586
|
+
declare const OAUTH_STATE_COOKIE_NAME = "sm_oauth_state";
|
|
587
|
+
/**
|
|
588
|
+
* Set OAuth state in an httpOnly cookie.
|
|
589
|
+
* Call this when starting an OAuth flow.
|
|
590
|
+
*/
|
|
591
|
+
declare function setOAuthState(response: NextResponse, state: string): NextResponse;
|
|
592
|
+
/**
|
|
593
|
+
* Validate OAuth state from callback against stored cookie.
|
|
594
|
+
* Returns error message if invalid, undefined if valid.
|
|
595
|
+
*/
|
|
596
|
+
declare function validateOAuthState(request: NextRequest, callbackState: string | null): string | undefined;
|
|
597
|
+
/**
|
|
598
|
+
* Validate OAuth state (async version for Server Components).
|
|
599
|
+
*/
|
|
600
|
+
declare function validateOAuthStateAsync(callbackState: string | null): Promise<string | undefined>;
|
|
601
|
+
/**
|
|
602
|
+
* Clear OAuth state cookie after successful authentication.
|
|
603
|
+
*/
|
|
604
|
+
declare function clearOAuthState(response: NextResponse): NextResponse;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Application Secrets Management
|
|
608
|
+
*
|
|
609
|
+
* Provides cached access to tenant secrets stored in ScaleMule Vault.
|
|
610
|
+
* Use this instead of environment variables for sensitive configuration.
|
|
611
|
+
*
|
|
612
|
+
* Benefits:
|
|
613
|
+
* - Secrets stored securely with AES-256-GCM + AWS KMS encryption
|
|
614
|
+
* - Centralized management via ScaleMule admin dashboard
|
|
615
|
+
* - Automatic caching to minimize API calls
|
|
616
|
+
* - No need to manage k8s secrets yourself
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* ```typescript
|
|
620
|
+
* import { getAppSecret } from '@scalemule/nextjs/server'
|
|
621
|
+
*
|
|
622
|
+
* // In your API route or server component:
|
|
623
|
+
* const salt = await getAppSecret('ANONYMOUS_USER_SALT')
|
|
624
|
+
* // Uses cached value on subsequent calls
|
|
625
|
+
* ```
|
|
626
|
+
*/
|
|
627
|
+
/** Configuration options */
|
|
628
|
+
interface SecretsConfig {
|
|
629
|
+
/** Cache TTL in milliseconds (default: 5 minutes) */
|
|
630
|
+
cacheTtlMs?: number;
|
|
631
|
+
/** Disable caching (for testing) */
|
|
632
|
+
noCache?: boolean;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Configure secrets caching behavior
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```typescript
|
|
639
|
+
* configureSecrets({ cacheTtlMs: 60000 }) // 1 minute cache
|
|
640
|
+
* ```
|
|
641
|
+
*/
|
|
642
|
+
declare function configureSecrets(config: SecretsConfig): void;
|
|
643
|
+
/**
|
|
644
|
+
* Get a secret from the ScaleMule tenant vault
|
|
645
|
+
*
|
|
646
|
+
* This function automatically caches secrets to minimize API calls.
|
|
647
|
+
* If the secret doesn't exist, returns undefined.
|
|
648
|
+
*
|
|
649
|
+
* @param key - The secret key (e.g., 'ANONYMOUS_USER_SALT')
|
|
650
|
+
* @returns The secret value, or undefined if not found
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```typescript
|
|
654
|
+
* import { getAppSecret } from '@scalemule/nextjs/server'
|
|
655
|
+
*
|
|
656
|
+
* export async function POST(request: NextRequest) {
|
|
657
|
+
* const salt = await getAppSecret('ANONYMOUS_USER_SALT')
|
|
658
|
+
* if (!salt) {
|
|
659
|
+
* console.warn('ANONYMOUS_USER_SALT not configured in ScaleMule vault')
|
|
660
|
+
* // Fall back to environment variable or default
|
|
661
|
+
* salt = process.env.ANONYMOUS_USER_SALT || 'default-salt'
|
|
662
|
+
* }
|
|
663
|
+
* // Use the salt...
|
|
664
|
+
* }
|
|
665
|
+
* ```
|
|
666
|
+
*/
|
|
667
|
+
declare function getAppSecret(key: string): Promise<string | undefined>;
|
|
668
|
+
/**
|
|
669
|
+
* Get a secret, throwing if not found
|
|
670
|
+
*
|
|
671
|
+
* Use this when the secret is required and the app cannot function without it.
|
|
672
|
+
*
|
|
673
|
+
* @param key - The secret key
|
|
674
|
+
* @returns The secret value
|
|
675
|
+
* @throws Error if the secret is not found
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```typescript
|
|
679
|
+
* const salt = await requireAppSecret('ANONYMOUS_USER_SALT')
|
|
680
|
+
* // Throws if not configured
|
|
681
|
+
* ```
|
|
682
|
+
*/
|
|
683
|
+
declare function requireAppSecret(key: string): Promise<string>;
|
|
684
|
+
/**
|
|
685
|
+
* Get a secret with a fallback value
|
|
686
|
+
*
|
|
687
|
+
* Useful for development or when migrating from environment variables.
|
|
688
|
+
*
|
|
689
|
+
* @param key - The secret key
|
|
690
|
+
* @param fallback - Fallback value if secret not found
|
|
691
|
+
* @returns The secret value or fallback
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* ```typescript
|
|
695
|
+
* // Fall back to env var if not in vault yet
|
|
696
|
+
* const salt = await getAppSecretOrDefault(
|
|
697
|
+
* 'ANONYMOUS_USER_SALT',
|
|
698
|
+
* process.env.ANONYMOUS_USER_SALT || 'dev-salt'
|
|
699
|
+
* )
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
declare function getAppSecretOrDefault(key: string, fallback: string): Promise<string>;
|
|
703
|
+
/**
|
|
704
|
+
* Invalidate cached secret (force refresh on next access)
|
|
705
|
+
*
|
|
706
|
+
* @param key - The secret key to invalidate, or undefined to clear all
|
|
707
|
+
*/
|
|
708
|
+
declare function invalidateSecretCache(key?: string): void;
|
|
709
|
+
/**
|
|
710
|
+
* Prefetch secrets into cache
|
|
711
|
+
*
|
|
712
|
+
* Call this during app startup to warm the cache.
|
|
713
|
+
*
|
|
714
|
+
* @param keys - Array of secret keys to prefetch
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* ```typescript
|
|
718
|
+
* // In your app initialization:
|
|
719
|
+
* await prefetchSecrets(['ANONYMOUS_USER_SALT', 'WEBHOOK_SECRET'])
|
|
720
|
+
* ```
|
|
721
|
+
*/
|
|
722
|
+
declare function prefetchSecrets(keys: string[]): Promise<void>;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Application Bundles Management
|
|
726
|
+
*
|
|
727
|
+
* Bundles are structured secrets like database credentials, S3 configs, etc.
|
|
728
|
+
* They support inheritance - child bundles can inherit from parent bundles
|
|
729
|
+
* and override specific fields.
|
|
730
|
+
*
|
|
731
|
+
* @example
|
|
732
|
+
* ```typescript
|
|
733
|
+
* import { getBundle, getMySqlBundle } from '@scalemule/nextjs/server'
|
|
734
|
+
*
|
|
735
|
+
* // Get a generic bundle
|
|
736
|
+
* const config = await getBundle<{ apiKey: string }>('external/stripe')
|
|
737
|
+
*
|
|
738
|
+
* // Get a typed MySQL bundle
|
|
739
|
+
* const db = await getMySqlBundle('database/prod')
|
|
740
|
+
* const connection = mysql.createConnection(db.connectionUrl)
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
interface MySqlBundle {
|
|
744
|
+
host: string;
|
|
745
|
+
port: number;
|
|
746
|
+
username: string;
|
|
747
|
+
password: string;
|
|
748
|
+
database: string;
|
|
749
|
+
ssl_mode?: string;
|
|
750
|
+
}
|
|
751
|
+
interface PostgresBundle {
|
|
752
|
+
host: string;
|
|
753
|
+
port: number;
|
|
754
|
+
username: string;
|
|
755
|
+
password: string;
|
|
756
|
+
database: string;
|
|
757
|
+
ssl_mode?: string;
|
|
758
|
+
}
|
|
759
|
+
interface RedisBundle {
|
|
760
|
+
host: string;
|
|
761
|
+
port: number;
|
|
762
|
+
password?: string;
|
|
763
|
+
database?: number;
|
|
764
|
+
ssl?: boolean;
|
|
765
|
+
}
|
|
766
|
+
interface S3Bundle {
|
|
767
|
+
bucket: string;
|
|
768
|
+
region: string;
|
|
769
|
+
access_key_id: string;
|
|
770
|
+
secret_access_key: string;
|
|
771
|
+
endpoint?: string;
|
|
772
|
+
}
|
|
773
|
+
interface OAuthBundle {
|
|
774
|
+
client_id: string;
|
|
775
|
+
client_secret: string;
|
|
776
|
+
redirect_uri: string;
|
|
777
|
+
scopes?: string[];
|
|
778
|
+
}
|
|
779
|
+
interface SmtpBundle {
|
|
780
|
+
host: string;
|
|
781
|
+
port: number;
|
|
782
|
+
username: string;
|
|
783
|
+
password: string;
|
|
784
|
+
from_email: string;
|
|
785
|
+
from_name?: string;
|
|
786
|
+
encryption?: 'none' | 'tls' | 'starttls';
|
|
787
|
+
}
|
|
788
|
+
/** Configuration options */
|
|
789
|
+
interface BundlesConfig {
|
|
790
|
+
/** Cache TTL in milliseconds (default: 5 minutes) */
|
|
791
|
+
cacheTtlMs?: number;
|
|
792
|
+
/** Disable caching (for testing) */
|
|
793
|
+
noCache?: boolean;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Configure bundles caching behavior
|
|
797
|
+
*/
|
|
798
|
+
declare function configureBundles(config: BundlesConfig): void;
|
|
799
|
+
/**
|
|
800
|
+
* Get a bundle from the ScaleMule vault
|
|
801
|
+
*
|
|
802
|
+
* @param key - The bundle key (e.g., 'database/prod')
|
|
803
|
+
* @param resolve - Whether to resolve inheritance (default: true)
|
|
804
|
+
* @returns The bundle data, or undefined if not found
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```typescript
|
|
808
|
+
* const stripe = await getBundle<{ apiKey: string }>('external/stripe')
|
|
809
|
+
* if (stripe) {
|
|
810
|
+
* const client = new Stripe(stripe.apiKey)
|
|
811
|
+
* }
|
|
812
|
+
* ```
|
|
813
|
+
*/
|
|
814
|
+
declare function getBundle<T = Record<string, unknown>>(key: string, resolve?: boolean): Promise<T | undefined>;
|
|
815
|
+
/**
|
|
816
|
+
* Get a bundle, throwing if not found
|
|
817
|
+
*/
|
|
818
|
+
declare function requireBundle<T = Record<string, unknown>>(key: string, resolve?: boolean): Promise<T>;
|
|
819
|
+
/**
|
|
820
|
+
* Get a MySQL bundle with connection URL
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ```typescript
|
|
824
|
+
* const db = await getMySqlBundle('database/prod')
|
|
825
|
+
* const connection = mysql.createConnection(db.connectionUrl)
|
|
826
|
+
* ```
|
|
827
|
+
*/
|
|
828
|
+
declare function getMySqlBundle(key: string): Promise<(MySqlBundle & {
|
|
829
|
+
connectionUrl: string;
|
|
830
|
+
}) | undefined>;
|
|
831
|
+
/**
|
|
832
|
+
* Get a PostgreSQL bundle with connection URL
|
|
833
|
+
*/
|
|
834
|
+
declare function getPostgresBundle(key: string): Promise<(PostgresBundle & {
|
|
835
|
+
connectionUrl: string;
|
|
836
|
+
}) | undefined>;
|
|
837
|
+
/**
|
|
838
|
+
* Get a Redis bundle with connection URL
|
|
839
|
+
*/
|
|
840
|
+
declare function getRedisBundle(key: string): Promise<(RedisBundle & {
|
|
841
|
+
connectionUrl: string;
|
|
842
|
+
}) | undefined>;
|
|
843
|
+
/**
|
|
844
|
+
* Get an S3 bundle
|
|
845
|
+
*/
|
|
846
|
+
declare function getS3Bundle(key: string): Promise<S3Bundle | undefined>;
|
|
847
|
+
/**
|
|
848
|
+
* Get an OAuth bundle
|
|
849
|
+
*/
|
|
850
|
+
declare function getOAuthBundle(key: string): Promise<OAuthBundle | undefined>;
|
|
851
|
+
/**
|
|
852
|
+
* Get an SMTP bundle
|
|
853
|
+
*/
|
|
854
|
+
declare function getSmtpBundle(key: string): Promise<SmtpBundle | undefined>;
|
|
855
|
+
/**
|
|
856
|
+
* Invalidate cached bundle (force refresh on next access)
|
|
857
|
+
*
|
|
858
|
+
* @param key - The bundle key to invalidate, or undefined to clear all
|
|
859
|
+
*/
|
|
860
|
+
declare function invalidateBundleCache(key?: string): void;
|
|
861
|
+
/**
|
|
862
|
+
* Prefetch bundles into cache
|
|
863
|
+
*
|
|
864
|
+
* @param keys - Array of bundle keys to prefetch
|
|
865
|
+
*/
|
|
866
|
+
declare function prefetchBundles(keys: string[]): Promise<void>;
|
|
867
|
+
|
|
868
|
+
export { type AnalyticsRoutesConfig, type AuthMiddlewareConfig, type AuthRoutesConfig, CSRF_COOKIE_NAME, CSRF_HEADER_NAME, type HandlerContext, type HandlerOptions, type MySqlBundle, OAUTH_STATE_COOKIE_NAME, type OAuthBundle, type PostgresBundle, type RedisBundle, type S3Bundle, SESSION_COOKIE_NAME, ScaleMuleError, ServerConfig, type SessionCookieOptions, type SessionData, type SmtpBundle, USER_ID_COOKIE_NAME, apiHandler, buildClientContextHeaders, clearOAuthState, clearSession, configureBundles, configureSecrets, createAnalyticsRoutes, createAuthMiddleware, createAuthRoutes, errorCodeToStatus, extractClientContext, extractClientContextFromReq, generateCSRFToken, getAppSecret, getAppSecretOrDefault, getBundle, getCSRFToken, getMySqlBundle, getOAuthBundle, getPostgresBundle, getRedisBundle, getS3Bundle, getSession, getSessionFromRequest, getSmtpBundle, invalidateBundleCache, invalidateSecretCache, prefetchBundles, prefetchSecrets, requireAppSecret, requireBundle, requireSession, setOAuthState, unwrap, validateCSRFToken, validateCSRFTokenAsync, validateOAuthState, validateOAuthStateAsync, withAuth, withCSRFProtection, withCSRFToken, withSession };
|