@plyaz/types 1.15.20 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/aws/index.d.ts +5 -0
- package/dist/api/aws/signature.d.ts +42 -0
- package/dist/api/endpoints/cdn/endpoints.d.ts +57 -0
- package/dist/api/endpoints/cdn/index.d.ts +6 -0
- package/dist/api/endpoints/cdn/types.d.ts +151 -0
- package/dist/api/endpoints/index.d.ts +2 -0
- package/dist/api/endpoints/types.d.ts +3 -1
- package/dist/api/endpoints/virustotal/endpoints.d.ts +37 -0
- package/dist/api/endpoints/virustotal/index.d.ts +6 -0
- package/dist/api/endpoints/virustotal/types.d.ts +202 -0
- package/dist/api/index.cjs +1317 -1
- package/dist/api/index.cjs.map +1 -1
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +1317 -1
- package/dist/api/index.js.map +1 -1
- package/dist/core/idempotency.d.ts +48 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/errors/codes.d.ts +296 -0
- package/dist/errors/enums.d.ts +10 -0
- package/dist/errors/index.cjs +1482 -1
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1482 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/validation.d.ts +71 -0
- package/dist/index.cjs +2268 -132
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +2227 -133
- package/dist/index.js.map +1 -1
- package/dist/logger/enums.d.ts +10 -0
- package/dist/notifications/types.d.ts +1 -2
- package/dist/storage/compliance.d.ts +247 -0
- package/dist/storage/enums.d.ts +527 -0
- package/dist/storage/event-handler-mapping.d.ts +69 -0
- package/dist/storage/index.d.ts +13 -0
- package/dist/storage/interfaces.d.ts +2242 -0
- package/dist/storage/plugins.d.ts +996 -0
- package/dist/storage/schemas.d.ts +224 -0
- package/dist/storage/webhooks.d.ts +340 -0
- package/package.json +6 -1
|
@@ -0,0 +1,996 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Plugin System Types
|
|
3
|
+
* @module @plyaz/types/storage/plugins
|
|
4
|
+
*
|
|
5
|
+
* Defines the plugin system for extending storage functionality with lifecycle hooks.
|
|
6
|
+
* Plugins are separate from webhooks - they run synchronously during file operations.
|
|
7
|
+
*/
|
|
8
|
+
import type { FileMetadata, UploadParams, UploadResult, DownloadParams, DownloadResult, DeleteParams, FileDeleteResult, PresignedUrlOptions, PresignedUrlResult, AdapterHealthCheck, StorageListFilesParams, StorageListFilesResult, StorageCopyFileParams, StorageMoveFileParams, StorageReplaceFileParams } from './interfaces';
|
|
9
|
+
import type { STORAGE_PLUGIN_TYPE } from './enums';
|
|
10
|
+
/**
|
|
11
|
+
* Known plugin names for type safety
|
|
12
|
+
* Use this for skipPlugins/onlyPlugins parameters
|
|
13
|
+
*/
|
|
14
|
+
export type StorageKnownPluginName = 'virus-scanner' | 'sharp-image-processor' | 'ffmpeg-video-processor' | 'metadata-extractor' | 'cdn-invalidator' | 'file-size-validator' | 'metadata-enricher' | 'upload-notifier' | 'delete-auditor' | 'access-logger' | string;
|
|
15
|
+
/**
|
|
16
|
+
* Plugin execution options for filtering which plugins to run
|
|
17
|
+
* Used to control plugin execution per operation
|
|
18
|
+
*/
|
|
19
|
+
export interface StoragePluginExecutionOptions {
|
|
20
|
+
/** Skip specific plugins by name for this operation */
|
|
21
|
+
skipPlugins?: readonly StorageKnownPluginName[];
|
|
22
|
+
/** Only run these specific plugins for this operation */
|
|
23
|
+
onlyPlugins?: readonly StorageKnownPluginName[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Base plugin configuration
|
|
27
|
+
*/
|
|
28
|
+
export interface BasePluginConfig {
|
|
29
|
+
/** Plugin name */
|
|
30
|
+
name: StorageKnownPluginName;
|
|
31
|
+
/** Plugin type */
|
|
32
|
+
type: STORAGE_PLUGIN_TYPE;
|
|
33
|
+
/** Plugin priority (1-100, lower runs first) */
|
|
34
|
+
priority?: number;
|
|
35
|
+
/** Plugin version */
|
|
36
|
+
version?: string;
|
|
37
|
+
/** Plugin description */
|
|
38
|
+
description?: string;
|
|
39
|
+
/** Whether the plugin is enabled */
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
/** Logger instance */
|
|
42
|
+
logger?: unknown;
|
|
43
|
+
/** API client configuration (for REST API-based plugins) */
|
|
44
|
+
apiClientConfig?: {
|
|
45
|
+
baseURL: string;
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
timeout?: number;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Plugin Registry Configuration
|
|
53
|
+
*/
|
|
54
|
+
export interface PluginRegistryConfig {
|
|
55
|
+
/** Logger instance */
|
|
56
|
+
logger?: unknown;
|
|
57
|
+
/** Whether to continue execution if a plugin fails */
|
|
58
|
+
continueOnError?: boolean;
|
|
59
|
+
/** Maximum execution time for all plugins (milliseconds) */
|
|
60
|
+
maxExecutionTime?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Storage Adapter Interface for Plugins
|
|
64
|
+
* Provides access to all public storage operations
|
|
65
|
+
* BaseStorageAdapter implements this interface
|
|
66
|
+
*
|
|
67
|
+
* Note: This interface uses structural typing to match BaseStorageAdapter
|
|
68
|
+
* without creating circular dependencies between packages
|
|
69
|
+
*/
|
|
70
|
+
export interface PluginStorageAdapterInterface {
|
|
71
|
+
/** Adapter name */
|
|
72
|
+
readonly name: string;
|
|
73
|
+
/** Adapter type */
|
|
74
|
+
readonly type: string;
|
|
75
|
+
/** Adapter priority */
|
|
76
|
+
readonly priority: number;
|
|
77
|
+
/** Whether adapter is enabled */
|
|
78
|
+
readonly enabled: boolean;
|
|
79
|
+
/** Upload a file to storage - uses UploadParams signature */
|
|
80
|
+
upload: (params: UploadParams) => Promise<UploadResult>;
|
|
81
|
+
/** Download a file from storage - uses DownloadParams signature */
|
|
82
|
+
download: (params: DownloadParams) => Promise<DownloadResult>;
|
|
83
|
+
/** Delete a file from storage - uses DeleteParams signature */
|
|
84
|
+
delete: (params: DeleteParams) => Promise<FileDeleteResult>;
|
|
85
|
+
/** Generate a presigned/signed URL for file access */
|
|
86
|
+
getSignedUrl: (options: PresignedUrlOptions) => Promise<PresignedUrlResult>;
|
|
87
|
+
/** Check if adapter is available */
|
|
88
|
+
isAvailable: () => boolean;
|
|
89
|
+
/** Perform health check on adapter */
|
|
90
|
+
healthCheck: () => Promise<AdapterHealthCheck>;
|
|
91
|
+
/** Get file metadata */
|
|
92
|
+
getFileMetadata: (fileId: string, bucket?: string) => Promise<FileMetadata>;
|
|
93
|
+
/** Restore a soft-deleted file */
|
|
94
|
+
restoreFile?: (fileId: string) => Promise<FileMetadata>;
|
|
95
|
+
/** List files with optional filters */
|
|
96
|
+
listFiles?: (params: StorageListFilesParams) => Promise<StorageListFilesResult>;
|
|
97
|
+
/** Copy a file */
|
|
98
|
+
copyFile?: (params: StorageCopyFileParams) => Promise<FileMetadata>;
|
|
99
|
+
/** Move a file */
|
|
100
|
+
moveFile?: (params: StorageMoveFileParams) => Promise<FileMetadata>;
|
|
101
|
+
/** Replace a file */
|
|
102
|
+
replaceFile?: (params: StorageReplaceFileParams) => Promise<FileMetadata>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Plugin lifecycle hook context
|
|
106
|
+
* Provides information about the current operation to plugins
|
|
107
|
+
*/
|
|
108
|
+
export interface StoragePluginContext {
|
|
109
|
+
/** Operation type (upload, delete, access, etc.) */
|
|
110
|
+
operation: 'upload' | 'delete' | 'access' | 'update';
|
|
111
|
+
/** Timestamp when operation started */
|
|
112
|
+
timestamp: Date;
|
|
113
|
+
/** User ID performing the operation (if available) */
|
|
114
|
+
userId?: string;
|
|
115
|
+
/** Request correlation ID for tracing */
|
|
116
|
+
correlationId?: string;
|
|
117
|
+
/** Storage adapter for file operations - provides access to all public storage methods */
|
|
118
|
+
storageAdapter: PluginStorageAdapterInterface;
|
|
119
|
+
/** Additional context metadata */
|
|
120
|
+
metadata?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Result from beforeUpload hook
|
|
124
|
+
* Can modify metadata or reject the upload
|
|
125
|
+
*/
|
|
126
|
+
export interface BeforeUploadResult {
|
|
127
|
+
/** Whether to allow the upload */
|
|
128
|
+
allowed: boolean;
|
|
129
|
+
/** Reason if upload is rejected */
|
|
130
|
+
reason?: string;
|
|
131
|
+
/** Modified file (if plugin wants to return modified file) */
|
|
132
|
+
file?: StoragePluginFile;
|
|
133
|
+
/** Modified metadata (if plugin wants to add/modify) */
|
|
134
|
+
modifiedMetadata?: Partial<FileMetadata>;
|
|
135
|
+
/** Additional data to pass to afterUpload hooks */
|
|
136
|
+
pluginData?: Record<string, unknown>;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Result from beforeDelete hook
|
|
140
|
+
* Can prevent deletion
|
|
141
|
+
*/
|
|
142
|
+
export interface BeforeDeleteResult {
|
|
143
|
+
/** Whether to allow the deletion */
|
|
144
|
+
allowed: boolean;
|
|
145
|
+
/** Reason if deletion is rejected */
|
|
146
|
+
reason?: string;
|
|
147
|
+
/** Additional data to pass to afterDelete hooks */
|
|
148
|
+
pluginData?: Record<string, unknown>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* File buffer with metadata for plugin hooks
|
|
152
|
+
*/
|
|
153
|
+
export interface StoragePluginFile {
|
|
154
|
+
/** File buffer */
|
|
155
|
+
buffer: globalThis.Buffer;
|
|
156
|
+
/** File metadata */
|
|
157
|
+
metadata: FileMetadata;
|
|
158
|
+
/** Original filename */
|
|
159
|
+
filename: string;
|
|
160
|
+
/** MIME type */
|
|
161
|
+
mimeType: string;
|
|
162
|
+
/** File size in bytes */
|
|
163
|
+
size: number;
|
|
164
|
+
/** Custom metadata that plugins can add */
|
|
165
|
+
customMetadata?: Record<string, unknown>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Upload result passed to afterUpload hooks
|
|
169
|
+
*/
|
|
170
|
+
export interface StoragePluginUploadResult {
|
|
171
|
+
/** Uploaded file ID */
|
|
172
|
+
fileId: string;
|
|
173
|
+
/** Public URL to access the file */
|
|
174
|
+
url: string;
|
|
175
|
+
/** CDN URL (if applicable) */
|
|
176
|
+
cdnUrl?: string;
|
|
177
|
+
/** File metadata */
|
|
178
|
+
metadata: FileMetadata;
|
|
179
|
+
/** Storage adapter that handled the upload */
|
|
180
|
+
adapter: string;
|
|
181
|
+
/** Upload duration in milliseconds */
|
|
182
|
+
duration: number;
|
|
183
|
+
/** Data passed from beforeUpload hooks */
|
|
184
|
+
pluginData?: Record<string, unknown>;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Delete result passed to afterDelete hooks
|
|
188
|
+
*/
|
|
189
|
+
export interface StoragePluginDeleteResult {
|
|
190
|
+
/** Deleted file ID */
|
|
191
|
+
fileId: string;
|
|
192
|
+
/** File metadata (before deletion) */
|
|
193
|
+
metadata: FileMetadata;
|
|
194
|
+
/** Whether it was a soft delete */
|
|
195
|
+
softDelete: boolean;
|
|
196
|
+
/** Deletion timestamp */
|
|
197
|
+
deletedAt: Date;
|
|
198
|
+
/** Data passed from beforeDelete hooks */
|
|
199
|
+
pluginData?: Record<string, unknown>;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Access event passed to onAccess hooks
|
|
203
|
+
*/
|
|
204
|
+
export interface StoragePluginAccessEvent {
|
|
205
|
+
/** Accessed file ID */
|
|
206
|
+
fileId: string;
|
|
207
|
+
/** User ID who accessed the file */
|
|
208
|
+
userId: string;
|
|
209
|
+
/** Access type (download, view, preview, etc.) */
|
|
210
|
+
accessType: 'download' | 'view' | 'preview' | 'stream' | 'other';
|
|
211
|
+
/** Access timestamp */
|
|
212
|
+
timestamp: Date;
|
|
213
|
+
/** File metadata */
|
|
214
|
+
metadata?: FileMetadata;
|
|
215
|
+
/** IP address of the accessor */
|
|
216
|
+
ipAddress?: string;
|
|
217
|
+
/** User agent */
|
|
218
|
+
userAgent?: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Plugin health status
|
|
222
|
+
*/
|
|
223
|
+
export interface StoragePluginHealth {
|
|
224
|
+
/** Plugin name */
|
|
225
|
+
plugin: StorageKnownPluginName;
|
|
226
|
+
/** Whether the plugin is healthy */
|
|
227
|
+
healthy: boolean;
|
|
228
|
+
/** Status message */
|
|
229
|
+
message?: string;
|
|
230
|
+
/** Last check timestamp */
|
|
231
|
+
lastCheck: Date;
|
|
232
|
+
/** Error details if unhealthy */
|
|
233
|
+
error?: {
|
|
234
|
+
code: string;
|
|
235
|
+
message: string;
|
|
236
|
+
stack?: string;
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Base Storage Plugin Interface
|
|
241
|
+
* All plugins must implement this interface
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* class VirusScanPlugin implements StoragePlugin {
|
|
246
|
+
* readonly name = 'virus-scan';
|
|
247
|
+
* readonly type = STORAGE_PLUGIN_TYPE.SECURITY;
|
|
248
|
+
* readonly priority = 10; // Run first
|
|
249
|
+
*
|
|
250
|
+
* async beforeUpload(file: StoragePluginFile, context: StoragePluginContext): Promise<BeforeUploadResult> {
|
|
251
|
+
* const scanResult = await this.scanFile(file.buffer);
|
|
252
|
+
* if (scanResult.infected) {
|
|
253
|
+
* return {
|
|
254
|
+
* allowed: false,
|
|
255
|
+
* reason: `Virus detected: ${scanResult.virusName}`,
|
|
256
|
+
* };
|
|
257
|
+
* }
|
|
258
|
+
* return { allowed: true };
|
|
259
|
+
* }
|
|
260
|
+
* }
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
export interface StoragePlugin {
|
|
264
|
+
/** Unique plugin name (lowercase-with-dashes) */
|
|
265
|
+
readonly name: StorageKnownPluginName;
|
|
266
|
+
/** Plugin type for categorization */
|
|
267
|
+
readonly type: STORAGE_PLUGIN_TYPE;
|
|
268
|
+
/**
|
|
269
|
+
* Plugin priority (1-100)
|
|
270
|
+
* Lower numbers run first
|
|
271
|
+
* Security plugins typically use 1-20
|
|
272
|
+
* Metadata plugins typically use 21-40
|
|
273
|
+
* Other plugins typically use 41-100
|
|
274
|
+
*/
|
|
275
|
+
readonly priority: number;
|
|
276
|
+
/** Plugin version */
|
|
277
|
+
readonly version?: string;
|
|
278
|
+
/** Plugin description */
|
|
279
|
+
readonly description?: string;
|
|
280
|
+
/** Whether the plugin is enabled */
|
|
281
|
+
enabled?: boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Initialize the plugin
|
|
284
|
+
* Called once when plugin is registered
|
|
285
|
+
* Use this to setup connections, validate configuration, etc.
|
|
286
|
+
*/
|
|
287
|
+
initialize?(): Promise<void>;
|
|
288
|
+
/**
|
|
289
|
+
* Cleanup the plugin
|
|
290
|
+
* Called when plugin is destroyed
|
|
291
|
+
* Use this to close connections, release resources, etc.
|
|
292
|
+
*/
|
|
293
|
+
destroy?(): Promise<void>;
|
|
294
|
+
/**
|
|
295
|
+
* Check plugin health
|
|
296
|
+
* Used for monitoring and diagnostics
|
|
297
|
+
*/
|
|
298
|
+
healthCheck?(): Promise<StoragePluginHealth>;
|
|
299
|
+
/**
|
|
300
|
+
* PRE-UPLOAD HOOK (BLOCKING)
|
|
301
|
+
* Called BEFORE file is uploaded to storage
|
|
302
|
+
* Can reject upload by returning { allowed: false }
|
|
303
|
+
* Can modify metadata by returning { modifiedMetadata: {...} }
|
|
304
|
+
*
|
|
305
|
+
* @param file - File to be uploaded with metadata
|
|
306
|
+
* @param context - Operation context
|
|
307
|
+
* @returns Result indicating whether to allow upload and any modifications
|
|
308
|
+
*/
|
|
309
|
+
beforeUpload?(file: StoragePluginFile, context: StoragePluginContext): Promise<BeforeUploadResult>;
|
|
310
|
+
/**
|
|
311
|
+
* POST-UPLOAD HOOK (ASYNC)
|
|
312
|
+
* Called AFTER file is successfully uploaded to storage
|
|
313
|
+
* Runs asynchronously, doesn't block the upload response
|
|
314
|
+
* Use for metadata extraction, CDN invalidation, audit logging, etc.
|
|
315
|
+
*
|
|
316
|
+
* @param result - Upload result with file ID and metadata
|
|
317
|
+
* @param context - Operation context
|
|
318
|
+
*/
|
|
319
|
+
afterUpload?(result: StoragePluginUploadResult, context: StoragePluginContext): Promise<void>;
|
|
320
|
+
/**
|
|
321
|
+
* PRE-DELETE HOOK (BLOCKING)
|
|
322
|
+
* Called BEFORE file is deleted from storage
|
|
323
|
+
* Can prevent deletion by returning { allowed: false }
|
|
324
|
+
*
|
|
325
|
+
* @param fileId - File ID to be deleted
|
|
326
|
+
* @param metadata - File metadata (if available)
|
|
327
|
+
* @param context - Operation context
|
|
328
|
+
* @returns Result indicating whether to allow deletion
|
|
329
|
+
*/
|
|
330
|
+
beforeDelete?(fileId: string, metadata: FileMetadata | undefined, context: StoragePluginContext): Promise<BeforeDeleteResult>;
|
|
331
|
+
/**
|
|
332
|
+
* POST-DELETE HOOK (ASYNC)
|
|
333
|
+
* Called AFTER file is deleted from storage
|
|
334
|
+
* Runs asynchronously, doesn't block the delete response
|
|
335
|
+
* Use for CDN cache purging, audit logging, cleanup, etc.
|
|
336
|
+
*
|
|
337
|
+
* @param result - Delete result with file ID and metadata
|
|
338
|
+
* @param context - Operation context
|
|
339
|
+
*/
|
|
340
|
+
afterDelete?(result: StoragePluginDeleteResult, context: StoragePluginContext): Promise<void>;
|
|
341
|
+
/**
|
|
342
|
+
* ON-ACCESS HOOK (ASYNC)
|
|
343
|
+
* Called when a file is accessed (downloaded, viewed, etc.)
|
|
344
|
+
* Runs asynchronously, doesn't block the access
|
|
345
|
+
* Use for access logging, analytics, compliance tracking, etc.
|
|
346
|
+
*
|
|
347
|
+
* @param event - Access event details
|
|
348
|
+
* @param context - Operation context
|
|
349
|
+
*/
|
|
350
|
+
onAccess?(event: StoragePluginAccessEvent, context: StoragePluginContext): Promise<void>;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Plugin configuration
|
|
354
|
+
* Used to configure a plugin instance
|
|
355
|
+
*/
|
|
356
|
+
export interface StoragePluginConfig {
|
|
357
|
+
/** Plugin instance */
|
|
358
|
+
plugin: StoragePlugin;
|
|
359
|
+
/** Whether the plugin is enabled */
|
|
360
|
+
enabled?: boolean;
|
|
361
|
+
/** Override priority */
|
|
362
|
+
priority?: number;
|
|
363
|
+
/** Additional configuration */
|
|
364
|
+
config?: Record<string, unknown>;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Plugin execution result
|
|
368
|
+
* Returned by plugin registry after executing hooks
|
|
369
|
+
*/
|
|
370
|
+
export interface StoragePluginExecutionResult {
|
|
371
|
+
/** Whether all plugins allowed the operation */
|
|
372
|
+
allowed: boolean;
|
|
373
|
+
/** Reason if operation was rejected */
|
|
374
|
+
reason?: string;
|
|
375
|
+
/** Plugin that rejected the operation */
|
|
376
|
+
rejectedBy?: string;
|
|
377
|
+
/** Modified metadata from plugins */
|
|
378
|
+
modifiedMetadata?: Partial<FileMetadata>;
|
|
379
|
+
/** Plugin data to pass to subsequent hooks */
|
|
380
|
+
pluginData?: Record<string, unknown>;
|
|
381
|
+
/** Execution duration in milliseconds */
|
|
382
|
+
duration: number;
|
|
383
|
+
/** Number of plugins executed */
|
|
384
|
+
pluginsExecuted: number;
|
|
385
|
+
/** Errors from plugins (non-fatal) */
|
|
386
|
+
errors?: Array<{
|
|
387
|
+
plugin: string;
|
|
388
|
+
error: Error;
|
|
389
|
+
}>;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Virus scan result
|
|
393
|
+
*/
|
|
394
|
+
export interface VirusScanResult {
|
|
395
|
+
/** Whether the file is clean (no threats detected) */
|
|
396
|
+
clean: boolean;
|
|
397
|
+
/** Whether the file is infected with malware */
|
|
398
|
+
infected: boolean;
|
|
399
|
+
/** Name of the virus/malware detected (if any) */
|
|
400
|
+
virusName?: string;
|
|
401
|
+
/** Scan duration in milliseconds */
|
|
402
|
+
scanTime: number;
|
|
403
|
+
/** Timestamp when scan was performed */
|
|
404
|
+
scanDate: Date;
|
|
405
|
+
/** Scan confidence score (0-100) */
|
|
406
|
+
confidence?: number;
|
|
407
|
+
/** Additional scan metadata from the provider */
|
|
408
|
+
metadata?: Record<string, unknown>;
|
|
409
|
+
/** Provider-specific scan ID for tracking */
|
|
410
|
+
scanId?: string;
|
|
411
|
+
/** Detailed threat information */
|
|
412
|
+
threats?: VirusThreat[];
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Detailed threat information
|
|
416
|
+
*/
|
|
417
|
+
export interface VirusThreat {
|
|
418
|
+
/** Threat name/signature */
|
|
419
|
+
name: string;
|
|
420
|
+
/** Threat type (virus, trojan, ransomware, etc.) */
|
|
421
|
+
type?: string;
|
|
422
|
+
/** Threat severity (low, medium, high, critical) */
|
|
423
|
+
severity?: 'low' | 'medium' | 'high' | 'critical';
|
|
424
|
+
/** Detection engine that found this threat */
|
|
425
|
+
engine?: string;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Base virus scan provider configuration
|
|
429
|
+
* Common configuration for all virus scanning providers
|
|
430
|
+
*/
|
|
431
|
+
export interface VirusScanProviderConfig {
|
|
432
|
+
/** API key or authentication token */
|
|
433
|
+
apiKey?: string;
|
|
434
|
+
/** Provider API endpoint (baseURL) */
|
|
435
|
+
endpoint?: string;
|
|
436
|
+
/** Request timeout in milliseconds */
|
|
437
|
+
timeout?: number;
|
|
438
|
+
/** Maximum file size to scan (in bytes) */
|
|
439
|
+
maxFileSize?: number;
|
|
440
|
+
/** Enable verbose logging */
|
|
441
|
+
verbose?: boolean;
|
|
442
|
+
/** Additional provider-specific options */
|
|
443
|
+
options?: Record<string, unknown>;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Base virus scan provider interface
|
|
447
|
+
* All virus scan providers must implement this interface
|
|
448
|
+
*/
|
|
449
|
+
export interface VirusScanProvider {
|
|
450
|
+
/** Provider name */
|
|
451
|
+
readonly providerName: string;
|
|
452
|
+
/**
|
|
453
|
+
* Scan a file for viruses/malware
|
|
454
|
+
* @param file - File buffer to scan
|
|
455
|
+
* @param filename - Original filename (for context)
|
|
456
|
+
* @returns Scan result with threat information
|
|
457
|
+
*/
|
|
458
|
+
scan(file: globalThis.Buffer, filename: string): Promise<VirusScanResult>;
|
|
459
|
+
/**
|
|
460
|
+
* Check if provider is available and healthy
|
|
461
|
+
* @returns True if provider can accept scan requests
|
|
462
|
+
*/
|
|
463
|
+
isAvailable(): Promise<boolean>;
|
|
464
|
+
/**
|
|
465
|
+
* Get provider statistics (optional)
|
|
466
|
+
* @returns Provider usage statistics
|
|
467
|
+
*/
|
|
468
|
+
getStatistics?(): Promise<{
|
|
469
|
+
scansPerformed: number;
|
|
470
|
+
threatsDetected: number;
|
|
471
|
+
averageScanTime: number;
|
|
472
|
+
}>;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Virus scan plugin configuration
|
|
476
|
+
*/
|
|
477
|
+
export interface VirusScanPluginConfig extends Omit<BasePluginConfig, 'name' | 'type'> {
|
|
478
|
+
/** Virus scan provider instance */
|
|
479
|
+
provider: VirusScanProvider;
|
|
480
|
+
/** API key for the provider (for REST-based providers like VirusTotal) */
|
|
481
|
+
apiKey?: string;
|
|
482
|
+
/** Provider API endpoint (for REST-based providers) */
|
|
483
|
+
apiEndpoint?: string;
|
|
484
|
+
/** Reject upload if scan fails (default: true) */
|
|
485
|
+
rejectOnError?: boolean;
|
|
486
|
+
/** Skip scan for files above this size (bytes, default: no limit) */
|
|
487
|
+
skipAboveSize?: number;
|
|
488
|
+
/** File extensions to skip scanning (e.g., ['.txt', '.md']) */
|
|
489
|
+
skipExtensions?: string[];
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* VirusTotal provider configuration
|
|
493
|
+
* @see VirusTotalProvider in @plyaz/storage/plugins
|
|
494
|
+
* Note: API key and endpoint are configured at the plugin level
|
|
495
|
+
*/
|
|
496
|
+
export interface VirusTotalProviderConfig extends VirusScanProviderConfig {
|
|
497
|
+
/** Wait for scan to complete (default: true) */
|
|
498
|
+
waitForResult?: boolean;
|
|
499
|
+
/** Maximum wait time for scan results in milliseconds (default: 60000) */
|
|
500
|
+
maxWaitTime?: number;
|
|
501
|
+
/** Poll interval for checking scan status in milliseconds (default: 5000) */
|
|
502
|
+
pollInterval?: number;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* ClamAV provider configuration for virus scanning
|
|
506
|
+
* @see ClamAVProvider in @plyaz/storage/plugins
|
|
507
|
+
*/
|
|
508
|
+
export interface ClamAVProviderConfig extends VirusScanProviderConfig {
|
|
509
|
+
/** ClamAV daemon host (default: 'localhost') */
|
|
510
|
+
host?: string;
|
|
511
|
+
/** ClamAV daemon port (default: 3310) */
|
|
512
|
+
port?: number;
|
|
513
|
+
/** Socket path for Unix domain socket (alternative to host/port) */
|
|
514
|
+
socketPath?: string;
|
|
515
|
+
/** Enable quarantine for infected files (default: false) */
|
|
516
|
+
enableQuarantine?: boolean;
|
|
517
|
+
/** Quarantine directory path (default: './quarantine') */
|
|
518
|
+
quarantinePath?: string;
|
|
519
|
+
/** Enable streaming scan mode (default: true for better performance) */
|
|
520
|
+
streamScan?: boolean;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Image variant configuration for Sharp image processing
|
|
524
|
+
* @see SharpImagePlugin in @plyaz/storage/plugins
|
|
525
|
+
*/
|
|
526
|
+
export interface ImageVariant {
|
|
527
|
+
/** Variant name (thumbnail, medium, large, etc.) */
|
|
528
|
+
name: string;
|
|
529
|
+
/** Target width in pixels */
|
|
530
|
+
width?: number;
|
|
531
|
+
/** Target height in pixels */
|
|
532
|
+
height?: number;
|
|
533
|
+
/** Resize fit mode */
|
|
534
|
+
fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
|
|
535
|
+
/** Resize position (when fit is 'cover' or 'contain') */
|
|
536
|
+
position?: 'center' | 'top' | 'right top' | 'right' | 'right bottom' | 'bottom' | 'left bottom' | 'left' | 'left top';
|
|
537
|
+
/** Custom quality for this variant (overrides global quality) */
|
|
538
|
+
quality?: number;
|
|
539
|
+
/** Custom format for this variant */
|
|
540
|
+
format?: 'jpeg' | 'png' | 'webp' | 'avif';
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Watermark configuration for Sharp image processing
|
|
544
|
+
* @see SharpImagePlugin in @plyaz/storage/plugins
|
|
545
|
+
*/
|
|
546
|
+
export interface WatermarkConfig {
|
|
547
|
+
/** Enable watermarking */
|
|
548
|
+
enabled: boolean;
|
|
549
|
+
/** Path to watermark image file */
|
|
550
|
+
imagePath?: string;
|
|
551
|
+
/** Watermark image buffer (alternative to imagePath) */
|
|
552
|
+
imageBuffer?: globalThis.Buffer;
|
|
553
|
+
/** Watermark opacity (0-1) */
|
|
554
|
+
opacity?: number;
|
|
555
|
+
/** Watermark position */
|
|
556
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
|
|
557
|
+
/** Watermark size as percentage of image (default: 20%) */
|
|
558
|
+
size?: number;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Sharp Image Plugin configuration
|
|
562
|
+
* @see SharpImagePlugin in @plyaz/storage/plugins
|
|
563
|
+
*/
|
|
564
|
+
export interface SharpImagePluginConfig {
|
|
565
|
+
/** Image variants to generate */
|
|
566
|
+
variants?: ImageVariant[];
|
|
567
|
+
/** Output formats to generate (default: ['webp', 'jpeg']) */
|
|
568
|
+
formats?: Array<'jpeg' | 'png' | 'webp' | 'avif'>;
|
|
569
|
+
/** JPEG/WEBP quality (1-100, default: 85) */
|
|
570
|
+
quality?: number;
|
|
571
|
+
/** Strip metadata (EXIF) for privacy (default: true) */
|
|
572
|
+
stripMetadata?: boolean;
|
|
573
|
+
/** Watermark configuration */
|
|
574
|
+
watermark?: WatermarkConfig;
|
|
575
|
+
/** Only process these MIME types (default: all image/* types) */
|
|
576
|
+
supportedMimeTypes?: string[];
|
|
577
|
+
/** Upload variants back to storage (default: true) */
|
|
578
|
+
uploadVariants?: boolean;
|
|
579
|
+
/** Preserve original file (default: true) */
|
|
580
|
+
preserveOriginal?: boolean;
|
|
581
|
+
/** Plugin priority (1-100, lower runs first) */
|
|
582
|
+
priority?: number;
|
|
583
|
+
/** Plugin version */
|
|
584
|
+
version?: string;
|
|
585
|
+
/** Plugin description */
|
|
586
|
+
description?: string;
|
|
587
|
+
/** Whether the plugin is enabled */
|
|
588
|
+
enabled?: boolean;
|
|
589
|
+
/** Logger instance */
|
|
590
|
+
logger?: unknown;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Video resolution configuration for FFmpeg video processing
|
|
594
|
+
* @see FFmpegVideoPlugin in @plyaz/storage/plugins
|
|
595
|
+
*/
|
|
596
|
+
export interface VideoResolution {
|
|
597
|
+
/** Resolution name (480p, 720p, 1080p, 4k) */
|
|
598
|
+
name: string;
|
|
599
|
+
/** Target width in pixels */
|
|
600
|
+
width: number;
|
|
601
|
+
/** Target height in pixels */
|
|
602
|
+
height: number;
|
|
603
|
+
/** Video bitrate (e.g., '1000k', '2500k') */
|
|
604
|
+
bitrate: string;
|
|
605
|
+
/** Video codec (e.g., 'libx264', 'libx265') */
|
|
606
|
+
codec?: string;
|
|
607
|
+
/** Audio codec (e.g., 'aac', 'mp3') */
|
|
608
|
+
audioCodec?: string;
|
|
609
|
+
/** Audio bitrate (e.g., '128k') */
|
|
610
|
+
audioBitrate?: string;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Thumbnail generation configuration for FFmpeg video processing
|
|
614
|
+
* @see FFmpegVideoPlugin in @plyaz/storage/plugins
|
|
615
|
+
*/
|
|
616
|
+
export interface ThumbnailConfig {
|
|
617
|
+
/** Number of thumbnails to generate */
|
|
618
|
+
count: number;
|
|
619
|
+
/** Timestamps as percentage of duration (0-1) */
|
|
620
|
+
timestamps: number[];
|
|
621
|
+
/** Thumbnail format (jpeg, png) */
|
|
622
|
+
format?: 'jpeg' | 'png';
|
|
623
|
+
/** Thumbnail quality (1-100) */
|
|
624
|
+
quality?: number;
|
|
625
|
+
/** Thumbnail width (height auto-calculated) */
|
|
626
|
+
width?: number;
|
|
627
|
+
/** Thumbnail size (width x height) */
|
|
628
|
+
size?: {
|
|
629
|
+
width: number;
|
|
630
|
+
height: number;
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* HLS streaming configuration for FFmpeg video processing
|
|
635
|
+
* @see FFmpegVideoPlugin in @plyaz/storage/plugins
|
|
636
|
+
*/
|
|
637
|
+
export interface HLSConfig {
|
|
638
|
+
/** Enable HLS streaming */
|
|
639
|
+
enabled: boolean;
|
|
640
|
+
/** Segment duration in seconds */
|
|
641
|
+
segmentDuration?: number;
|
|
642
|
+
/** Variant bitrates for adaptive streaming */
|
|
643
|
+
variantBitrates?: string[];
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* FFmpeg Video Plugin configuration
|
|
647
|
+
* @see FFmpegVideoPlugin in @plyaz/storage/plugins
|
|
648
|
+
*/
|
|
649
|
+
export interface FFmpegVideoPluginConfig {
|
|
650
|
+
/** Path to ffmpeg binary */
|
|
651
|
+
ffmpegPath?: string;
|
|
652
|
+
/** Path to ffprobe binary */
|
|
653
|
+
ffprobePath?: string;
|
|
654
|
+
/** Video resolutions to generate */
|
|
655
|
+
resolutions?: VideoResolution[];
|
|
656
|
+
/** Thumbnail configuration */
|
|
657
|
+
thumbnails?: ThumbnailConfig;
|
|
658
|
+
/** HLS streaming configuration */
|
|
659
|
+
hls?: HLSConfig;
|
|
660
|
+
/** Process in background queue */
|
|
661
|
+
useQueue?: boolean;
|
|
662
|
+
/** Only process these MIME types */
|
|
663
|
+
supportedMimeTypes?: string[];
|
|
664
|
+
/** Upload variants back to storage */
|
|
665
|
+
uploadVariants?: boolean;
|
|
666
|
+
/** Plugin priority (1-100, lower runs first) */
|
|
667
|
+
priority?: number;
|
|
668
|
+
/** Plugin version */
|
|
669
|
+
version?: string;
|
|
670
|
+
/** Plugin description */
|
|
671
|
+
description?: string;
|
|
672
|
+
/** Whether the plugin is enabled */
|
|
673
|
+
enabled?: boolean;
|
|
674
|
+
/** Logger instance */
|
|
675
|
+
logger?: unknown;
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Extracted metadata structure
|
|
679
|
+
*/
|
|
680
|
+
export interface ExtractedMetadata {
|
|
681
|
+
/** File type category */
|
|
682
|
+
category: 'image' | 'audio' | 'video' | 'document' | 'other';
|
|
683
|
+
/** Image EXIF data */
|
|
684
|
+
exif?: {
|
|
685
|
+
make?: string;
|
|
686
|
+
model?: string;
|
|
687
|
+
software?: string;
|
|
688
|
+
dateTime?: string;
|
|
689
|
+
exposureTime?: number;
|
|
690
|
+
fNumber?: number;
|
|
691
|
+
iso?: number;
|
|
692
|
+
focalLength?: number;
|
|
693
|
+
flash?: number;
|
|
694
|
+
whiteBalance?: number;
|
|
695
|
+
orientation?: number;
|
|
696
|
+
xResolution?: number;
|
|
697
|
+
yResolution?: number;
|
|
698
|
+
resolutionUnit?: number;
|
|
699
|
+
gps?: {
|
|
700
|
+
latitude?: number;
|
|
701
|
+
longitude?: number;
|
|
702
|
+
altitude?: number;
|
|
703
|
+
};
|
|
704
|
+
};
|
|
705
|
+
/** Audio ID3 tags */
|
|
706
|
+
id3?: {
|
|
707
|
+
title?: string;
|
|
708
|
+
artist?: string;
|
|
709
|
+
album?: string;
|
|
710
|
+
year?: number;
|
|
711
|
+
genre?: string;
|
|
712
|
+
trackNumber?: number;
|
|
713
|
+
albumArtist?: string;
|
|
714
|
+
composer?: string;
|
|
715
|
+
duration?: number;
|
|
716
|
+
bitrate?: number;
|
|
717
|
+
sampleRate?: number;
|
|
718
|
+
codec?: string;
|
|
719
|
+
};
|
|
720
|
+
/** Video metadata */
|
|
721
|
+
video?: {
|
|
722
|
+
duration?: number;
|
|
723
|
+
width?: number;
|
|
724
|
+
height?: number;
|
|
725
|
+
codec?: string;
|
|
726
|
+
bitrate?: number;
|
|
727
|
+
fps?: number;
|
|
728
|
+
audioCodec?: string;
|
|
729
|
+
format?: string;
|
|
730
|
+
};
|
|
731
|
+
/** Document metadata */
|
|
732
|
+
document?: {
|
|
733
|
+
title?: string;
|
|
734
|
+
author?: string;
|
|
735
|
+
subject?: string;
|
|
736
|
+
creator?: string;
|
|
737
|
+
producer?: string;
|
|
738
|
+
creationDate?: string;
|
|
739
|
+
modificationDate?: string;
|
|
740
|
+
pageCount?: number;
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Metadata Extraction Plugin configuration
|
|
745
|
+
*/
|
|
746
|
+
export interface MetadataExtractionPluginConfig {
|
|
747
|
+
/** Extract EXIF data from images */
|
|
748
|
+
extractExif?: boolean;
|
|
749
|
+
/** Extract ID3 tags from audio files */
|
|
750
|
+
extractId3?: boolean;
|
|
751
|
+
/** Extract metadata from videos */
|
|
752
|
+
extractVideoMeta?: boolean;
|
|
753
|
+
/** Extract metadata from documents */
|
|
754
|
+
extractDocMeta?: boolean;
|
|
755
|
+
/** Strip sensitive data (GPS, serial numbers) */
|
|
756
|
+
stripSensitiveData?: boolean;
|
|
757
|
+
/** Preserve original metadata in files */
|
|
758
|
+
preserveOriginal?: boolean;
|
|
759
|
+
/** Supported file mime types */
|
|
760
|
+
supportedMimeTypes?: string[];
|
|
761
|
+
priority?: number;
|
|
762
|
+
version?: string;
|
|
763
|
+
description?: string;
|
|
764
|
+
enabled?: boolean;
|
|
765
|
+
logger?: unknown;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* CDN Provider Types
|
|
769
|
+
*/
|
|
770
|
+
export type CDNProviderType = 'cloudflare' | 'cloudfront' | 'fastly';
|
|
771
|
+
/**
|
|
772
|
+
* Base CDN Provider Configuration
|
|
773
|
+
*/
|
|
774
|
+
export interface BaseCDNProviderConfig {
|
|
775
|
+
/** CDN provider type */
|
|
776
|
+
type: CDNProviderType;
|
|
777
|
+
/** Base URL pattern for generating cache URLs */
|
|
778
|
+
baseUrl?: string;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Cloudflare CDN Configuration
|
|
782
|
+
*/
|
|
783
|
+
export interface CloudflareCDNConfig extends BaseCDNProviderConfig {
|
|
784
|
+
type: 'cloudflare';
|
|
785
|
+
/** Cloudflare Zone ID */
|
|
786
|
+
zoneId: string;
|
|
787
|
+
/** Cloudflare API Token */
|
|
788
|
+
apiToken: string;
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* AWS CloudFront Configuration
|
|
792
|
+
*/
|
|
793
|
+
export interface CloudFrontCDNConfig extends BaseCDNProviderConfig {
|
|
794
|
+
type: 'cloudfront';
|
|
795
|
+
/** CloudFront Distribution ID */
|
|
796
|
+
distributionId: string;
|
|
797
|
+
/** AWS Access Key ID */
|
|
798
|
+
accessKeyId: string;
|
|
799
|
+
/** AWS Secret Access Key */
|
|
800
|
+
secretAccessKey: string;
|
|
801
|
+
/** AWS Region */
|
|
802
|
+
region?: string;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Fastly CDN Configuration
|
|
806
|
+
*/
|
|
807
|
+
export interface FastlyCDNConfig extends BaseCDNProviderConfig {
|
|
808
|
+
type: 'fastly';
|
|
809
|
+
/** Fastly Service ID */
|
|
810
|
+
serviceId: string;
|
|
811
|
+
/** Fastly API Key */
|
|
812
|
+
apiKey: string;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* CDN Provider Configuration Union
|
|
816
|
+
*/
|
|
817
|
+
export type CDNProviderConfig = CloudflareCDNConfig | CloudFrontCDNConfig | FastlyCDNConfig;
|
|
818
|
+
/**
|
|
819
|
+
* CDN Invalidation Plugin Configuration
|
|
820
|
+
*/
|
|
821
|
+
export interface CDNInvalidationPluginConfig {
|
|
822
|
+
/** CDN provider configurations */
|
|
823
|
+
providers: CDNProviderConfig[];
|
|
824
|
+
/** Maximum URLs per invalidation request */
|
|
825
|
+
batchSize?: number;
|
|
826
|
+
/** Number of retry attempts on failure */
|
|
827
|
+
retryAttempts?: number;
|
|
828
|
+
/** Retry delay in milliseconds */
|
|
829
|
+
retryDelay?: number;
|
|
830
|
+
/** Enable invalidation on delete */
|
|
831
|
+
invalidateOnDelete?: boolean;
|
|
832
|
+
/** Enable invalidation on update */
|
|
833
|
+
invalidateOnUpdate?: boolean;
|
|
834
|
+
/** URL pattern generator function */
|
|
835
|
+
urlGenerator?: (fileId: string, filename: string) => string[];
|
|
836
|
+
priority?: number;
|
|
837
|
+
version?: string;
|
|
838
|
+
description?: string;
|
|
839
|
+
enabled?: boolean;
|
|
840
|
+
logger?: unknown;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Cloudflare CDN Plugin Configuration
|
|
844
|
+
*/
|
|
845
|
+
export interface CloudflareCDNPluginConfig {
|
|
846
|
+
/** Cloudflare Zone ID */
|
|
847
|
+
zoneId: string;
|
|
848
|
+
/** Cloudflare API Token with Cache Purge permission */
|
|
849
|
+
apiToken: string;
|
|
850
|
+
/** Base URL for CDN (optional) */
|
|
851
|
+
baseUrl?: string;
|
|
852
|
+
/** Maximum URLs per purge request (default: 30) */
|
|
853
|
+
batchSize?: number;
|
|
854
|
+
/** Number of retry attempts on failure (default: 3) */
|
|
855
|
+
retryAttempts?: number;
|
|
856
|
+
/** Retry delay in milliseconds (default: 1000) */
|
|
857
|
+
retryDelay?: number;
|
|
858
|
+
/** Enable invalidation on delete (default: true) */
|
|
859
|
+
invalidateOnDelete?: boolean;
|
|
860
|
+
/** Enable invalidation on update (default: true) */
|
|
861
|
+
invalidateOnUpdate?: boolean;
|
|
862
|
+
/** URL generator function */
|
|
863
|
+
urlGenerator?: (fileId: string, filename: string) => string[];
|
|
864
|
+
priority?: number;
|
|
865
|
+
version?: string;
|
|
866
|
+
description?: string;
|
|
867
|
+
enabled?: boolean;
|
|
868
|
+
logger?: unknown;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* CloudFront CDN Plugin Configuration
|
|
872
|
+
*/
|
|
873
|
+
export interface CloudFrontCDNPluginConfig {
|
|
874
|
+
/** CloudFront Distribution ID */
|
|
875
|
+
distributionId: string;
|
|
876
|
+
/** AWS Access Key ID */
|
|
877
|
+
accessKeyId: string;
|
|
878
|
+
/** AWS Secret Access Key */
|
|
879
|
+
secretAccessKey: string;
|
|
880
|
+
/** AWS Region (default: us-east-1) */
|
|
881
|
+
region?: string;
|
|
882
|
+
/** Base URL for CDN (optional) */
|
|
883
|
+
baseUrl?: string;
|
|
884
|
+
/** Maximum paths per invalidation (default: 1000) */
|
|
885
|
+
batchSize?: number;
|
|
886
|
+
/** Number of retry attempts on failure (default: 3) */
|
|
887
|
+
retryAttempts?: number;
|
|
888
|
+
/** Retry delay in milliseconds (default: 1000) */
|
|
889
|
+
retryDelay?: number;
|
|
890
|
+
/** Enable invalidation on delete (default: true) */
|
|
891
|
+
invalidateOnDelete?: boolean;
|
|
892
|
+
/** Enable invalidation on update (default: true) */
|
|
893
|
+
invalidateOnUpdate?: boolean;
|
|
894
|
+
/** Path generator function */
|
|
895
|
+
pathGenerator?: (fileId: string, filename: string) => string[];
|
|
896
|
+
priority?: number;
|
|
897
|
+
version?: string;
|
|
898
|
+
description?: string;
|
|
899
|
+
enabled?: boolean;
|
|
900
|
+
logger?: unknown;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Fastly CDN Plugin Configuration
|
|
904
|
+
*/
|
|
905
|
+
export interface FastlyCDNPluginConfig {
|
|
906
|
+
/** Fastly Service ID */
|
|
907
|
+
serviceId: string;
|
|
908
|
+
/** Fastly API Token with Purge permission */
|
|
909
|
+
apiToken: string;
|
|
910
|
+
/** Base URL for CDN (optional) */
|
|
911
|
+
baseUrl?: string;
|
|
912
|
+
/** Number of retry attempts on failure (default: 3) */
|
|
913
|
+
retryAttempts?: number;
|
|
914
|
+
/** Retry delay in milliseconds (default: 1000) */
|
|
915
|
+
retryDelay?: number;
|
|
916
|
+
/** Enable invalidation on delete (default: true) */
|
|
917
|
+
invalidateOnDelete?: boolean;
|
|
918
|
+
/** Enable invalidation on update (default: true) */
|
|
919
|
+
invalidateOnUpdate?: boolean;
|
|
920
|
+
/** URL generator function */
|
|
921
|
+
urlGenerator?: (fileId: string, filename: string) => string[];
|
|
922
|
+
priority?: number;
|
|
923
|
+
version?: string;
|
|
924
|
+
description?: string;
|
|
925
|
+
enabled?: boolean;
|
|
926
|
+
logger?: unknown;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* CDN Invalidation Result
|
|
930
|
+
*/
|
|
931
|
+
export interface CDNInvalidationResult {
|
|
932
|
+
/** CDN provider type */
|
|
933
|
+
provider: CDNProviderType;
|
|
934
|
+
/** Whether invalidation was successful */
|
|
935
|
+
success: boolean;
|
|
936
|
+
/** URLs that were invalidated */
|
|
937
|
+
urls: string[];
|
|
938
|
+
/** Error message if failed */
|
|
939
|
+
error?: string;
|
|
940
|
+
/** Invalidation ID from CDN provider */
|
|
941
|
+
invalidationId?: string;
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* CDN Plugin Statistics
|
|
945
|
+
* Statistics for CDN invalidation operations
|
|
946
|
+
*/
|
|
947
|
+
export interface StorageCDNPluginStatistics {
|
|
948
|
+
/** Total number of successful invalidations performed */
|
|
949
|
+
invalidationsPerformed: number;
|
|
950
|
+
/** Total number of failed invalidations */
|
|
951
|
+
invalidationsFailed: number;
|
|
952
|
+
/** Total number of URLs/paths invalidated (use one or both depending on CDN) */
|
|
953
|
+
urlsInvalidated?: number;
|
|
954
|
+
pathsInvalidated?: number;
|
|
955
|
+
/** Number of queued URLs/paths waiting to be invalidated (use one or both depending on CDN) */
|
|
956
|
+
queuedUrls?: number;
|
|
957
|
+
queuedPaths?: number;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Image Processing Plugin Statistics
|
|
961
|
+
* Statistics for image processing operations
|
|
962
|
+
*/
|
|
963
|
+
export interface StorageImageProcessingPluginStatistics {
|
|
964
|
+
/** Total number of images processed */
|
|
965
|
+
imagesProcessed: number;
|
|
966
|
+
/** Total number of variants generated */
|
|
967
|
+
variantsGenerated: number;
|
|
968
|
+
/** Average number of variants generated per image */
|
|
969
|
+
averageVariantsPerImage: number;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Metadata Extraction Plugin Statistics
|
|
973
|
+
* Statistics for metadata extraction operations
|
|
974
|
+
*/
|
|
975
|
+
export interface StorageMetadataExtractionPluginStatistics {
|
|
976
|
+
/** Total number of files with metadata extracted */
|
|
977
|
+
filesProcessed: number;
|
|
978
|
+
/** Success rate as a percentage (0-100) */
|
|
979
|
+
successRate: number;
|
|
980
|
+
metadataExtracted?: number;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Video Processing Plugin Statistics
|
|
984
|
+
* Statistics for video processing operations
|
|
985
|
+
*/
|
|
986
|
+
export interface StorageVideoProcessingPluginStatistics {
|
|
987
|
+
/** Total number of videos processed */
|
|
988
|
+
videosProcessed: number;
|
|
989
|
+
/** Total number of thumbnails generated */
|
|
990
|
+
thumbnailsGenerated?: number;
|
|
991
|
+
/** Average thumbnails per video */
|
|
992
|
+
averageThumbnailsPerVideo?: number;
|
|
993
|
+
/** Total number of variants generated */
|
|
994
|
+
variantsGenerated: number;
|
|
995
|
+
averageVariantsPerVideo?: number;
|
|
996
|
+
}
|