alepha 0.13.0 → 0.13.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/dist/api-jobs/index.d.ts +26 -26
- package/dist/api-users/index.d.ts +1 -1
- package/dist/cli/{dist-Sz2EXvQX.cjs → dist-Dl9Vl7Ur.js} +17 -13
- package/dist/cli/{dist-BBPjuQ56.js.map → dist-Dl9Vl7Ur.js.map} +1 -1
- package/dist/cli/index.d.ts +3 -11
- package/dist/cli/index.js +106 -74
- package/dist/cli/index.js.map +1 -1
- package/dist/email/index.js +71 -73
- package/dist/email/index.js.map +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/index.d.ts +4 -4
- package/dist/retry/index.d.ts +1 -1
- package/dist/retry/index.js +2 -2
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +6 -6
- package/dist/security/index.d.ts +28 -28
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server-health/index.d.ts +17 -17
- package/dist/server-metrics/index.js +170 -174
- package/dist/server-metrics/index.js.map +1 -1
- package/dist/server-security/index.d.ts +9 -9
- package/dist/vite/index.js +4 -5
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/package.json +52 -103
- package/src/cli/apps/AlephaPackageBuilderCli.ts +7 -2
- package/src/cli/assets/appRouterTs.ts +9 -0
- package/src/cli/assets/indexHtml.ts +2 -1
- package/src/cli/assets/mainBrowserTs.ts +10 -0
- package/src/cli/commands/CoreCommands.ts +6 -5
- package/src/cli/commands/DrizzleCommands.ts +65 -57
- package/src/cli/commands/VerifyCommands.ts +1 -1
- package/src/cli/services/ProjectUtils.ts +44 -38
- package/src/orm/providers/DrizzleKitProvider.ts +1 -1
- package/src/retry/descriptors/$retry.ts +5 -3
- package/src/server/providers/NodeHttpServerProvider.ts +1 -1
- package/src/vite/helpers/boot.ts +3 -3
- package/dist/api-files/index.cjs +0 -1293
- package/dist/api-files/index.cjs.map +0 -1
- package/dist/api-files/index.d.cts +0 -829
- package/dist/api-jobs/index.cjs +0 -274
- package/dist/api-jobs/index.cjs.map +0 -1
- package/dist/api-jobs/index.d.cts +0 -654
- package/dist/api-notifications/index.cjs +0 -380
- package/dist/api-notifications/index.cjs.map +0 -1
- package/dist/api-notifications/index.d.cts +0 -289
- package/dist/api-parameters/index.cjs +0 -66
- package/dist/api-parameters/index.cjs.map +0 -1
- package/dist/api-parameters/index.d.cts +0 -84
- package/dist/api-users/index.cjs +0 -6009
- package/dist/api-users/index.cjs.map +0 -1
- package/dist/api-users/index.d.cts +0 -4740
- package/dist/api-verifications/index.cjs +0 -407
- package/dist/api-verifications/index.cjs.map +0 -1
- package/dist/api-verifications/index.d.cts +0 -207
- package/dist/batch/index.cjs +0 -408
- package/dist/batch/index.cjs.map +0 -1
- package/dist/batch/index.d.cts +0 -330
- package/dist/bin/index.cjs +0 -17
- package/dist/bin/index.cjs.map +0 -1
- package/dist/bin/index.d.cts +0 -1
- package/dist/bucket/index.cjs +0 -303
- package/dist/bucket/index.cjs.map +0 -1
- package/dist/bucket/index.d.cts +0 -355
- package/dist/cache/index.cjs +0 -241
- package/dist/cache/index.cjs.map +0 -1
- package/dist/cache/index.d.cts +0 -202
- package/dist/cache-redis/index.cjs +0 -84
- package/dist/cache-redis/index.cjs.map +0 -1
- package/dist/cache-redis/index.d.cts +0 -40
- package/dist/cli/chunk-DSlc6foC.cjs +0 -43
- package/dist/cli/dist-BBPjuQ56.js +0 -2778
- package/dist/cli/dist-Sz2EXvQX.cjs.map +0 -1
- package/dist/cli/index.cjs +0 -1241
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.d.cts +0 -422
- package/dist/command/index.cjs +0 -693
- package/dist/command/index.cjs.map +0 -1
- package/dist/command/index.d.cts +0 -340
- package/dist/core/index.cjs +0 -2264
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -1927
- package/dist/datetime/index.cjs +0 -318
- package/dist/datetime/index.cjs.map +0 -1
- package/dist/datetime/index.d.cts +0 -145
- package/dist/email/index.cjs +0 -10874
- package/dist/email/index.cjs.map +0 -1
- package/dist/email/index.d.cts +0 -186
- package/dist/fake/index.cjs +0 -34641
- package/dist/fake/index.cjs.map +0 -1
- package/dist/fake/index.d.cts +0 -74
- package/dist/file/index.cjs +0 -1212
- package/dist/file/index.cjs.map +0 -1
- package/dist/file/index.d.cts +0 -698
- package/dist/lock/index.cjs +0 -226
- package/dist/lock/index.cjs.map +0 -1
- package/dist/lock/index.d.cts +0 -361
- package/dist/lock-redis/index.cjs +0 -113
- package/dist/lock-redis/index.cjs.map +0 -1
- package/dist/lock-redis/index.d.cts +0 -24
- package/dist/logger/index.cjs +0 -521
- package/dist/logger/index.cjs.map +0 -1
- package/dist/logger/index.d.cts +0 -281
- package/dist/orm/index.cjs +0 -2986
- package/dist/orm/index.cjs.map +0 -1
- package/dist/orm/index.d.cts +0 -2213
- package/dist/queue/index.cjs +0 -1044
- package/dist/queue/index.cjs.map +0 -1
- package/dist/queue/index.d.cts +0 -1265
- package/dist/queue-redis/index.cjs +0 -873
- package/dist/queue-redis/index.cjs.map +0 -1
- package/dist/queue-redis/index.d.cts +0 -82
- package/dist/redis/index.cjs +0 -153
- package/dist/redis/index.cjs.map +0 -1
- package/dist/redis/index.d.cts +0 -82
- package/dist/retry/index.cjs +0 -146
- package/dist/retry/index.cjs.map +0 -1
- package/dist/retry/index.d.cts +0 -172
- package/dist/router/index.cjs +0 -111
- package/dist/router/index.cjs.map +0 -1
- package/dist/router/index.d.cts +0 -46
- package/dist/scheduler/index.cjs +0 -576
- package/dist/scheduler/index.cjs.map +0 -1
- package/dist/scheduler/index.d.cts +0 -145
- package/dist/security/index.cjs +0 -2402
- package/dist/security/index.cjs.map +0 -1
- package/dist/security/index.d.cts +0 -598
- package/dist/server/index.cjs +0 -1680
- package/dist/server/index.cjs.map +0 -1
- package/dist/server/index.d.cts +0 -810
- package/dist/server-auth/index.cjs +0 -3146
- package/dist/server-auth/index.cjs.map +0 -1
- package/dist/server-auth/index.d.cts +0 -1164
- package/dist/server-cache/index.cjs +0 -252
- package/dist/server-cache/index.cjs.map +0 -1
- package/dist/server-cache/index.d.cts +0 -164
- package/dist/server-compress/index.cjs +0 -141
- package/dist/server-compress/index.cjs.map +0 -1
- package/dist/server-compress/index.d.cts +0 -38
- package/dist/server-cookies/index.cjs +0 -234
- package/dist/server-cookies/index.cjs.map +0 -1
- package/dist/server-cookies/index.d.cts +0 -144
- package/dist/server-cors/index.cjs +0 -201
- package/dist/server-cors/index.cjs.map +0 -1
- package/dist/server-cors/index.d.cts +0 -140
- package/dist/server-health/index.cjs +0 -62
- package/dist/server-health/index.cjs.map +0 -1
- package/dist/server-health/index.d.cts +0 -58
- package/dist/server-helmet/index.cjs +0 -131
- package/dist/server-helmet/index.cjs.map +0 -1
- package/dist/server-helmet/index.d.cts +0 -97
- package/dist/server-links/index.cjs +0 -992
- package/dist/server-links/index.cjs.map +0 -1
- package/dist/server-links/index.d.cts +0 -513
- package/dist/server-metrics/index.cjs +0 -4535
- package/dist/server-metrics/index.cjs.map +0 -1
- package/dist/server-metrics/index.d.cts +0 -35
- package/dist/server-multipart/index.cjs +0 -237
- package/dist/server-multipart/index.cjs.map +0 -1
- package/dist/server-multipart/index.d.cts +0 -50
- package/dist/server-proxy/index.cjs +0 -186
- package/dist/server-proxy/index.cjs.map +0 -1
- package/dist/server-proxy/index.d.cts +0 -234
- package/dist/server-rate-limit/index.cjs +0 -241
- package/dist/server-rate-limit/index.cjs.map +0 -1
- package/dist/server-rate-limit/index.d.cts +0 -183
- package/dist/server-security/index.cjs +0 -316
- package/dist/server-security/index.cjs.map +0 -1
- package/dist/server-security/index.d.cts +0 -173
- package/dist/server-static/index.cjs +0 -170
- package/dist/server-static/index.cjs.map +0 -1
- package/dist/server-static/index.d.cts +0 -121
- package/dist/server-swagger/index.cjs +0 -1021
- package/dist/server-swagger/index.cjs.map +0 -1
- package/dist/server-swagger/index.d.cts +0 -382
- package/dist/sms/index.cjs +0 -221
- package/dist/sms/index.cjs.map +0 -1
- package/dist/sms/index.d.cts +0 -130
- package/dist/thread/index.cjs +0 -350
- package/dist/thread/index.cjs.map +0 -1
- package/dist/thread/index.d.cts +0 -260
- package/dist/topic/index.cjs +0 -282
- package/dist/topic/index.cjs.map +0 -1
- package/dist/topic/index.d.cts +0 -523
- package/dist/topic-redis/index.cjs +0 -71
- package/dist/topic-redis/index.cjs.map +0 -1
- package/dist/topic-redis/index.d.cts +0 -42
- package/dist/vite/index.cjs +0 -1077
- package/dist/vite/index.cjs.map +0 -1
- package/dist/vite/index.d.cts +0 -542
- package/dist/websocket/index.cjs +0 -1117
- package/dist/websocket/index.cjs.map +0 -1
- package/dist/websocket/index.d.cts +0 -861
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["AlephaError","FileSystemProvider","FileDetector","Descriptor","FileSystemProvider","KIND","t","Alepha","FileDetector","FileSystemProvider","AlephaError","alepha"],"sources":["../../src/bucket/errors/InvalidFileError.ts","../../src/bucket/providers/FileStorageProvider.ts","../../src/bucket/errors/FileNotFoundError.ts","../../src/bucket/providers/MemoryFileStorageProvider.ts","../../src/bucket/descriptors/$bucket.ts","../../src/bucket/providers/LocalFileStorageProvider.ts","../../src/bucket/index.ts"],"sourcesContent":["export class InvalidFileError extends Error {\n public readonly status = 400;\n}\n","import type { FileLike } from \"alepha\";\n\nexport abstract class FileStorageProvider {\n /**\n * Uploads a file to the storage.\n *\n * @param bucketName - Container name\n * @param file - File to upload\n * @param fileId - Optional file identifier. If not provided, a unique ID will be generated.\n * @return The identifier of the uploaded file.\n */\n abstract upload(\n bucketName: string,\n file: FileLike,\n fileId?: string,\n ): Promise<string>;\n\n /**\n * Downloads a file from the storage.\n *\n * @param bucketName - Container name\n * @param fileId - Identifier of the file to download\n * @return The downloaded file as a FileLike object.\n */\n abstract download(bucketName: string, fileId: string): Promise<FileLike>;\n\n /**\n * Check if fileId exists in the storage bucket.\n *\n * @param bucketName - Container name\n * @param fileId - Identifier of the file to stream\n * @return True is the file exists, false otherwise.\n */\n abstract exists(bucketName: string, fileId: string): Promise<boolean>;\n\n /**\n * Delete permanently a file from the storage.\n *\n * @param bucketName - Container name\n * @param fileId - Identifier of the file to delete\n */\n abstract delete(bucketName: string, fileId: string): Promise<void>;\n}\n","import { AlephaError } from \"alepha\";\n\nexport class FileNotFoundError extends AlephaError {\n public readonly status = 404;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { $inject, type FileLike } from \"alepha\";\nimport { FileDetector, FileSystemProvider } from \"alepha/file\";\nimport { FileNotFoundError } from \"../errors/FileNotFoundError.ts\";\nimport type { FileStorageProvider } from \"./FileStorageProvider.ts\";\n\nexport class MemoryFileStorageProvider implements FileStorageProvider {\n public readonly files: Record<string, FileLike> = {};\n protected readonly fileSystem = $inject(FileSystemProvider);\n protected readonly fileDetector = $inject(FileDetector);\n\n public async upload(\n bucketName: string,\n file: FileLike,\n fileId?: string,\n ): Promise<string> {\n fileId ??= this.createId();\n\n this.files[`${bucketName}/${fileId}`] = this.fileSystem.createFile({\n stream: file.stream(),\n name: file.name,\n type: file.type,\n size: file.size,\n });\n\n return fileId;\n }\n\n public async download(bucketName: string, fileId: string): Promise<FileLike> {\n const fileKey = `${bucketName}/${fileId}`;\n const file = this.files[fileKey];\n\n if (!file) {\n throw new FileNotFoundError(`File with ID ${fileId} not found.`);\n }\n\n return file;\n }\n\n public async exists(bucketName: string, fileId: string): Promise<boolean> {\n return `${bucketName}/${fileId}` in this.files;\n }\n\n public async delete(bucketName: string, fileId: string): Promise<void> {\n const fileKey = `${bucketName}/${fileId}`;\n if (!(fileKey in this.files)) {\n throw new FileNotFoundError(`File with ID ${fileId} not found.`);\n }\n\n delete this.files[fileKey];\n }\n\n protected createId(): string {\n return randomUUID();\n }\n}\n","import {\n $inject,\n createDescriptor,\n Descriptor,\n type FileLike,\n KIND,\n type Service,\n} from \"alepha\";\nimport { FileSystemProvider } from \"alepha/file\";\nimport { InvalidFileError } from \"../errors/InvalidFileError.ts\";\nimport { FileStorageProvider } from \"../providers/FileStorageProvider.ts\";\nimport { MemoryFileStorageProvider } from \"../providers/MemoryFileStorageProvider.ts\";\n\n/**\n * Creates a bucket descriptor for file storage and management with configurable validation.\n *\n * Provides a comprehensive file storage system that handles uploads, downloads, validation,\n * and management across multiple storage backends with MIME type and size limit controls.\n *\n * **Key Features**\n * - Multi-provider support (filesystem, cloud storage, in-memory)\n * - Automatic MIME type and file size validation\n * - Event integration for file operations monitoring\n * - Flexible per-bucket and per-operation configuration\n * - Smart file type and size detection\n *\n * **Common Use Cases**\n * - User profile pictures and document uploads\n * - Product images and media management\n * - Document storage and retrieval systems\n *\n * @example\n * ```ts\n * class MediaService {\n * images = $bucket({\n * name: \"user-images\",\n * mimeTypes: [\"image/jpeg\", \"image/png\", \"image/gif\"],\n * maxSize: 5 // 5MB limit\n * });\n *\n * documents = $bucket({\n * name: \"documents\",\n * mimeTypes: [\"application/pdf\", \"text/plain\"],\n * maxSize: 50 // 50MB limit\n * });\n *\n * async uploadProfileImage(file: FileLike, userId: string): Promise<string> {\n * const fileId = await this.images.upload(file);\n * await this.userService.updateProfileImage(userId, fileId);\n * return fileId;\n * }\n *\n * async downloadDocument(documentId: string): Promise<FileLike> {\n * return await this.documents.download(documentId);\n * }\n *\n * async deleteDocument(documentId: string): Promise<void> {\n * await this.documents.delete(documentId);\n * }\n * }\n * ```\n */\nexport const $bucket = (options: BucketDescriptorOptions) =>\n createDescriptor(BucketDescriptor, options);\n\nexport interface BucketDescriptorOptions extends BucketFileOptions {\n /**\n * File storage provider configuration for the bucket.\n *\n * Options:\n * - **\"memory\"**: In-memory storage (default for development, lost on restart)\n * - **Service<FileStorageProvider>**: Custom provider class (e.g., S3FileStorageProvider, AzureBlobProvider)\n * - **undefined**: Uses the default file storage provider from dependency injection\n *\n * **Provider Selection Guidelines**:\n * - **Development**: Use \"memory\" for fast, simple testing without external dependencies\n * - **Production**: Use cloud providers (S3, Azure Blob, Google Cloud Storage) for scalability\n * - **Local deployment**: Use filesystem providers for on-premise installations\n * - **Hybrid**: Use different providers for different bucket types (temp files vs permanent storage)\n *\n * **Provider Capabilities**:\n * - File persistence and durability guarantees\n * - Scalability and performance characteristics\n * - Geographic distribution and CDN integration\n * - Cost implications for storage and bandwidth\n * - Backup and disaster recovery features\n *\n * @default Uses injected FileStorageProvider\n * @example \"memory\"\n * @example S3FileStorageProvider\n * @example AzureBlobStorageProvider\n */\n provider?: Service<FileStorageProvider> | \"memory\";\n\n /**\n * Unique name identifier for the bucket.\n *\n * This name is used for:\n * - Storage backend organization and partitioning\n * - File path generation and URL construction\n * - Logging, monitoring, and debugging\n * - Access control and permissions management\n * - Backup and replication configuration\n *\n * **Naming Conventions**:\n * - Use lowercase with hyphens for consistency\n * - Include purpose or content type in the name\n * - Avoid spaces and special characters\n * - Consider environment prefixes for deployment isolation\n *\n * If not provided, defaults to the property key where the bucket is declared.\n *\n * @example \"user-avatars\"\n * @example \"product-images\"\n * @example \"legal-documents\"\n * @example \"temp-processing-files\"\n */\n name?: string;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface BucketFileOptions {\n /**\n * Human-readable description of the bucket's purpose and contents.\n *\n * Used for:\n * - Documentation generation and API references\n * - Developer onboarding and system understanding\n * - Monitoring dashboards and admin interfaces\n * - Compliance and audit documentation\n *\n * **Description Best Practices**:\n * - Explain what types of files this bucket stores\n * - Mention any special handling or processing requirements\n * - Include information about retention policies if applicable\n * - Note any compliance or security considerations\n *\n * @example \"User profile pictures and avatar images\"\n * @example \"Product catalog images with automated thumbnail generation\"\n * @example \"Legal documents requiring long-term retention\"\n * @example \"Temporary files for data processing workflows\"\n */\n description?: string;\n\n /**\n * Array of allowed MIME types for files uploaded to this bucket.\n *\n * When specified, only files with these exact MIME types will be accepted.\n * Files with disallowed MIME types will be rejected with an InvalidFileError.\n *\n * **MIME Type Categories**:\n * - Images: \"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\", \"image/svg+xml\"\n * - Documents: \"application/pdf\", \"text/plain\", \"text/csv\"\n * - Office: \"application/msword\", \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"\n * - Archives: \"application/zip\", \"application/x-tar\", \"application/gzip\"\n * - Media: \"video/mp4\", \"audio/mpeg\", \"audio/wav\"\n *\n * **Security Considerations**:\n * - Always validate MIME types for user uploads\n * - Be cautious with executable file types\n * - Consider using allow-lists rather than deny-lists\n * - Remember that MIME types can be spoofed by malicious users\n *\n * If not specified, all MIME types are allowed (not recommended for user uploads).\n *\n * @example [\"image/jpeg\", \"image/png\"] // Only JPEG and PNG images\n * @example [\"application/pdf\", \"text/plain\"] // Documents only\n * @example [\"video/mp4\", \"video/webm\"] // Video files\n */\n mimeTypes?: string[];\n\n /**\n * Maximum file size allowed in megabytes (MB).\n *\n * Files larger than this limit will be rejected with an InvalidFileError.\n * This helps prevent:\n * - Storage quota exhaustion\n * - Memory issues during file processing\n * - Long upload times and timeouts\n * - Abuse of storage resources\n *\n * **Size Guidelines by File Type**:\n * - Profile images: 1-5 MB\n * - Product photos: 5-10 MB\n * - Documents: 10-50 MB\n * - Video files: 50-500 MB\n * - Data files: 100-1000 MB\n *\n * **Considerations**:\n * - Consider your storage costs and limits\n * - Factor in network upload speeds for users\n * - Account for processing requirements (thumbnails, compression)\n * - Set reasonable limits based on actual use cases\n *\n * @default 10 MB\n *\n * @example 1 // 1MB for small images\n * @example 25 // 25MB for documents\n * @example 100 // 100MB for media files\n */\n maxSize?: number;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class BucketDescriptor extends Descriptor<BucketDescriptorOptions> {\n public readonly provider = this.$provider();\n private readonly fileSystem = $inject(FileSystemProvider);\n\n public get name() {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n /**\n * Uploads a file to the bucket.\n */\n public async upload(\n file: FileLike,\n options?: BucketFileOptions,\n ): Promise<string> {\n if (file instanceof File) {\n // our createFile is smarter than the browser's File constructor\n // by doing this, we can guess the MIME type and size!\n file = this.fileSystem.createFile({ file });\n }\n\n options = {\n ...this.options,\n ...options,\n };\n\n const mimeTypes = options.mimeTypes ?? undefined;\n const maxSize = options.maxSize ?? 10; // Default to 10 MB if not specified\n\n if (mimeTypes) {\n const mimeType = file.type || \"application/octet-stream\";\n if (!mimeTypes.includes(mimeType)) {\n throw new InvalidFileError(\n `MIME type ${mimeType} is not allowed in bucket ${this.name}`,\n );\n }\n }\n\n // check size in bytes, convert MB to bytes\n if (file.size > maxSize * 1024 * 1024) {\n throw new InvalidFileError(\n `File size ${file.size} exceeds the maximum size of ${this.options.maxSize} MB in bucket ${this.name}`,\n );\n }\n\n const id = await this.provider.upload(this.name, file);\n\n await this.alepha.events.emit(\"bucket:file:uploaded\", {\n id,\n bucket: this,\n file,\n options,\n });\n\n return id;\n }\n\n /**\n * Delete permanently a file from the bucket.\n */\n public async delete(fileId: string, skipHook = false): Promise<void> {\n await this.provider.delete(this.name, fileId);\n\n if (skipHook) {\n return;\n }\n\n await this.alepha.events.emit(\"bucket:file:deleted\", {\n id: fileId,\n bucket: this,\n });\n }\n\n /**\n * Checks if a file exists in the bucket.\n */\n public async exists(fileId: string): Promise<boolean> {\n return this.provider.exists(this.name, fileId);\n }\n\n /**\n * Downloads a file from the bucket.\n */\n public async download(fileId: string): Promise<FileLike> {\n return this.provider.download(this.name, fileId);\n }\n\n protected $provider() {\n if (!this.options.provider) {\n return this.alepha.inject(FileStorageProvider);\n }\n if (this.options.provider === \"memory\") {\n return this.alepha.inject(MemoryFileStorageProvider);\n }\n return this.alepha.inject(this.options.provider);\n }\n}\n\n$bucket[KIND] = BucketDescriptor;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface BucketFileOptions {\n /**\n * Optional description of the bucket.\n */\n description?: string;\n\n /**\n * Allowed MIME types.\n */\n mimeTypes?: string[];\n\n /**\n * Maximum size of the files in the bucket.\n *\n * @default 10\n */\n maxSize?: number;\n}\n","import { randomUUID } from \"node:crypto\";\nimport type * as fs from \"node:fs\";\nimport { createReadStream } from \"node:fs\";\nimport { mkdir, stat, unlink } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n $atom,\n $hook,\n $inject,\n $use,\n Alepha,\n AlephaError,\n type FileLike,\n type Static,\n t,\n} from \"alepha\";\nimport { FileDetector, FileSystemProvider } from \"alepha/file\";\nimport { $logger } from \"alepha/logger\";\nimport { $bucket } from \"../descriptors/$bucket.ts\";\nimport { FileNotFoundError } from \"../errors/FileNotFoundError.ts\";\nimport type { FileStorageProvider } from \"./FileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Local file storage configuration atom\n */\nexport const localFileStorageOptions = $atom({\n name: \"alepha.bucket.local.options\",\n schema: t.object({\n storagePath: t.string({\n description: \"Directory path where files will be stored\",\n }),\n }),\n default: {\n storagePath: \"node_modules/.alepha/buckets\",\n },\n});\n\nexport type LocalFileStorageProviderOptions = Static<\n typeof localFileStorageOptions.schema\n>;\n\ndeclare module \"alepha\" {\n interface State {\n [localFileStorageOptions.key]: LocalFileStorageProviderOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class LocalFileStorageProvider implements FileStorageProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly fileDetector = $inject(FileDetector);\n protected readonly fileSystemProvider = $inject(FileSystemProvider);\n protected readonly options = $use(localFileStorageOptions);\n\n protected get storagePath(): string {\n return this.options.storagePath;\n }\n\n protected readonly onConfigure = $hook({\n on: \"configure\",\n handler: async () => {\n if (\n this.alepha.isTest() &&\n this.storagePath === localFileStorageOptions.options.default.storagePath\n ) {\n this.alepha.state.set(localFileStorageOptions, {\n storagePath: join(tmpdir(), `alepha-test-${Date.now()}`),\n });\n }\n },\n });\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n try {\n await mkdir(this.storagePath, { recursive: true });\n } catch {}\n\n for (const bucket of this.alepha.descriptors($bucket)) {\n if (bucket.provider !== this) {\n continue;\n }\n\n await mkdir(join(this.storagePath, bucket.name), {\n recursive: true,\n });\n\n this.log.debug(`Bucket '${bucket.name}' at ${this.storagePath} OK`);\n }\n },\n });\n\n public async upload(\n bucketName: string,\n file: FileLike,\n fileId?: string,\n ): Promise<string> {\n fileId ??= this.createId(file.type);\n\n this.log.trace(`Uploading file to ${bucketName}`);\n\n await this.fileSystemProvider.writeFile(\n this.path(bucketName, fileId),\n file,\n );\n\n return fileId;\n }\n\n public async download(bucketName: string, fileId: string): Promise<FileLike> {\n const filePath = this.path(bucketName, fileId);\n\n try {\n const stats = await stat(filePath);\n const mimeType = this.fileDetector.getContentType(fileId);\n\n return this.fileSystemProvider.createFile({\n stream: createReadStream(filePath),\n name: fileId,\n type: mimeType,\n size: stats.size,\n });\n } catch (error) {\n if (this.isErrorNoEntry(error)) {\n throw new FileNotFoundError(`File with ID ${fileId} not found.`);\n }\n throw new AlephaError(\"Invalid file operation\", { cause: error });\n }\n }\n\n public async exists(bucketName: string, fileId: string): Promise<boolean> {\n try {\n await stat(this.path(bucketName, fileId));\n return true;\n } catch (error) {\n if (this.isErrorNoEntry(error)) {\n return false;\n }\n throw new AlephaError(\"Error checking file existence\", { cause: error });\n }\n }\n\n public async delete(bucketName: string, fileId: string): Promise<void> {\n try {\n return await unlink(this.path(bucketName, fileId));\n } catch (error) {\n if (this.isErrorNoEntry(error)) {\n throw new FileNotFoundError(`File with ID ${fileId} not found.`);\n }\n throw new AlephaError(\"Error deleting file\", { cause: error });\n }\n }\n\n protected stat(bucket: string, fileId: string): Promise<fs.Stats> {\n return stat(this.path(bucket, fileId));\n }\n\n protected createId(mimeType: string): string {\n const ext = this.fileDetector.getExtensionFromMimeType(mimeType);\n return `${randomUUID()}.${ext}`;\n }\n\n protected path(bucket: string, fileId = \"\"): string {\n return join(this.storagePath, bucket, fileId);\n }\n\n protected isErrorNoEntry(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n }\n}\n","import { $module, type FileLike } from \"alepha\";\nimport {\n $bucket,\n type BucketDescriptor,\n type BucketFileOptions,\n} from \"./descriptors/$bucket.ts\";\nimport { FileStorageProvider } from \"./providers/FileStorageProvider.ts\";\nimport { LocalFileStorageProvider } from \"./providers/LocalFileStorageProvider.ts\";\nimport { MemoryFileStorageProvider } from \"./providers/MemoryFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$bucket.ts\";\nexport * from \"./errors/FileNotFoundError.ts\";\nexport * from \"./providers/FileStorageProvider.ts\";\nexport * from \"./providers/LocalFileStorageProvider.ts\";\nexport * from \"./providers/MemoryFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface Hooks {\n /**\n * Triggered when a file is uploaded to a bucket.\n * Can be used to perform actions after a file is uploaded, like creating a database record!\n */\n \"bucket:file:uploaded\": {\n id: string;\n file: FileLike;\n bucket: BucketDescriptor;\n options: BucketFileOptions;\n };\n /**\n * Triggered when a file is deleted from a bucket.\n */\n \"bucket:file:deleted\": {\n id: string;\n bucket: BucketDescriptor;\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides file storage capabilities through declarative bucket descriptors with support for multiple storage backends.\n *\n * The bucket module enables unified file operations across different storage systems using the `$bucket` descriptor\n * on class properties. It abstracts storage provider differences, offering consistent APIs for local filesystem,\n * cloud storage, or in-memory storage for testing environments.\n *\n * @see {@link $bucket}\n * @see {@link FileStorageProvider}\n * @module alepha.bucket\n */\nexport const AlephaBucket = $module({\n name: \"alepha.bucket\",\n descriptors: [$bucket],\n services: [\n FileStorageProvider,\n MemoryFileStorageProvider,\n LocalFileStorageProvider,\n ],\n register: (alepha) =>\n alepha.with({\n optional: true,\n provide: FileStorageProvider,\n use: alepha.isTest()\n ? MemoryFileStorageProvider\n : LocalFileStorageProvider,\n }),\n});\n"],"mappings":"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"}
|
package/dist/bucket/index.d.cts
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import * as alepha1 from "alepha";
|
|
2
|
-
import { Alepha, AlephaError, Descriptor, FileLike, KIND, Service, Static } from "alepha";
|
|
3
|
-
import { FileDetector, FileSystemProvider } from "alepha/file";
|
|
4
|
-
import * as alepha_logger0 from "alepha/logger";
|
|
5
|
-
import * as fs from "node:fs";
|
|
6
|
-
|
|
7
|
-
//#region src/bucket/providers/FileStorageProvider.d.ts
|
|
8
|
-
declare abstract class FileStorageProvider {
|
|
9
|
-
/**
|
|
10
|
-
* Uploads a file to the storage.
|
|
11
|
-
*
|
|
12
|
-
* @param bucketName - Container name
|
|
13
|
-
* @param file - File to upload
|
|
14
|
-
* @param fileId - Optional file identifier. If not provided, a unique ID will be generated.
|
|
15
|
-
* @return The identifier of the uploaded file.
|
|
16
|
-
*/
|
|
17
|
-
abstract upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
|
|
18
|
-
/**
|
|
19
|
-
* Downloads a file from the storage.
|
|
20
|
-
*
|
|
21
|
-
* @param bucketName - Container name
|
|
22
|
-
* @param fileId - Identifier of the file to download
|
|
23
|
-
* @return The downloaded file as a FileLike object.
|
|
24
|
-
*/
|
|
25
|
-
abstract download(bucketName: string, fileId: string): Promise<FileLike>;
|
|
26
|
-
/**
|
|
27
|
-
* Check if fileId exists in the storage bucket.
|
|
28
|
-
*
|
|
29
|
-
* @param bucketName - Container name
|
|
30
|
-
* @param fileId - Identifier of the file to stream
|
|
31
|
-
* @return True is the file exists, false otherwise.
|
|
32
|
-
*/
|
|
33
|
-
abstract exists(bucketName: string, fileId: string): Promise<boolean>;
|
|
34
|
-
/**
|
|
35
|
-
* Delete permanently a file from the storage.
|
|
36
|
-
*
|
|
37
|
-
* @param bucketName - Container name
|
|
38
|
-
* @param fileId - Identifier of the file to delete
|
|
39
|
-
*/
|
|
40
|
-
abstract delete(bucketName: string, fileId: string): Promise<void>;
|
|
41
|
-
}
|
|
42
|
-
//#endregion
|
|
43
|
-
//#region src/bucket/providers/MemoryFileStorageProvider.d.ts
|
|
44
|
-
declare class MemoryFileStorageProvider implements FileStorageProvider {
|
|
45
|
-
readonly files: Record<string, FileLike>;
|
|
46
|
-
protected readonly fileSystem: FileSystemProvider;
|
|
47
|
-
protected readonly fileDetector: FileDetector;
|
|
48
|
-
upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
|
|
49
|
-
download(bucketName: string, fileId: string): Promise<FileLike>;
|
|
50
|
-
exists(bucketName: string, fileId: string): Promise<boolean>;
|
|
51
|
-
delete(bucketName: string, fileId: string): Promise<void>;
|
|
52
|
-
protected createId(): string;
|
|
53
|
-
}
|
|
54
|
-
//#endregion
|
|
55
|
-
//#region src/bucket/descriptors/$bucket.d.ts
|
|
56
|
-
/**
|
|
57
|
-
* Creates a bucket descriptor for file storage and management with configurable validation.
|
|
58
|
-
*
|
|
59
|
-
* Provides a comprehensive file storage system that handles uploads, downloads, validation,
|
|
60
|
-
* and management across multiple storage backends with MIME type and size limit controls.
|
|
61
|
-
*
|
|
62
|
-
* **Key Features**
|
|
63
|
-
* - Multi-provider support (filesystem, cloud storage, in-memory)
|
|
64
|
-
* - Automatic MIME type and file size validation
|
|
65
|
-
* - Event integration for file operations monitoring
|
|
66
|
-
* - Flexible per-bucket and per-operation configuration
|
|
67
|
-
* - Smart file type and size detection
|
|
68
|
-
*
|
|
69
|
-
* **Common Use Cases**
|
|
70
|
-
* - User profile pictures and document uploads
|
|
71
|
-
* - Product images and media management
|
|
72
|
-
* - Document storage and retrieval systems
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* class MediaService {
|
|
77
|
-
* images = $bucket({
|
|
78
|
-
* name: "user-images",
|
|
79
|
-
* mimeTypes: ["image/jpeg", "image/png", "image/gif"],
|
|
80
|
-
* maxSize: 5 // 5MB limit
|
|
81
|
-
* });
|
|
82
|
-
*
|
|
83
|
-
* documents = $bucket({
|
|
84
|
-
* name: "documents",
|
|
85
|
-
* mimeTypes: ["application/pdf", "text/plain"],
|
|
86
|
-
* maxSize: 50 // 50MB limit
|
|
87
|
-
* });
|
|
88
|
-
*
|
|
89
|
-
* async uploadProfileImage(file: FileLike, userId: string): Promise<string> {
|
|
90
|
-
* const fileId = await this.images.upload(file);
|
|
91
|
-
* await this.userService.updateProfileImage(userId, fileId);
|
|
92
|
-
* return fileId;
|
|
93
|
-
* }
|
|
94
|
-
*
|
|
95
|
-
* async downloadDocument(documentId: string): Promise<FileLike> {
|
|
96
|
-
* return await this.documents.download(documentId);
|
|
97
|
-
* }
|
|
98
|
-
*
|
|
99
|
-
* async deleteDocument(documentId: string): Promise<void> {
|
|
100
|
-
* await this.documents.delete(documentId);
|
|
101
|
-
* }
|
|
102
|
-
* }
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
declare const $bucket: {
|
|
106
|
-
(options: BucketDescriptorOptions): BucketDescriptor;
|
|
107
|
-
[KIND]: typeof BucketDescriptor;
|
|
108
|
-
};
|
|
109
|
-
interface BucketDescriptorOptions extends BucketFileOptions {
|
|
110
|
-
/**
|
|
111
|
-
* File storage provider configuration for the bucket.
|
|
112
|
-
*
|
|
113
|
-
* Options:
|
|
114
|
-
* - **"memory"**: In-memory storage (default for development, lost on restart)
|
|
115
|
-
* - **Service<FileStorageProvider>**: Custom provider class (e.g., S3FileStorageProvider, AzureBlobProvider)
|
|
116
|
-
* - **undefined**: Uses the default file storage provider from dependency injection
|
|
117
|
-
*
|
|
118
|
-
* **Provider Selection Guidelines**:
|
|
119
|
-
* - **Development**: Use "memory" for fast, simple testing without external dependencies
|
|
120
|
-
* - **Production**: Use cloud providers (S3, Azure Blob, Google Cloud Storage) for scalability
|
|
121
|
-
* - **Local deployment**: Use filesystem providers for on-premise installations
|
|
122
|
-
* - **Hybrid**: Use different providers for different bucket types (temp files vs permanent storage)
|
|
123
|
-
*
|
|
124
|
-
* **Provider Capabilities**:
|
|
125
|
-
* - File persistence and durability guarantees
|
|
126
|
-
* - Scalability and performance characteristics
|
|
127
|
-
* - Geographic distribution and CDN integration
|
|
128
|
-
* - Cost implications for storage and bandwidth
|
|
129
|
-
* - Backup and disaster recovery features
|
|
130
|
-
*
|
|
131
|
-
* @default Uses injected FileStorageProvider
|
|
132
|
-
* @example "memory"
|
|
133
|
-
* @example S3FileStorageProvider
|
|
134
|
-
* @example AzureBlobStorageProvider
|
|
135
|
-
*/
|
|
136
|
-
provider?: Service<FileStorageProvider> | "memory";
|
|
137
|
-
/**
|
|
138
|
-
* Unique name identifier for the bucket.
|
|
139
|
-
*
|
|
140
|
-
* This name is used for:
|
|
141
|
-
* - Storage backend organization and partitioning
|
|
142
|
-
* - File path generation and URL construction
|
|
143
|
-
* - Logging, monitoring, and debugging
|
|
144
|
-
* - Access control and permissions management
|
|
145
|
-
* - Backup and replication configuration
|
|
146
|
-
*
|
|
147
|
-
* **Naming Conventions**:
|
|
148
|
-
* - Use lowercase with hyphens for consistency
|
|
149
|
-
* - Include purpose or content type in the name
|
|
150
|
-
* - Avoid spaces and special characters
|
|
151
|
-
* - Consider environment prefixes for deployment isolation
|
|
152
|
-
*
|
|
153
|
-
* If not provided, defaults to the property key where the bucket is declared.
|
|
154
|
-
*
|
|
155
|
-
* @example "user-avatars"
|
|
156
|
-
* @example "product-images"
|
|
157
|
-
* @example "legal-documents"
|
|
158
|
-
* @example "temp-processing-files"
|
|
159
|
-
*/
|
|
160
|
-
name?: string;
|
|
161
|
-
}
|
|
162
|
-
interface BucketFileOptions {
|
|
163
|
-
/**
|
|
164
|
-
* Human-readable description of the bucket's purpose and contents.
|
|
165
|
-
*
|
|
166
|
-
* Used for:
|
|
167
|
-
* - Documentation generation and API references
|
|
168
|
-
* - Developer onboarding and system understanding
|
|
169
|
-
* - Monitoring dashboards and admin interfaces
|
|
170
|
-
* - Compliance and audit documentation
|
|
171
|
-
*
|
|
172
|
-
* **Description Best Practices**:
|
|
173
|
-
* - Explain what types of files this bucket stores
|
|
174
|
-
* - Mention any special handling or processing requirements
|
|
175
|
-
* - Include information about retention policies if applicable
|
|
176
|
-
* - Note any compliance or security considerations
|
|
177
|
-
*
|
|
178
|
-
* @example "User profile pictures and avatar images"
|
|
179
|
-
* @example "Product catalog images with automated thumbnail generation"
|
|
180
|
-
* @example "Legal documents requiring long-term retention"
|
|
181
|
-
* @example "Temporary files for data processing workflows"
|
|
182
|
-
*/
|
|
183
|
-
description?: string;
|
|
184
|
-
/**
|
|
185
|
-
* Array of allowed MIME types for files uploaded to this bucket.
|
|
186
|
-
*
|
|
187
|
-
* When specified, only files with these exact MIME types will be accepted.
|
|
188
|
-
* Files with disallowed MIME types will be rejected with an InvalidFileError.
|
|
189
|
-
*
|
|
190
|
-
* **MIME Type Categories**:
|
|
191
|
-
* - Images: "image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"
|
|
192
|
-
* - Documents: "application/pdf", "text/plain", "text/csv"
|
|
193
|
-
* - Office: "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
194
|
-
* - Archives: "application/zip", "application/x-tar", "application/gzip"
|
|
195
|
-
* - Media: "video/mp4", "audio/mpeg", "audio/wav"
|
|
196
|
-
*
|
|
197
|
-
* **Security Considerations**:
|
|
198
|
-
* - Always validate MIME types for user uploads
|
|
199
|
-
* - Be cautious with executable file types
|
|
200
|
-
* - Consider using allow-lists rather than deny-lists
|
|
201
|
-
* - Remember that MIME types can be spoofed by malicious users
|
|
202
|
-
*
|
|
203
|
-
* If not specified, all MIME types are allowed (not recommended for user uploads).
|
|
204
|
-
*
|
|
205
|
-
* @example ["image/jpeg", "image/png"] // Only JPEG and PNG images
|
|
206
|
-
* @example ["application/pdf", "text/plain"] // Documents only
|
|
207
|
-
* @example ["video/mp4", "video/webm"] // Video files
|
|
208
|
-
*/
|
|
209
|
-
mimeTypes?: string[];
|
|
210
|
-
/**
|
|
211
|
-
* Maximum file size allowed in megabytes (MB).
|
|
212
|
-
*
|
|
213
|
-
* Files larger than this limit will be rejected with an InvalidFileError.
|
|
214
|
-
* This helps prevent:
|
|
215
|
-
* - Storage quota exhaustion
|
|
216
|
-
* - Memory issues during file processing
|
|
217
|
-
* - Long upload times and timeouts
|
|
218
|
-
* - Abuse of storage resources
|
|
219
|
-
*
|
|
220
|
-
* **Size Guidelines by File Type**:
|
|
221
|
-
* - Profile images: 1-5 MB
|
|
222
|
-
* - Product photos: 5-10 MB
|
|
223
|
-
* - Documents: 10-50 MB
|
|
224
|
-
* - Video files: 50-500 MB
|
|
225
|
-
* - Data files: 100-1000 MB
|
|
226
|
-
*
|
|
227
|
-
* **Considerations**:
|
|
228
|
-
* - Consider your storage costs and limits
|
|
229
|
-
* - Factor in network upload speeds for users
|
|
230
|
-
* - Account for processing requirements (thumbnails, compression)
|
|
231
|
-
* - Set reasonable limits based on actual use cases
|
|
232
|
-
*
|
|
233
|
-
* @default 10 MB
|
|
234
|
-
*
|
|
235
|
-
* @example 1 // 1MB for small images
|
|
236
|
-
* @example 25 // 25MB for documents
|
|
237
|
-
* @example 100 // 100MB for media files
|
|
238
|
-
*/
|
|
239
|
-
maxSize?: number;
|
|
240
|
-
}
|
|
241
|
-
declare class BucketDescriptor extends Descriptor<BucketDescriptorOptions> {
|
|
242
|
-
readonly provider: FileStorageProvider | MemoryFileStorageProvider;
|
|
243
|
-
private readonly fileSystem;
|
|
244
|
-
get name(): string;
|
|
245
|
-
/**
|
|
246
|
-
* Uploads a file to the bucket.
|
|
247
|
-
*/
|
|
248
|
-
upload(file: FileLike, options?: BucketFileOptions): Promise<string>;
|
|
249
|
-
/**
|
|
250
|
-
* Delete permanently a file from the bucket.
|
|
251
|
-
*/
|
|
252
|
-
delete(fileId: string, skipHook?: boolean): Promise<void>;
|
|
253
|
-
/**
|
|
254
|
-
* Checks if a file exists in the bucket.
|
|
255
|
-
*/
|
|
256
|
-
exists(fileId: string): Promise<boolean>;
|
|
257
|
-
/**
|
|
258
|
-
* Downloads a file from the bucket.
|
|
259
|
-
*/
|
|
260
|
-
download(fileId: string): Promise<FileLike>;
|
|
261
|
-
protected $provider(): FileStorageProvider | MemoryFileStorageProvider;
|
|
262
|
-
}
|
|
263
|
-
interface BucketFileOptions {
|
|
264
|
-
/**
|
|
265
|
-
* Optional description of the bucket.
|
|
266
|
-
*/
|
|
267
|
-
description?: string;
|
|
268
|
-
/**
|
|
269
|
-
* Allowed MIME types.
|
|
270
|
-
*/
|
|
271
|
-
mimeTypes?: string[];
|
|
272
|
-
/**
|
|
273
|
-
* Maximum size of the files in the bucket.
|
|
274
|
-
*
|
|
275
|
-
* @default 10
|
|
276
|
-
*/
|
|
277
|
-
maxSize?: number;
|
|
278
|
-
}
|
|
279
|
-
//#endregion
|
|
280
|
-
//#region src/bucket/errors/FileNotFoundError.d.ts
|
|
281
|
-
declare class FileNotFoundError extends AlephaError {
|
|
282
|
-
readonly status = 404;
|
|
283
|
-
}
|
|
284
|
-
//#endregion
|
|
285
|
-
//#region src/bucket/providers/LocalFileStorageProvider.d.ts
|
|
286
|
-
/**
|
|
287
|
-
* Local file storage configuration atom
|
|
288
|
-
*/
|
|
289
|
-
declare const localFileStorageOptions: alepha1.Atom<alepha1.TObject<{
|
|
290
|
-
storagePath: alepha1.TString;
|
|
291
|
-
}>, "alepha.bucket.local.options">;
|
|
292
|
-
type LocalFileStorageProviderOptions = Static<typeof localFileStorageOptions.schema>;
|
|
293
|
-
declare module "alepha" {
|
|
294
|
-
interface State {
|
|
295
|
-
[localFileStorageOptions.key]: LocalFileStorageProviderOptions;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
declare class LocalFileStorageProvider implements FileStorageProvider {
|
|
299
|
-
protected readonly alepha: Alepha;
|
|
300
|
-
protected readonly log: alepha_logger0.Logger;
|
|
301
|
-
protected readonly fileDetector: FileDetector;
|
|
302
|
-
protected readonly fileSystemProvider: FileSystemProvider;
|
|
303
|
-
protected readonly options: Readonly<{
|
|
304
|
-
storagePath: string;
|
|
305
|
-
}>;
|
|
306
|
-
protected get storagePath(): string;
|
|
307
|
-
protected readonly onConfigure: alepha1.HookDescriptor<"configure">;
|
|
308
|
-
protected readonly onStart: alepha1.HookDescriptor<"start">;
|
|
309
|
-
upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
|
|
310
|
-
download(bucketName: string, fileId: string): Promise<FileLike>;
|
|
311
|
-
exists(bucketName: string, fileId: string): Promise<boolean>;
|
|
312
|
-
delete(bucketName: string, fileId: string): Promise<void>;
|
|
313
|
-
protected stat(bucket: string, fileId: string): Promise<fs.Stats>;
|
|
314
|
-
protected createId(mimeType: string): string;
|
|
315
|
-
protected path(bucket: string, fileId?: string): string;
|
|
316
|
-
protected isErrorNoEntry(error: unknown): boolean;
|
|
317
|
-
}
|
|
318
|
-
//#endregion
|
|
319
|
-
//#region src/bucket/index.d.ts
|
|
320
|
-
declare module "alepha" {
|
|
321
|
-
interface Hooks {
|
|
322
|
-
/**
|
|
323
|
-
* Triggered when a file is uploaded to a bucket.
|
|
324
|
-
* Can be used to perform actions after a file is uploaded, like creating a database record!
|
|
325
|
-
*/
|
|
326
|
-
"bucket:file:uploaded": {
|
|
327
|
-
id: string;
|
|
328
|
-
file: FileLike;
|
|
329
|
-
bucket: BucketDescriptor;
|
|
330
|
-
options: BucketFileOptions;
|
|
331
|
-
};
|
|
332
|
-
/**
|
|
333
|
-
* Triggered when a file is deleted from a bucket.
|
|
334
|
-
*/
|
|
335
|
-
"bucket:file:deleted": {
|
|
336
|
-
id: string;
|
|
337
|
-
bucket: BucketDescriptor;
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Provides file storage capabilities through declarative bucket descriptors with support for multiple storage backends.
|
|
343
|
-
*
|
|
344
|
-
* The bucket module enables unified file operations across different storage systems using the `$bucket` descriptor
|
|
345
|
-
* on class properties. It abstracts storage provider differences, offering consistent APIs for local filesystem,
|
|
346
|
-
* cloud storage, or in-memory storage for testing environments.
|
|
347
|
-
*
|
|
348
|
-
* @see {@link $bucket}
|
|
349
|
-
* @see {@link FileStorageProvider}
|
|
350
|
-
* @module alepha.bucket
|
|
351
|
-
*/
|
|
352
|
-
declare const AlephaBucket: alepha1.Service<alepha1.Module>;
|
|
353
|
-
//#endregion
|
|
354
|
-
export { $bucket, AlephaBucket, BucketDescriptor, BucketDescriptorOptions, BucketFileOptions, FileNotFoundError, FileStorageProvider, LocalFileStorageProvider, LocalFileStorageProviderOptions, MemoryFileStorageProvider, localFileStorageOptions };
|
|
355
|
-
//# sourceMappingURL=index.d.cts.map
|
package/dist/cache/index.cjs
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
let alepha = require("alepha");
|
|
2
|
-
let alepha_datetime = require("alepha/datetime");
|
|
3
|
-
let alepha_logger = require("alepha/logger");
|
|
4
|
-
|
|
5
|
-
//#region src/cache/errors/CacheError.ts
|
|
6
|
-
var CacheError = class extends alepha.AlephaError {};
|
|
7
|
-
|
|
8
|
-
//#endregion
|
|
9
|
-
//#region src/cache/providers/CacheProvider.ts
|
|
10
|
-
/**
|
|
11
|
-
* Cache provider interface.
|
|
12
|
-
*
|
|
13
|
-
* All methods are asynchronous and return promises.
|
|
14
|
-
* Values are stored as Uint8Array.
|
|
15
|
-
*/
|
|
16
|
-
var CacheProvider = class {};
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/cache/providers/MemoryCacheProvider.ts
|
|
20
|
-
var MemoryCacheProvider = class {
|
|
21
|
-
dateTimeProvider = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
|
|
22
|
-
log = (0, alepha_logger.$logger)();
|
|
23
|
-
store = {};
|
|
24
|
-
async get(name, key) {
|
|
25
|
-
return this.store[name]?.[key]?.data;
|
|
26
|
-
}
|
|
27
|
-
async set(name, key, value, ttl) {
|
|
28
|
-
if (this.store[name] == null) this.store[name] = {};
|
|
29
|
-
this.store[name][key] ??= {};
|
|
30
|
-
this.store[name][key].data = value;
|
|
31
|
-
this.log.debug(`Setting cache for name`, {
|
|
32
|
-
name,
|
|
33
|
-
key,
|
|
34
|
-
ttl
|
|
35
|
-
});
|
|
36
|
-
if (this.store[name][key].timeout) {
|
|
37
|
-
this.dateTimeProvider.clearTimeout(this.store[name][key].timeout);
|
|
38
|
-
this.store[name][key].timeout = void 0;
|
|
39
|
-
}
|
|
40
|
-
if (ttl) this.store[name][key].timeout = this.dateTimeProvider.createTimeout(() => this.del(name, key), ttl);
|
|
41
|
-
return this.store[name][key].data;
|
|
42
|
-
}
|
|
43
|
-
async del(name, ...keys) {
|
|
44
|
-
if (keys.length === 0) {
|
|
45
|
-
this.log.debug(`Deleting all cache for name`, { name });
|
|
46
|
-
if (this.store[name]) for (const key of Object.keys(this.store[name])) {
|
|
47
|
-
const timeout = this.store[name][key]?.timeout;
|
|
48
|
-
if (timeout) this.dateTimeProvider.clearTimeout(timeout);
|
|
49
|
-
}
|
|
50
|
-
delete this.store[name];
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
this.log.debug(`Deleting cache for name`, {
|
|
54
|
-
name,
|
|
55
|
-
keys
|
|
56
|
-
});
|
|
57
|
-
for (const key of keys) {
|
|
58
|
-
if (this.store[name] == null) break;
|
|
59
|
-
const timeout = this.store[name][key]?.timeout;
|
|
60
|
-
if (timeout) this.dateTimeProvider.clearTimeout(timeout);
|
|
61
|
-
delete this.store[name][key];
|
|
62
|
-
}
|
|
63
|
-
if (Object.keys(this.store[name] ?? {}).length === 0) delete this.store[name];
|
|
64
|
-
}
|
|
65
|
-
async has(name, key) {
|
|
66
|
-
return this.store[name]?.[key]?.data != null;
|
|
67
|
-
}
|
|
68
|
-
async keys(name, filter) {
|
|
69
|
-
const store = this.store[name] ?? {};
|
|
70
|
-
const keys = Object.keys(store);
|
|
71
|
-
if (filter) return keys.filter((key) => key.startsWith(filter));
|
|
72
|
-
return keys;
|
|
73
|
-
}
|
|
74
|
-
async clear() {
|
|
75
|
-
this.log.debug("Clearing all cache");
|
|
76
|
-
for (const name of Object.keys(this.store)) for (const key of Object.keys(this.store[name])) {
|
|
77
|
-
const timeout = this.store[name][key]?.timeout;
|
|
78
|
-
if (timeout) this.dateTimeProvider.clearTimeout(timeout);
|
|
79
|
-
}
|
|
80
|
-
this.store = {};
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
//#endregion
|
|
85
|
-
//#region src/cache/descriptors/$cache.ts
|
|
86
|
-
/**
|
|
87
|
-
* Creates a cache descriptor for high-performance data caching with automatic management.
|
|
88
|
-
*
|
|
89
|
-
* Provides a caching layer that improves application performance by storing frequently accessed
|
|
90
|
-
* data in memory or external stores like Redis, with support for both function result caching
|
|
91
|
-
* and manual cache operations.
|
|
92
|
-
*
|
|
93
|
-
* **Key Features**
|
|
94
|
-
* - Automatic function result caching based on input parameters
|
|
95
|
-
* - Multiple storage backends (in-memory, Redis, custom providers)
|
|
96
|
-
* - Intelligent serialization for JSON, strings, and binary data
|
|
97
|
-
* - Configurable TTL with automatic expiration
|
|
98
|
-
* - Pattern-based cache invalidation with wildcard support
|
|
99
|
-
* - Environment controls to enable/disable caching
|
|
100
|
-
*
|
|
101
|
-
* **Storage Backends**
|
|
102
|
-
* - Memory: Fast in-memory cache (default for development)
|
|
103
|
-
* - Redis: Distributed cache for production environments
|
|
104
|
-
* - Custom providers: Implement your own storage backend
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```ts
|
|
108
|
-
* class DataService {
|
|
109
|
-
* // Function result caching
|
|
110
|
-
* getUserData = $cache({
|
|
111
|
-
* name: "user-data",
|
|
112
|
-
* ttl: [10, "minutes"],
|
|
113
|
-
* handler: async (userId: string) => {
|
|
114
|
-
* return await database.users.findById(userId);
|
|
115
|
-
* }
|
|
116
|
-
* });
|
|
117
|
-
*
|
|
118
|
-
* // Manual cache operations
|
|
119
|
-
* sessionCache = $cache<UserSession>({
|
|
120
|
-
* name: "sessions",
|
|
121
|
-
* ttl: [1, "hour"]
|
|
122
|
-
* });
|
|
123
|
-
*
|
|
124
|
-
* async storeSession(id: string, session: UserSession) {
|
|
125
|
-
* await this.sessionCache.set(id, session);
|
|
126
|
-
* }
|
|
127
|
-
*
|
|
128
|
-
* async invalidateUserSessions(userId: string) {
|
|
129
|
-
* await this.sessionCache.invalidate(`user:${userId}:*`);
|
|
130
|
-
* }
|
|
131
|
-
* }
|
|
132
|
-
* ```
|
|
133
|
-
*/
|
|
134
|
-
const $cache = (options = {}) => {
|
|
135
|
-
const instance = (0, alepha.createDescriptor)(CacheDescriptor, options);
|
|
136
|
-
const fn = (...args) => instance.run(...args);
|
|
137
|
-
return Object.setPrototypeOf(fn, instance);
|
|
138
|
-
};
|
|
139
|
-
const envSchema = alepha.t.object({
|
|
140
|
-
CACHE_ENABLED: alepha.t.boolean({ default: true }),
|
|
141
|
-
CACHE_DEFAULT_TTL: alepha.t.number({
|
|
142
|
-
default: 300,
|
|
143
|
-
description: "The default time to live for cache entries. In seconds."
|
|
144
|
-
})
|
|
145
|
-
});
|
|
146
|
-
var CacheDescriptor = class extends alepha.Descriptor {
|
|
147
|
-
env = (0, alepha.$env)(envSchema);
|
|
148
|
-
dateTimeProvider = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
|
|
149
|
-
provider = this.$provider();
|
|
150
|
-
encoder = new TextEncoder();
|
|
151
|
-
decoder = new TextDecoder();
|
|
152
|
-
codes = {
|
|
153
|
-
BINARY: 1,
|
|
154
|
-
JSON: 2,
|
|
155
|
-
STRING: 3
|
|
156
|
-
};
|
|
157
|
-
get container() {
|
|
158
|
-
return this.options.name ?? `${this.config.service.name}:${this.config.propertyKey}`;
|
|
159
|
-
}
|
|
160
|
-
async run(...args) {
|
|
161
|
-
const handler = this.options.handler;
|
|
162
|
-
if (!handler) throw new Error("Cache handler is not defined.");
|
|
163
|
-
const key = this.key(...args);
|
|
164
|
-
const cached = await this.get(key);
|
|
165
|
-
if (cached) return cached;
|
|
166
|
-
const result = await handler(...args);
|
|
167
|
-
await this.set(key, result);
|
|
168
|
-
return result;
|
|
169
|
-
}
|
|
170
|
-
key(...args) {
|
|
171
|
-
return this.options.key ? this.options.key(...args) : JSON.stringify(args);
|
|
172
|
-
}
|
|
173
|
-
async invalidate(...keys) {
|
|
174
|
-
const keysToDelete = [];
|
|
175
|
-
for (const key of keys) if (key.endsWith("*")) {
|
|
176
|
-
const result = await this.provider.keys(this.container, key.slice(0, -1));
|
|
177
|
-
keysToDelete.push(...result);
|
|
178
|
-
} else keysToDelete.push(key);
|
|
179
|
-
await this.provider.del(this.container, ...keysToDelete);
|
|
180
|
-
}
|
|
181
|
-
async set(key, value, ttl) {
|
|
182
|
-
const px = this.dateTimeProvider.duration(ttl ?? this.options.ttl ?? [this.env.CACHE_DEFAULT_TTL, "seconds"]).as("milliseconds");
|
|
183
|
-
await this.provider.set(this.container, key, this.serialize(value), px > 0 ? px : void 0);
|
|
184
|
-
}
|
|
185
|
-
async get(key) {
|
|
186
|
-
if (!this.alepha.isStarted() || this.options.disabled || !this.env.CACHE_ENABLED) return;
|
|
187
|
-
const data = await this.provider.get(this.container, key);
|
|
188
|
-
if (data) return await this.deserialize(data);
|
|
189
|
-
}
|
|
190
|
-
serialize(value) {
|
|
191
|
-
if (value instanceof Uint8Array) return new Uint8Array([this.codes.BINARY, ...value]);
|
|
192
|
-
if (typeof value === "string") return new Uint8Array([this.codes.STRING, ...this.encoder.encode(value)]);
|
|
193
|
-
return new Uint8Array([this.codes.JSON, ...this.encoder.encode(JSON.stringify(value))]);
|
|
194
|
-
}
|
|
195
|
-
async deserialize(uint8Array) {
|
|
196
|
-
const type = uint8Array[0];
|
|
197
|
-
const payload = uint8Array.slice(1);
|
|
198
|
-
if (type === this.codes.BINARY) return payload;
|
|
199
|
-
if (type === this.codes.JSON) return JSON.parse(this.decoder.decode(payload));
|
|
200
|
-
if (type === this.codes.STRING) return this.decoder.decode(payload);
|
|
201
|
-
throw new CacheError(`Unknown serialization type: ${type}`);
|
|
202
|
-
}
|
|
203
|
-
$provider() {
|
|
204
|
-
if (!this.options.provider) return this.alepha.inject(CacheProvider);
|
|
205
|
-
if (this.options.provider === "memory") return this.alepha.inject(MemoryCacheProvider);
|
|
206
|
-
return this.alepha.inject(this.options.provider);
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
$cache[alepha.KIND] = CacheDescriptor;
|
|
210
|
-
|
|
211
|
-
//#endregion
|
|
212
|
-
//#region src/cache/index.ts
|
|
213
|
-
/**
|
|
214
|
-
* Provides high-performance caching capabilities for Alepha applications with configurable TTL and multiple storage backends.
|
|
215
|
-
*
|
|
216
|
-
* The cache module enables declarative caching through the `$cache` descriptor, allowing you to cache method results,
|
|
217
|
-
* API responses, or computed values with automatic invalidation and type safety. It supports both in-memory and
|
|
218
|
-
* persistent storage backends for different performance and durability requirements.
|
|
219
|
-
*
|
|
220
|
-
* @see {@link $cache}
|
|
221
|
-
* @see {@link CacheProvider}
|
|
222
|
-
* @module alepha.cache
|
|
223
|
-
*/
|
|
224
|
-
const AlephaCache = (0, alepha.$module)({
|
|
225
|
-
name: "alepha.cache",
|
|
226
|
-
descriptors: [$cache],
|
|
227
|
-
services: [CacheProvider, MemoryCacheProvider],
|
|
228
|
-
register: (alepha$1) => alepha$1.with({
|
|
229
|
-
optional: true,
|
|
230
|
-
provide: CacheProvider,
|
|
231
|
-
use: MemoryCacheProvider
|
|
232
|
-
})
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
//#endregion
|
|
236
|
-
exports.$cache = $cache;
|
|
237
|
-
exports.AlephaCache = AlephaCache;
|
|
238
|
-
exports.CacheDescriptor = CacheDescriptor;
|
|
239
|
-
exports.CacheProvider = CacheProvider;
|
|
240
|
-
exports.MemoryCacheProvider = MemoryCacheProvider;
|
|
241
|
-
//# sourceMappingURL=index.cjs.map
|