express-storage 1.0.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +490 -0
  3. package/dist/drivers/base.driver.d.ts +69 -0
  4. package/dist/drivers/base.driver.d.ts.map +1 -0
  5. package/dist/drivers/base.driver.js +161 -0
  6. package/dist/drivers/base.driver.js.map +1 -0
  7. package/dist/drivers/gcs.driver.d.ts +39 -0
  8. package/dist/drivers/gcs.driver.d.ts.map +1 -0
  9. package/dist/drivers/gcs.driver.js +126 -0
  10. package/dist/drivers/gcs.driver.js.map +1 -0
  11. package/dist/drivers/local.driver.d.ts +30 -0
  12. package/dist/drivers/local.driver.d.ts.map +1 -0
  13. package/dist/drivers/local.driver.js +102 -0
  14. package/dist/drivers/local.driver.js.map +1 -0
  15. package/dist/drivers/oci.driver.d.ts +37 -0
  16. package/dist/drivers/oci.driver.d.ts.map +1 -0
  17. package/dist/drivers/oci.driver.js +84 -0
  18. package/dist/drivers/oci.driver.js.map +1 -0
  19. package/dist/drivers/s3.driver.d.ts +38 -0
  20. package/dist/drivers/s3.driver.d.ts.map +1 -0
  21. package/dist/drivers/s3.driver.js +135 -0
  22. package/dist/drivers/s3.driver.js.map +1 -0
  23. package/dist/factory/driver.factory.d.ts +56 -0
  24. package/dist/factory/driver.factory.d.ts.map +1 -0
  25. package/dist/factory/driver.factory.js +117 -0
  26. package/dist/factory/driver.factory.js.map +1 -0
  27. package/dist/index.d.ts +29 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +53 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/storage-manager.d.ts +75 -0
  32. package/dist/storage-manager.d.ts.map +1 -0
  33. package/dist/storage-manager.js +144 -0
  34. package/dist/storage-manager.js.map +1 -0
  35. package/dist/types/storage.types.d.ts +70 -0
  36. package/dist/types/storage.types.d.ts.map +1 -0
  37. package/dist/types/storage.types.js +2 -0
  38. package/dist/types/storage.types.js.map +1 -0
  39. package/dist/utils/config.utils.d.ts +21 -0
  40. package/dist/utils/config.utils.d.ts.map +1 -0
  41. package/dist/utils/config.utils.js +128 -0
  42. package/dist/utils/config.utils.js.map +1 -0
  43. package/dist/utils/file.utils.d.ts +45 -0
  44. package/dist/utils/file.utils.d.ts.map +1 -0
  45. package/dist/utils/file.utils.js +95 -0
  46. package/dist/utils/file.utils.js.map +1 -0
  47. package/package.json +82 -0
