@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.
@@ -0,0 +1,728 @@
1
+ import { R as RegisterRequest, j as ApiResponse, U as User, k as LoginRequest, L as LoginResponse, c as ListFilesParams, Q as ListFilesResponse, K as StorageFile, _ as ClientContext, T as UploadResponse } from './index-BkacIKdu.mjs';
2
+
3
+ /**
4
+ * Server-Side ScaleMule Client
5
+ *
6
+ * Stateless client for use in Next.js API routes.
7
+ * Does not manage sessions - that's handled by cookies.
8
+ */
9
+
10
+ type ScaleMuleEnvironment = 'dev' | 'prod';
11
+ interface ServerConfig {
12
+ /** Your ScaleMule API key (use env var, never hardcode) */
13
+ apiKey: string;
14
+ /** Environment: 'dev' or 'prod' - automatically sets gateway URL */
15
+ environment?: ScaleMuleEnvironment;
16
+ /** Custom gateway URL (overrides environment preset) */
17
+ gatewayUrl?: string;
18
+ /** Enable debug logging */
19
+ debug?: boolean;
20
+ }
21
+ declare class ScaleMuleServer {
22
+ private apiKey;
23
+ private gatewayUrl;
24
+ private debug;
25
+ constructor(config: ServerConfig);
26
+ /**
27
+ * Make a request to the ScaleMule API
28
+ *
29
+ * @param method - HTTP method
30
+ * @param path - API path (e.g., /v1/auth/login)
31
+ * @param options - Request options
32
+ * @param options.body - Request body (will be JSON stringified)
33
+ * @param options.userId - User ID (passed through for storage operations)
34
+ * @param options.sessionToken - Session token sent as Authorization: Bearer header
35
+ * @param options.clientContext - End user context to forward (IP, user agent, etc.)
36
+ */
37
+ private request;
38
+ auth: {
39
+ /**
40
+ * Register a new user
41
+ */
42
+ register: (data: RegisterRequest) => Promise<ApiResponse<User>>;
43
+ /**
44
+ * Login user - returns session token (store in HTTP-only cookie)
45
+ */
46
+ login: (data: LoginRequest) => Promise<ApiResponse<LoginResponse>>;
47
+ /**
48
+ * Logout user
49
+ */
50
+ logout: (sessionToken: string) => Promise<ApiResponse<void>>;
51
+ /**
52
+ * Get current user from session token
53
+ */
54
+ me: (sessionToken: string) => Promise<ApiResponse<User>>;
55
+ /**
56
+ * Refresh session token
57
+ */
58
+ refresh: (sessionToken: string) => Promise<ApiResponse<{
59
+ session_token: string;
60
+ expires_at: string;
61
+ }>>;
62
+ /**
63
+ * Request password reset email
64
+ */
65
+ forgotPassword: (email: string) => Promise<ApiResponse<{
66
+ message: string;
67
+ }>>;
68
+ /**
69
+ * Reset password with token
70
+ */
71
+ resetPassword: (token: string, newPassword: string) => Promise<ApiResponse<{
72
+ message: string;
73
+ }>>;
74
+ /**
75
+ * Verify email with token
76
+ */
77
+ verifyEmail: (token: string) => Promise<ApiResponse<{
78
+ message: string;
79
+ }>>;
80
+ /**
81
+ * Resend verification email.
82
+ * Can be called with a session token (authenticated) or email (unauthenticated).
83
+ */
84
+ resendVerification: (sessionTokenOrEmail: string, options?: {
85
+ email?: string;
86
+ }) => Promise<ApiResponse<{
87
+ message: string;
88
+ }>>;
89
+ };
90
+ user: {
91
+ /**
92
+ * Update user profile
93
+ */
94
+ update: (sessionToken: string, data: {
95
+ full_name?: string;
96
+ avatar_url?: string;
97
+ }) => Promise<ApiResponse<User>>;
98
+ /**
99
+ * Change password
100
+ */
101
+ changePassword: (sessionToken: string, currentPassword: string, newPassword: string) => Promise<ApiResponse<{
102
+ message: string;
103
+ }>>;
104
+ /**
105
+ * Change email
106
+ */
107
+ changeEmail: (sessionToken: string, newEmail: string, password: string) => Promise<ApiResponse<{
108
+ message: string;
109
+ }>>;
110
+ /**
111
+ * Delete account
112
+ */
113
+ deleteAccount: (sessionToken: string, password: string) => Promise<ApiResponse<{
114
+ message: string;
115
+ }>>;
116
+ };
117
+ secrets: {
118
+ /**
119
+ * Get a secret from the tenant vault
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const result = await scalemule.secrets.get('ANONYMOUS_USER_SALT')
124
+ * if (result.success) {
125
+ * console.log('Salt:', result.data.value)
126
+ * }
127
+ * ```
128
+ */
129
+ get: (key: string) => Promise<ApiResponse<{
130
+ value: string;
131
+ version: number;
132
+ }>>;
133
+ /**
134
+ * Set a secret in the tenant vault
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * await scalemule.secrets.set('ANONYMOUS_USER_SALT', 'my-secret-salt')
139
+ * ```
140
+ */
141
+ set: (key: string, value: string) => Promise<ApiResponse<{
142
+ value: string;
143
+ version: number;
144
+ }>>;
145
+ /**
146
+ * Delete a secret from the tenant vault
147
+ */
148
+ delete: (key: string) => Promise<ApiResponse<void>>;
149
+ /**
150
+ * List all secrets in the tenant vault
151
+ */
152
+ list: () => Promise<ApiResponse<{
153
+ secrets: Array<{
154
+ path: string;
155
+ version: number;
156
+ }>;
157
+ }>>;
158
+ /**
159
+ * Get secret version history
160
+ */
161
+ versions: (key: string) => Promise<ApiResponse<{
162
+ versions: Array<{
163
+ version: number;
164
+ created_at: string;
165
+ }>;
166
+ }>>;
167
+ /**
168
+ * Rollback to a specific version
169
+ */
170
+ rollback: (key: string, version: number) => Promise<ApiResponse<{
171
+ value: string;
172
+ version: number;
173
+ }>>;
174
+ /**
175
+ * Rotate a secret (copy current version as new version)
176
+ */
177
+ rotate: (key: string, newValue: string) => Promise<ApiResponse<{
178
+ value: string;
179
+ version: number;
180
+ }>>;
181
+ };
182
+ bundles: {
183
+ /**
184
+ * Get a bundle (structured secret like database credentials)
185
+ *
186
+ * @param key - Bundle key (e.g., 'database/prod')
187
+ * @param resolve - Whether to resolve inheritance (default: true)
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const result = await scalemule.bundles.get('database/prod')
192
+ * if (result.success) {
193
+ * console.log('DB Host:', result.data.data.host)
194
+ * }
195
+ * ```
196
+ */
197
+ get: <T = Record<string, unknown>>(key: string, resolve?: boolean) => Promise<ApiResponse<{
198
+ type: string;
199
+ data: T;
200
+ version: number;
201
+ inherits_from?: string;
202
+ }>>;
203
+ /**
204
+ * Set a bundle (structured secret)
205
+ *
206
+ * @param key - Bundle key
207
+ * @param type - Bundle type: 'mysql', 'postgres', 'redis', 's3', 'oauth', 'smtp', 'generic'
208
+ * @param data - Bundle data (structure depends on type)
209
+ * @param inheritsFrom - Optional parent bundle key for inheritance
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * // Create a MySQL bundle
214
+ * await scalemule.bundles.set('database/prod', 'mysql', {
215
+ * host: 'db.example.com',
216
+ * port: 3306,
217
+ * username: 'app',
218
+ * password: 'secret',
219
+ * database: 'myapp'
220
+ * })
221
+ *
222
+ * // Create a bundle that inherits from another
223
+ * await scalemule.bundles.set('database/staging', 'mysql', {
224
+ * host: 'staging-db.example.com', // Override just the host
225
+ * }, 'database/prod')
226
+ * ```
227
+ */
228
+ set: <T = Record<string, unknown>>(key: string, type: string, data: T, inheritsFrom?: string) => Promise<ApiResponse<{
229
+ type: string;
230
+ data: T;
231
+ version: number;
232
+ }>>;
233
+ /**
234
+ * Delete a bundle
235
+ */
236
+ delete: (key: string) => Promise<ApiResponse<void>>;
237
+ /**
238
+ * List all bundles
239
+ */
240
+ list: () => Promise<ApiResponse<{
241
+ bundles: Array<{
242
+ path: string;
243
+ type: string;
244
+ version: number;
245
+ inherits_from?: string;
246
+ }>;
247
+ }>>;
248
+ /**
249
+ * Get connection URL for a database bundle
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * const result = await scalemule.bundles.connectionUrl('database/prod')
254
+ * if (result.success) {
255
+ * const client = mysql.createConnection(result.data.url)
256
+ * }
257
+ * ```
258
+ */
259
+ connectionUrl: (key: string) => Promise<ApiResponse<{
260
+ url: string;
261
+ }>>;
262
+ };
263
+ vaultAudit: {
264
+ /**
265
+ * Query audit logs for your tenant's vault operations
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * const result = await scalemule.vaultAudit.query({
270
+ * action: 'read',
271
+ * path: 'database/*',
272
+ * since: '2026-01-01'
273
+ * })
274
+ * ```
275
+ */
276
+ query: (options?: {
277
+ action?: "read" | "write" | "delete" | "list";
278
+ path?: string;
279
+ since?: string;
280
+ until?: string;
281
+ limit?: number;
282
+ }) => Promise<ApiResponse<{
283
+ logs: Array<{
284
+ timestamp: string;
285
+ action: string;
286
+ resource_path: string;
287
+ success: boolean;
288
+ error_message?: string;
289
+ }>;
290
+ }>>;
291
+ };
292
+ storage: {
293
+ /**
294
+ * List user's files
295
+ */
296
+ list: (userId: string, params?: ListFilesParams) => Promise<ApiResponse<ListFilesResponse>>;
297
+ /**
298
+ * Get file info
299
+ */
300
+ get: (fileId: string) => Promise<ApiResponse<StorageFile>>;
301
+ /**
302
+ * Delete file
303
+ */
304
+ delete: (userId: string, fileId: string) => Promise<ApiResponse<void>>;
305
+ /**
306
+ * Upload file (from server - use FormData)
307
+ *
308
+ * @param userId - The user ID who owns this file
309
+ * @param file - File data to upload
310
+ * @param options - Upload options
311
+ * @param options.clientContext - End user context to forward (IP, user agent, etc.)
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * // Forward end user context for proper attribution
316
+ * const result = await scalemule.storage.upload(
317
+ * userId,
318
+ * { buffer, filename, contentType },
319
+ * { clientContext: extractClientContext(request) }
320
+ * )
321
+ * ```
322
+ */
323
+ upload: (userId: string, file: {
324
+ buffer: BlobPart;
325
+ filename: string;
326
+ contentType: string;
327
+ }, options?: {
328
+ clientContext?: ClientContext;
329
+ }) => Promise<ApiResponse<UploadResponse>>;
330
+ };
331
+ webhooks: {
332
+ /**
333
+ * Create a new webhook subscription
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * const result = await scalemule.webhooks.create({
338
+ * webhook_name: 'Video Status Webhook',
339
+ * url: 'https://myapp.com/api/webhooks/scalemule',
340
+ * events: ['video.ready', 'video.failed']
341
+ * })
342
+ *
343
+ * // Store the secret for signature verification
344
+ * console.log('Webhook secret:', result.data.secret)
345
+ * ```
346
+ */
347
+ create: (data: {
348
+ webhook_name: string;
349
+ url: string;
350
+ events: string[];
351
+ }) => Promise<ApiResponse<{
352
+ id: string;
353
+ secret: string;
354
+ url: string;
355
+ events: string[];
356
+ }>>;
357
+ /**
358
+ * List all webhook subscriptions
359
+ */
360
+ list: () => Promise<ApiResponse<{
361
+ webhooks: Array<{
362
+ id: string;
363
+ webhook_name: string;
364
+ url: string;
365
+ events: string[];
366
+ is_enabled: boolean;
367
+ }>;
368
+ }>>;
369
+ /**
370
+ * Delete a webhook subscription
371
+ */
372
+ delete: (id: string) => Promise<ApiResponse<void>>;
373
+ /**
374
+ * Update a webhook subscription
375
+ */
376
+ update: (id: string, data: {
377
+ url?: string;
378
+ events?: string[];
379
+ is_enabled?: boolean;
380
+ }) => Promise<ApiResponse<{
381
+ id: string;
382
+ url: string;
383
+ events: string[];
384
+ }>>;
385
+ /**
386
+ * Get available webhook event types
387
+ */
388
+ eventTypes: () => Promise<ApiResponse<{
389
+ events: Array<{
390
+ event_name: string;
391
+ event_description: string;
392
+ payload_schema: Record<string, unknown>;
393
+ }>;
394
+ }>>;
395
+ };
396
+ analytics: {
397
+ /**
398
+ * Track an analytics event
399
+ *
400
+ * IMPORTANT: When calling from server-side code (API routes), always pass
401
+ * clientContext to ensure the real end user's IP is recorded, not the server's IP.
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * // In an API route
406
+ * import { extractClientContext, createServerClient } from '@scalemule/nextjs/server'
407
+ *
408
+ * export async function POST(request: NextRequest) {
409
+ * const clientContext = extractClientContext(request)
410
+ * const scalemule = createServerClient()
411
+ *
412
+ * await scalemule.analytics.trackEvent({
413
+ * event_name: 'button_clicked',
414
+ * properties: { button_id: 'signup' }
415
+ * }, { clientContext })
416
+ * }
417
+ * ```
418
+ */
419
+ trackEvent: (event: {
420
+ event_name: string;
421
+ event_category?: string;
422
+ properties?: Record<string, unknown>;
423
+ user_id?: string;
424
+ session_id?: string;
425
+ anonymous_id?: string;
426
+ session_duration_seconds?: number;
427
+ page_url?: string;
428
+ page_title?: string;
429
+ referrer?: string;
430
+ landing_page?: string;
431
+ device_type?: string;
432
+ device_brand?: string;
433
+ device_model?: string;
434
+ browser?: string;
435
+ browser_version?: string;
436
+ os?: string;
437
+ os_version?: string;
438
+ screen_resolution?: string;
439
+ viewport_size?: string;
440
+ utm_source?: string;
441
+ utm_medium?: string;
442
+ utm_campaign?: string;
443
+ utm_term?: string;
444
+ utm_content?: string;
445
+ client_timestamp?: string;
446
+ timestamp?: string;
447
+ }, options?: {
448
+ clientContext?: ClientContext;
449
+ }) => Promise<ApiResponse<{
450
+ tracked: number;
451
+ session_id?: string;
452
+ }>>;
453
+ /**
454
+ * Track a page view
455
+ *
456
+ * @example
457
+ * ```typescript
458
+ * await scalemule.analytics.trackPageView({
459
+ * page_url: 'https://example.com/products',
460
+ * page_title: 'Products',
461
+ * referrer: 'https://google.com'
462
+ * }, { clientContext })
463
+ * ```
464
+ */
465
+ trackPageView: (data: {
466
+ page_url: string;
467
+ page_title?: string;
468
+ referrer?: string;
469
+ session_id?: string;
470
+ user_id?: string;
471
+ }, options?: {
472
+ clientContext?: ClientContext;
473
+ }) => Promise<ApiResponse<{
474
+ tracked: number;
475
+ session_id?: string;
476
+ }>>;
477
+ /**
478
+ * Track multiple events in a batch (max 100)
479
+ *
480
+ * @example
481
+ * ```typescript
482
+ * await scalemule.analytics.trackBatch([
483
+ * { event_name: 'item_viewed', properties: { item_id: '123' } },
484
+ * { event_name: 'item_added_to_cart', properties: { item_id: '123' } }
485
+ * ], { clientContext })
486
+ * ```
487
+ */
488
+ trackBatch: (events: Array<{
489
+ event_name: string;
490
+ event_category?: string;
491
+ properties?: Record<string, unknown>;
492
+ user_id?: string;
493
+ session_id?: string;
494
+ anonymous_id?: string;
495
+ session_duration_seconds?: number;
496
+ page_url?: string;
497
+ page_title?: string;
498
+ referrer?: string;
499
+ landing_page?: string;
500
+ device_type?: string;
501
+ browser?: string;
502
+ os?: string;
503
+ screen_resolution?: string;
504
+ viewport_size?: string;
505
+ utm_source?: string;
506
+ utm_medium?: string;
507
+ utm_campaign?: string;
508
+ utm_term?: string;
509
+ utm_content?: string;
510
+ client_timestamp?: string;
511
+ timestamp?: string;
512
+ }>, options?: {
513
+ clientContext?: ClientContext;
514
+ }) => Promise<ApiResponse<{
515
+ tracked: number;
516
+ }>>;
517
+ };
518
+ }
519
+ /**
520
+ * Create a server client with environment-based defaults
521
+ */
522
+ declare function createServerClient(config?: Partial<ServerConfig>): ScaleMuleServer;
523
+
524
+ /**
525
+ * ScaleMule Webhook Helpers
526
+ *
527
+ * Provides utilities for webhook signature verification and route handlers
528
+ * for video processing events and other ScaleMule webhooks.
529
+ *
530
+ * @example
531
+ * ```typescript
532
+ * // app/api/webhooks/scalemule/route.ts
533
+ * import { createWebhookRoutes } from '@scalemule/nextjs/server'
534
+ *
535
+ * export const { POST } = createWebhookRoutes({
536
+ * secret: process.env.SCALEMULE_WEBHOOK_SECRET,
537
+ * onVideoReady: async (event) => {
538
+ * console.log('Video ready:', event.video_id)
539
+ * await updateDocument('videos', event.video_id, { status: 'ready' })
540
+ * },
541
+ * onVideoFailed: async (event) => {
542
+ * console.log('Video failed:', event.video_id, event.reason)
543
+ * }
544
+ * })
545
+ * ```
546
+ */
547
+
548
+ interface WebhookEvent<T = Record<string, unknown>> {
549
+ event: string;
550
+ timestamp: number;
551
+ data: T;
552
+ }
553
+ interface VideoReadyEvent {
554
+ video_id: string;
555
+ application_id: string;
556
+ duration_seconds?: number;
557
+ width?: number;
558
+ height?: number;
559
+ thumbnail_url?: string;
560
+ playlist_url?: string;
561
+ }
562
+ interface VideoFailedEvent {
563
+ video_id: string;
564
+ application_id: string;
565
+ reason: string;
566
+ }
567
+ interface VideoUploadedEvent {
568
+ video_id: string;
569
+ application_id: string;
570
+ filename?: string;
571
+ size_bytes?: number;
572
+ }
573
+ interface VideoTranscodedEvent {
574
+ video_id: string;
575
+ application_id: string;
576
+ derivative_count: number;
577
+ }
578
+ interface WebhookRoutesConfig {
579
+ /** ScaleMule client configuration (optional, uses env vars by default) */
580
+ client?: Partial<ServerConfig>;
581
+ /** Webhook secret for signature verification (recommended for security) */
582
+ secret?: string;
583
+ /** Handler for video.ready events */
584
+ onVideoReady?: (event: VideoReadyEvent) => void | Promise<void>;
585
+ /** Handler for video.failed events */
586
+ onVideoFailed?: (event: VideoFailedEvent) => void | Promise<void>;
587
+ /** Handler for video.uploaded events */
588
+ onVideoUploaded?: (event: VideoUploadedEvent) => void | Promise<void>;
589
+ /** Handler for video.transcoded events */
590
+ onVideoTranscoded?: (event: VideoTranscodedEvent) => void | Promise<void>;
591
+ /** Generic handler for any webhook event */
592
+ onEvent?: (event: WebhookEvent) => void | Promise<void>;
593
+ }
594
+ /**
595
+ * Verify webhook signature using HMAC-SHA256
596
+ *
597
+ * ScaleMule webhooks include a signature header in the format: sha256=<hex_signature>
598
+ *
599
+ * @param payload - Raw request body as string
600
+ * @param signature - Value of X-Webhook-Signature header
601
+ * @param secret - Your webhook secret
602
+ * @returns true if signature is valid
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * const isValid = verifyWebhookSignature(body, signature, secret)
607
+ * if (!isValid) {
608
+ * return new Response('Invalid signature', { status: 401 })
609
+ * }
610
+ * ```
611
+ */
612
+ declare function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean;
613
+ /**
614
+ * Parse a webhook event from the raw payload
615
+ *
616
+ * @param payload - Raw request body as string
617
+ * @returns Parsed webhook event
618
+ */
619
+ declare function parseWebhookEvent<T = Record<string, unknown>>(payload: string): WebhookEvent<T>;
620
+ /**
621
+ * Register a webhook for video events
622
+ *
623
+ * @param url - The URL to receive webhook notifications
624
+ * @param options - Registration options
625
+ * @returns The webhook ID and secret for signature verification
626
+ *
627
+ * @example
628
+ * ```typescript
629
+ * const { id, secret } = await registerVideoWebhook(
630
+ * 'https://myapp.com/api/webhooks/scalemule',
631
+ * { events: ['video.ready', 'video.failed'] }
632
+ * )
633
+ *
634
+ * // Store the secret securely for signature verification
635
+ * await saveToEnv('SCALEMULE_WEBHOOK_SECRET', secret)
636
+ * ```
637
+ */
638
+ declare function registerVideoWebhook(url: string, options?: {
639
+ /** Events to subscribe to (defaults to video.ready and video.failed) */
640
+ events?: ('video.ready' | 'video.failed' | 'video.uploaded' | 'video.transcoded')[];
641
+ /** Human-readable webhook name */
642
+ name?: string;
643
+ /** Client configuration */
644
+ clientConfig?: Partial<ServerConfig>;
645
+ }): Promise<{
646
+ id: string;
647
+ secret: string;
648
+ }>;
649
+ type RouteHandler$1 = (request: Request, context: {
650
+ params: Promise<{
651
+ scalemule?: string[];
652
+ }>;
653
+ }) => Promise<Response>;
654
+ /**
655
+ * Create Next.js App Router route handlers for ScaleMule webhooks
656
+ *
657
+ * Returns a POST handler that:
658
+ * - Verifies webhook signature (if secret provided)
659
+ * - Parses the event payload
660
+ * - Calls appropriate event handlers
661
+ * - Returns proper responses
662
+ *
663
+ * @param config - Webhook routes configuration
664
+ * @returns Object with POST handler for use in route.ts
665
+ *
666
+ * @example
667
+ * ```typescript
668
+ * // app/api/webhooks/scalemule/route.ts
669
+ * import { createWebhookRoutes } from '@scalemule/nextjs/server'
670
+ *
671
+ * export const { POST } = createWebhookRoutes({
672
+ * secret: process.env.SCALEMULE_WEBHOOK_SECRET,
673
+ * onVideoReady: async (event) => {
674
+ * // Update your database when video is ready
675
+ * await db.videos.update({
676
+ * where: { id: event.video_id },
677
+ * data: {
678
+ * status: 'ready',
679
+ * duration: event.duration_seconds,
680
+ * thumbnailUrl: event.thumbnail_url,
681
+ * }
682
+ * })
683
+ * },
684
+ * onVideoFailed: async (event) => {
685
+ * // Handle failed video processing
686
+ * await notifyUser(event.video_id, event.reason)
687
+ * }
688
+ * })
689
+ * ```
690
+ */
691
+ declare function createWebhookRoutes(config?: WebhookRoutesConfig): {
692
+ POST: RouteHandler$1;
693
+ };
694
+
695
+ /**
696
+ * Simplified webhook handler for 1-line setup.
697
+ *
698
+ * Usage in your Next.js app:
699
+ * ```ts
700
+ * // app/api/webhooks/scalemule/route.ts
701
+ * import { createWebhookHandler } from '@scalemule/nextjs/server/webhooks'
702
+ *
703
+ * export const POST = createWebhookHandler({
704
+ * secret: process.env.SCALEMULE_WEBHOOK_SECRET,
705
+ * onEvent: {
706
+ * 'video.transcoding.completed': async (event) => { ... },
707
+ * 'storage.file.uploaded': async (event) => { ... },
708
+ * }
709
+ * })
710
+ * ```
711
+ */
712
+
713
+ interface WebhookHandlerConfig {
714
+ /** Webhook secret for signature verification */
715
+ secret?: string;
716
+ /** Map of event name → handler function */
717
+ onEvent?: Record<string, (event: WebhookEvent) => void | Promise<void>>;
718
+ }
719
+ type RouteHandler = (request: Request) => Promise<Response>;
720
+ /**
721
+ * Create a webhook handler for ScaleMule events.
722
+ *
723
+ * Simpler alternative to createWebhookRoutes() — uses an event map
724
+ * instead of separate onVideoReady, onVideoFailed, etc. callbacks.
725
+ */
726
+ declare function createWebhookHandler(config?: WebhookHandlerConfig): RouteHandler;
727
+
728
+ export { type ServerConfig as S, type VideoReadyEvent as V, type WebhookEvent as W, ScaleMuleServer as a, createWebhookRoutes as b, createServerClient as c, type VideoFailedEvent as d, type VideoUploadedEvent as e, type VideoTranscodedEvent as f, type WebhookRoutesConfig as g, createWebhookHandler as h, parseWebhookEvent as p, registerVideoWebhook as r, verifyWebhookSignature as v };