@@ -0,0 +1,70 @@
1
+ import { Request } from 'express';
2
+ export type StorageDriver = 's3' | 's3-presigned' | 'gcs' | 'gcs-presigned' | 'oci' | 'oci-presigned' | 'local';
3
+ export interface FileUploadResult {
4
+ success: boolean;
5
+ fileName?: string;
6
+ fileUrl?: string;
7
+ error?: string;
8
+ }
9
+ export interface PresignedUrlResult {
10
+ success: boolean;
11
+ uploadUrl?: string;
12
+ viewUrl?: string;
13
+ error?: string;
14
+ }
15
+ export interface StorageConfig {
16
+ driver: StorageDriver;
17
+ bucketName?: string | undefined;
18
+ localPath?: string | undefined;
19
+ presignedUrlExpiry?: number | undefined;
20
+ awsRegion?: string | undefined;
21
+ awsAccessKey?: string | undefined;
22
+ awsSecretKey?: string | undefined;
23
+ gcsProjectId?: string | undefined;
24
+ gcsCredentials?: string | undefined;
25
+ ociRegion?: string | undefined;
26
+ ociCredentials?: string | undefined;
27
+ }
28
+ export interface SingleFileInput {
29
+ type: 'single';
30
+ file: Express.Multer.File;
31
+ }
32
+ export interface MultipleFilesInput {
33
+ type: 'multiple';
34
+ files: Express.Multer.File[];
35
+ }
36
+ export type FileInput = SingleFileInput | MultipleFilesInput;
37
+ export interface IStorageDriver {
38
+ upload(file: Express.Multer.File): Promise<FileUploadResult>;
39
+ uploadMultiple(files: Express.Multer.File[]): Promise<FileUploadResult[]>;
40
+ generateUploadUrl(fileName: string): Promise<PresignedUrlResult>;
41
+ generateViewUrl(fileName: string): Promise<PresignedUrlResult>;
42
+ generateMultipleUploadUrls(fileNames: string[]): Promise<PresignedUrlResult[]>;
43
+ generateMultipleViewUrls(fileNames: string[]): Promise<PresignedUrlResult[]>;
44
+ delete(fileName: string): Promise<boolean>;
45
+ deleteMultiple(fileNames: string[]): Promise<boolean[]>;
46
+ }
47
+ export interface StorageRequest extends Request {
48
+ storage?: {
49
+ files?: Express.Multer.File[];
50
+ uploadResults?: FileUploadResult[];
51
+ };
52
+ }
53
+ export interface ValidationResult {
54
+ isValid: boolean;
55
+ errors: string[];
56
+ }
57
+ export interface EnvironmentConfig {
58
+ FILE_DRIVER: string;
59
+ BUCKET_NAME?: string | undefined;
60
+ LOCAL_PATH?: string | undefined;
61
+ PRESIGNED_URL_EXPIRY?: string | undefined;
62
+ AWS_REGION?: string | undefined;
63
+ AWS_ACCESS_KEY?: string | undefined;
64
+ AWS_SECRET_KEY?: string | undefined;
65
+ GCS_PROJECT_ID?: string | undefined;
66
+ GCS_CREDENTIALS?: string | undefined;
67
+ OCI_REGION?: string | undefined;
68
+ OCI_CREDENTIALS?: string | undefined;
69
+ }
70
+ //# sourceMappingURL=storage.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.types.d.ts","sourceRoot":"","sources":["../../src/types/storage.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.types.js","sourceRoot":"","sources":["../../src/types/storage.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { StorageConfig, EnvironmentConfig, ValidationResult } from '../types/storage.types.js';
2
+ /**
3
+ * Load environment configuration
4
+ */
5
+ export declare function loadEnvironmentConfig(): EnvironmentConfig;
6
+ /**
7
+ * Convert environment config to storage config
8
+ */
9
+ export declare function environmentToStorageConfig(envConfig: EnvironmentConfig): StorageConfig;
10
+ /**
11
+ * Validate storage configuration
12
+ */
13
+ export declare function validateStorageConfig(config: StorageConfig): ValidationResult;
14
+ /**
15
+ * Load and validate configuration from environment
16
+ */
17
+ export declare function loadAndValidateConfig(): {
18
+ config: StorageConfig;
19
+ validation: ValidationResult;
20
+ };
21
+ //# sourceMappingURL=config.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.utils.d.ts","sourceRoot":"","sources":["../../src/utils/config.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAgC/F;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,iBAAiB,CAoBzD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,iBAAiB,GAAG,aAAa,CAwBtF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,CAuC7E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,gBAAgB,CAAA;CAAE,CAM/F"}
@@ -0,0 +1,128 @@
1
+ import dotenv from 'dotenv';
2
+ // Load environment variables
3
+ dotenv.config();
4
+ // Environment variable keys
5
+ const ENV_KEYS = {
6
+ FILE_DRIVER: 'FILE_DRIVER',
7
+ BUCKET_NAME: 'BUCKET_NAME',
8
+ LOCAL_PATH: 'LOCAL_PATH',
9
+ PRESIGNED_URL_EXPIRY: 'PRESIGNED_URL_EXPIRY',
10
+ // AWS S3
11
+ AWS_REGION: 'AWS_REGION',
12
+ AWS_ACCESS_KEY: 'AWS_ACCESS_KEY',
13
+ AWS_SECRET_KEY: 'AWS_SECRET_KEY',
14
+ // Google Cloud Storage
15
+ GCS_PROJECT_ID: 'GCS_PROJECT_ID',
16
+ GCS_CREDENTIALS: 'GCS_CREDENTIALS',
17
+ // Oracle Cloud Infrastructure
18
+ OCI_REGION: 'OCI_REGION',
19
+ OCI_CREDENTIALS: 'OCI_CREDENTIALS',
20
+ };
21
+ // Default configuration
22
+ const DEFAULT_CONFIG = {
23
+ presignedUrlExpiry: 600, // 10 minutes
24
+ localPath: 'public/express-storage',
25
+ };
26
+ /**
27
+ * Load environment configuration
28
+ */
29
+ export function loadEnvironmentConfig() {
30
+ return {
31
+ FILE_DRIVER: process.env[ENV_KEYS.FILE_DRIVER] || '',
32
+ BUCKET_NAME: process.env[ENV_KEYS.BUCKET_NAME] || undefined,
33
+ LOCAL_PATH: process.env[ENV_KEYS.LOCAL_PATH] || undefined,
34
+ PRESIGNED_URL_EXPIRY: process.env[ENV_KEYS.PRESIGNED_URL_EXPIRY] || undefined,
35
+ // AWS S3
36
+ AWS_REGION: process.env[ENV_KEYS.AWS_REGION] || undefined,
37
+ AWS_ACCESS_KEY: process.env[ENV_KEYS.AWS_ACCESS_KEY] || undefined,
38
+ AWS_SECRET_KEY: process.env[ENV_KEYS.AWS_SECRET_KEY] || undefined,
39
+ // Google Cloud Storage
40
+ GCS_PROJECT_ID: process.env[ENV_KEYS.GCS_PROJECT_ID] || undefined,
41
+ GCS_CREDENTIALS: process.env[ENV_KEYS.GCS_CREDENTIALS] || undefined,
42
+ // Oracle Cloud Infrastructure
43
+ OCI_REGION: process.env[ENV_KEYS.OCI_REGION] || undefined,
44
+ OCI_CREDENTIALS: process.env[ENV_KEYS.OCI_CREDENTIALS] || undefined,
45
+ };
46
+ }
47
+ /**
48
+ * Convert environment config to storage config
49
+ */
50
+ export function environmentToStorageConfig(envConfig) {
51
+ const config = {
52
+ driver: envConfig.FILE_DRIVER,
53
+ bucketName: envConfig.BUCKET_NAME,
54
+ localPath: envConfig.LOCAL_PATH || DEFAULT_CONFIG.localPath,
55
+ presignedUrlExpiry: envConfig.PRESIGNED_URL_EXPIRY
56
+ ? parseInt(envConfig.PRESIGNED_URL_EXPIRY, 10)
57
+ : DEFAULT_CONFIG.presignedUrlExpiry,
58
+ // AWS S3
59
+ awsRegion: envConfig.AWS_REGION,
60
+ awsAccessKey: envConfig.AWS_ACCESS_KEY,
61
+ awsSecretKey: envConfig.AWS_SECRET_KEY,
62
+ // Google Cloud Storage
63
+ gcsProjectId: envConfig.GCS_PROJECT_ID,
64
+ gcsCredentials: envConfig.GCS_CREDENTIALS,
65
+ // Oracle Cloud Infrastructure
66
+ ociRegion: envConfig.OCI_REGION,
67
+ ociCredentials: envConfig.OCI_CREDENTIALS,
68
+ };
69
+ return config;
70
+ }
71
+ /**
72
+ * Validate storage configuration
73
+ */
74
+ export function validateStorageConfig(config) {
75
+ const errors = [];
76
+ // Validate driver
77
+ if (!config.driver) {
78
+ errors.push('FILE_DRIVER is required');
79
+ }
80
+ else if (!['s3', 's3-presigned', 'gcs', 'gcs-presigned', 'oci', 'oci-presigned', 'local'].includes(config.driver)) {
81
+ errors.push(`Invalid FILE_DRIVER: ${config.driver}. Must be one of: s3, s3-presigned, gcs, gcs-presigned, oci, oci-presigned, local`);
82
+ }
83
+ // Validate cloud storage requirements
84
+ if (config.driver?.includes('s3')) {
85
+ if (!config.bucketName)
86
+ errors.push('BUCKET_NAME is required for S3');
87
+ if (!config.awsRegion)
88
+ errors.push('AWS_REGION is required for S3');
89
+ if (!config.awsAccessKey)
90
+ errors.push('AWS_ACCESS_KEY is required for S3');
91
+ if (!config.awsSecretKey)
92
+ errors.push('AWS_SECRET_KEY is required for S3');
93
+ }
94
+ if (config.driver?.includes('gcs')) {
95
+ if (!config.bucketName)
96
+ errors.push('BUCKET_NAME is required for GCS');
97
+ if (!config.gcsProjectId)
98
+ errors.push('GCS_PROJECT_ID is required for GCS');
99
+ if (!config.gcsCredentials)
100
+ errors.push('GCS_CREDENTIALS is required for GCS');
101
+ }
102
+ if (config.driver?.includes('oci')) {
103
+ if (!config.bucketName)
104
+ errors.push('BUCKET_NAME is required for OCI');
105
+ if (!config.ociRegion)
106
+ errors.push('OCI_REGION is required for OCI');
107
+ if (!config.ociCredentials)
108
+ errors.push('OCI_CREDENTIALS is required for OCI');
109
+ }
110
+ // Validate presigned URL expiry
111
+ if (config.presignedUrlExpiry && config.presignedUrlExpiry <= 0) {
112
+ errors.push('PRESIGNED_URL_EXPIRY must be greater than 0');
113
+ }
114
+ return {
115
+ isValid: errors.length === 0,
116
+ errors,
117
+ };
118
+ }
119
+ /**
120
+ * Load and validate configuration from environment
121
+ */
122
+ export function loadAndValidateConfig() {
123
+ const envConfig = loadEnvironmentConfig();
124
+ const config = environmentToStorageConfig(envConfig);
125
+ const validation = validateStorageConfig(config);
126
+ return { config, validation };
127
+ }
128
+ //# sourceMappingURL=config.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.utils.js","sourceRoot":"","sources":["../../src/utils/config.utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Generate unique filename with unix timestamp
3
+ */
4
+ export declare function generateUniqueFileName(originalName: string): string;
5
+ /**
6
+ * Sanitize filename to prevent security issues
7
+ */
8
+ export declare function sanitizeFileName(fileName: string): string;
9
+ /**
10
+ * Create month-based directory path
11
+ */
12
+ export declare function createMonthBasedPath(basePath: string): string;
13
+ /**
14
+ * Ensure directory exists, create if it doesn't
15
+ */
16
+ export declare function ensureDirectoryExists(dirPath: string): void;
17
+ /**
18
+ * Get file size in human readable format
19
+ */
20
+ export declare function formatFileSize(bytes: number): string;
21
+ /**
22
+ * Validate file size
23
+ */
24
+ export declare function validateFileSize(fileSize: number, maxSize: number): boolean;
25
+ /**
26
+ * Validate file type
27
+ */
28
+ export declare function validateFileType(mimeType: string, allowedTypes: string[]): boolean;
29
+ /**
30
+ * Create relative URL for local files
31
+ */
32
+ export declare function createLocalFileUrl(filePath: string, baseUrl?: string): string;
33
+ /**
34
+ * Get file extension from filename
35
+ */
36
+ export declare function getFileExtension(fileName: string): string;
37
+ /**
38
+ * Check if file is an image
39
+ */
40
+ export declare function isImageFile(mimeType: string): boolean;
41
+ /**
42
+ * Check if file is a document
43
+ */
44
+ export declare function isDocumentFile(mimeType: string): boolean;
45
+ //# sourceMappingURL=file.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.utils.d.ts","sourceRoot":"","sources":["../../src/utils/file.utils.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAElF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,MAAM,CAGjF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWxD"}
@@ -0,0 +1,95 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ /**
4
+ * Generate unique filename with unix timestamp
5
+ */
6
+ export function generateUniqueFileName(originalName) {
7
+ const timestamp = Math.floor(Date.now() / 1000); // Unix timestamp
8
+ const extension = path.extname(originalName);
9
+ const sanitizedName = sanitizeFileName(originalName);
10
+ const baseName = path.basename(sanitizedName, extension);
11
+ return `${timestamp}_${baseName}${extension}`;
12
+ }
13
+ /**
14
+ * Sanitize filename to prevent security issues
15
+ */
16
+ export function sanitizeFileName(fileName) {
17
+ return fileName
18
+ .replace(/[^a-zA-Z0-9.-]/g, '_') // Replace special characters with underscore
19
+ .replace(/_{2,}/g, '_') // Replace multiple underscores with single
20
+ .replace(/^_+|_+$/g, ''); // Remove leading/trailing underscores
21
+ }
22
+ /**
23
+ * Create month-based directory path
24
+ */
25
+ export function createMonthBasedPath(basePath) {
26
+ const now = new Date();
27
+ const month = now.toLocaleString('en', { month: 'long' }).toLowerCase();
28
+ const year = now.getFullYear();
29
+ return path.join(basePath, month, year.toString());
30
+ }
31
+ /**
32
+ * Ensure directory exists, create if it doesn't
33
+ */
34
+ export function ensureDirectoryExists(dirPath) {
35
+ if (!fs.existsSync(dirPath)) {
36
+ fs.mkdirSync(dirPath, { recursive: true });
37
+ }
38
+ }
39
+ /**
40
+ * Get file size in human readable format
41
+ */
42
+ export function formatFileSize(bytes) {
43
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
44
+ if (bytes === 0)
45
+ return '0 Bytes';
46
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
47
+ return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
48
+ }
49
+ /**
50
+ * Validate file size
51
+ */
52
+ export function validateFileSize(fileSize, maxSize) {
53
+ return fileSize <= maxSize;
54
+ }
55
+ /**
56
+ * Validate file type
57
+ */
58
+ export function validateFileType(mimeType, allowedTypes) {
59
+ return allowedTypes.includes(mimeType);
60
+ }
61
+ /**
62
+ * Create relative URL for local files
63
+ */
64
+ export function createLocalFileUrl(filePath, baseUrl = '') {
65
+ const relativePath = filePath.replace(/^public\//, '');
66
+ return `${baseUrl}/${relativePath}`.replace(/\/+/g, '/');
67
+ }
68
+ /**
69
+ * Get file extension from filename
70
+ */
71
+ export function getFileExtension(fileName) {
72
+ return path.extname(fileName).toLowerCase();
73
+ }
74
+ /**
75
+ * Check if file is an image
76
+ */
77
+ export function isImageFile(mimeType) {
78
+ return mimeType.startsWith('image/');
79
+ }
80
+ /**
81
+ * Check if file is a document
82
+ */
83
+ export function isDocumentFile(mimeType) {
84
+ const documentTypes = [
85
+ 'application/pdf',
86
+ 'application/msword',
87
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
88
+ 'application/vnd.ms-excel',
89
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
90
+ 'text/plain',
91
+ 'text/csv'
92
+ ];
93
+ return documentTypes.includes(mimeType);
94
+ }
95
+ //# sourceMappingURL=file.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.utils.js","sourceRoot":"","sources":["../../src/utils/file.utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAAoB;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,iBAAiB;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAEzD,OAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,QAAQ;SACZ,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,6CAA6C;SAC7E,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,2CAA2C;SAClE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,sCAAsC;AACpE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACxE,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAE/B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAElC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IAChE,OAAO,QAAQ,IAAI,OAAO,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,YAAsB;IACvE,OAAO,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,UAAkB,EAAE;IACvE,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,GAAG,OAAO,IAAI,YAAY,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,aAAa,GAAG;QACpB,iBAAiB;QACjB,oBAAoB;QACpB,yEAAyE;QACzE,0BAA0B;QAC1B,mEAAmE;QACnE,YAAY;QACZ,UAAU;KACX,CAAC;IACF,OAAO,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "express-storage",
3
+ "version": "1.0.0",
4
+ "description": "A simple and powerful file upload and storage management package for Express.js applications. Supports multiple storage drivers including S3, GCS, OCI, and local storage with presigned URL support.",
5
+ "homepage": "https://github.com/th3hero/express-storage#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/th3hero/express-storage/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/th3hero/express-storage.git"
12
+ },
13
+ "license": "MIT",
14
+ "author": "Alok Kumar (th3hero)",
15
+ "type": "module",
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.js",
21
+ "types": "./dist/index.d.ts"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "keywords": [
30
+ "express",
31
+ "file-upload",
32
+ "storage",
33
+ "s3",
34
+ "gcs",
35
+ "oci",
36
+ "presigned-url",
37
+ "typescript",
38
+ "multer",
39
+ "cloud-storage"
40
+ ],
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "dev": "tsc --watch",
44
+ "clean": "rm -rf dist",
45
+ "prepublishOnly": "npm run clean && npm run build",
46
+ "test": "jest",
47
+ "test:watch": "jest --watch",
48
+ "test:coverage": "jest --coverage",
49
+ "lint": "eslint src --ext .ts",
50
+ "lint:fix": "eslint src --ext .ts --fix",
51
+ "format": "prettier --write src/**/*.ts",
52
+ "type-check": "tsc --noEmit"
53
+ },
54
+ "peerDependencies": {
55
+ "express": "^4.21.2"
56
+ },
57
+ "engines": {
58
+ "node": ">=16.0.0"
59
+ },
60
+ "devDependencies": {
61
+ "@types/express": "^5.0.3",
62
+ "@types/jest": "^30.0.0",
63
+ "@types/multer": "^2.0.0",
64
+ "@types/node": "^24.1.0",
65
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
66
+ "@typescript-eslint/parser": "^8.38.0",
67
+ "eslint": "^9.32.0",
68
+ "jest": "^30.0.5",
69
+ "prettier": "^3.6.2",
70
+ "ts-jest": "^29.4.0",
71
+ "typescript": "^5.8.3"
72
+ },
73
+ "dependencies": {
74
+ "@aws-sdk/client-s3": "^3.856.0",
75
+ "@aws-sdk/s3-request-presigner": "^3.856.0",
76
+ "@google-cloud/storage": "^7.16.0",
77
+ "dotenv": "^17.2.1",
78
+ "multer": "^2.0.2",
79
+ "oci-sdk": "^2.114.0",
80
+ "tslib": "^2.8.1"
81
+ }
82
+ }