@ackplus/nest-file-storage 1.1.1 → 1.1.5

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 (44) hide show
  1. package/package.json +2 -2
  2. package/src/{index.ts → index.d.ts} +1 -0
  3. package/src/index.d.ts.map +1 -0
  4. package/src/index.js +7 -0
  5. package/src/lib/constants.d.ts +2 -0
  6. package/src/lib/constants.d.ts.map +1 -0
  7. package/src/lib/constants.js +4 -0
  8. package/src/lib/file-storage.service.d.ts +8 -0
  9. package/src/lib/file-storage.service.d.ts.map +1 -0
  10. package/src/lib/file-storage.service.js +29 -0
  11. package/src/lib/{index.ts → index.d.ts} +1 -0
  12. package/src/lib/index.d.ts.map +1 -0
  13. package/src/lib/index.js +8 -0
  14. package/src/lib/interceptor/file-storage.interceptor.d.ts +25 -0
  15. package/src/lib/interceptor/file-storage.interceptor.d.ts.map +1 -0
  16. package/src/lib/interceptor/{file-storage.interceptor.ts → file-storage.interceptor.js} +35 -71
  17. package/src/lib/nest-file-storage.module.d.ts +9 -0
  18. package/src/lib/nest-file-storage.module.d.ts.map +1 -0
  19. package/src/lib/nest-file-storage.module.js +74 -0
  20. package/src/lib/storage/azure.storage.d.ts +19 -0
  21. package/src/lib/storage/azure.storage.d.ts.map +1 -0
  22. package/src/lib/storage/{azure.storage.ts → azure.storage.js} +57 -118
  23. package/src/lib/storage/local.storage.d.ts +35 -0
  24. package/src/lib/storage/local.storage.d.ts.map +1 -0
  25. package/src/lib/storage/{local.storage.ts → local.storage.js} +44 -94
  26. package/src/lib/storage/s3.storage.d.ts +20 -0
  27. package/src/lib/storage/s3.storage.d.ts.map +1 -0
  28. package/src/lib/storage/{s3.storage.ts → s3.storage.js} +58 -105
  29. package/src/lib/storage.factory.d.ts +9 -0
  30. package/src/lib/storage.factory.d.ts.map +1 -0
  31. package/src/lib/storage.factory.js +81 -0
  32. package/src/lib/{types.ts → types.d.ts} +23 -35
  33. package/src/lib/types.d.ts.map +1 -0
  34. package/src/lib/types.js +9 -0
  35. package/eslint.config.mjs +0 -22
  36. package/jest.config.ts +0 -10
  37. package/project.json +0 -38
  38. package/src/lib/constants.ts +0 -1
  39. package/src/lib/file-storage.service.ts +0 -36
  40. package/src/lib/nest-file-storage.module.ts +0 -78
  41. package/src/lib/storage.factory.ts +0 -58
  42. package/tsconfig.json +0 -17
  43. package/tsconfig.lib.json +0 -14
  44. package/tsconfig.spec.json +0 -15
@@ -1,214 +1,153 @@
1
- import {
2
- BlobSASPermissions,
3
- BlobSASSignatureValues,
4
- BlobServiceClient,
5
- generateBlobSASQueryParameters,
6
- SASProtocol,
7
- StorageSharedKeyCredential,
8
- } from '@azure/storage-blob';
9
- import concat from 'concat-stream';
10
- import moment from 'moment';
11
- import { StorageEngine } from 'multer';
12
- import path, { basename, join } from 'path';
13
- import { v4 as uuidv4 } from 'uuid';
14
-
15
- import { AzureStorageOptions, Storage, UploadedFile } from '../types';
16
-
17
-
18
- export class AzureStorage implements StorageEngine, Storage {
19
-
20
- private blobServiceClient: BlobServiceClient;
21
-
22
- private fileNameFunction: (file: Express.Multer.File, req?: any) => string | Promise<string>;
23
- private fileDistFunction: (file: Express.Multer.File, req?: any) => string | Promise<string>;
24
-
25
-
26
- constructor(private options: AzureStorageOptions) {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AzureStorage = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const storage_blob_1 = require("@azure/storage-blob");
6
+ const concat_stream_1 = tslib_1.__importDefault(require("concat-stream"));
7
+ const moment_1 = tslib_1.__importDefault(require("moment"));
8
+ const path_1 = tslib_1.__importStar(require("path"));
9
+ const uuid_1 = require("uuid");
10
+ class AzureStorage {
11
+ constructor(options) {
12
+ this.options = options;
27
13
  this.fileNameFunction = options.fileName || ((file, _req) => {
28
- return `${uuidv4()}-${file.originalname}`;
14
+ return `${(0, uuid_1.v4)()}-${file.originalname}`;
29
15
  });
30
-
31
16
  this.fileDistFunction = options.fileDist || ((_file, _req) => {
32
- return path.join('uploads', moment().format('YYYY'), moment().format('MM'), moment().format('DD'));
17
+ return path_1.default.join('uploads', (0, moment_1.default)().format('YYYY'), (0, moment_1.default)().format('MM'), (0, moment_1.default)().format('DD'));
33
18
  });
34
-
35
- const sharedKeyCredential = new StorageSharedKeyCredential(
36
- options.account,
37
- options.accountKey,
38
- );
39
-
40
- this.blobServiceClient = new BlobServiceClient(
41
- `https://${options.account}.blob.core.windows.net`,
42
- sharedKeyCredential,
43
- );
19
+ const sharedKeyCredential = new storage_blob_1.StorageSharedKeyCredential(options.account, options.accountKey);
20
+ this.blobServiceClient = new storage_blob_1.BlobServiceClient(`https://${options.account}.blob.core.windows.net`, sharedKeyCredential);
44
21
  }
45
-
46
- async _handleFile(
47
- req: any,
48
- file: any,
49
- cb: (error?: any, info?: any) => void,
50
- ): Promise<void> {
22
+ async _handleFile(req, file, cb) {
51
23
  try {
52
24
  const dist = await this.fileDistFunction(file, req);
53
25
  const key = await this.fileNameFunction(file, req);
54
- const filePath = join(dist, key);
55
-
56
- file.stream.pipe(concat({ encoding: 'buffer' }, async (buffer) => {
26
+ const filePath = (0, path_1.join)(dist, key);
27
+ file.stream.pipe((0, concat_stream_1.default)({ encoding: 'buffer' }, async (buffer) => {
57
28
  const uploadedFile = await this.putFile(buffer, filePath);
58
-
59
- const fileInfo: UploadedFile = {
29
+ const fileInfo = {
60
30
  ...uploadedFile,
61
31
  fieldName: file.fieldname,
62
32
  originalName: file.originalname,
63
33
  mimetype: file.mimetype,
64
34
  };
65
35
  let transformData = fileInfo;
66
-
67
36
  if (this.options?.transformUploadedFileObject) {
68
37
  transformData = await this.options.transformUploadedFileObject(fileInfo);
69
38
  }
70
39
  cb(null, transformData);
71
40
  }));
72
- } catch (error) {
41
+ }
42
+ catch (error) {
73
43
  cb(error);
74
44
  }
75
-
76
- file.stream.on('error', (err: any) => cb(err));
45
+ file.stream.on('error', (err) => cb(err));
77
46
  }
78
-
79
- async _removeFile(
80
- _req: any,
81
- file: any,
82
- cb: (error: Error | null) => void,
83
- ): Promise<void> {
47
+ async _removeFile(_req, file, cb) {
84
48
  try {
85
49
  const blobClient = this.blobServiceClient
86
50
  .getContainerClient(this.options.container)
87
51
  .getBlobClient(file.key);
88
-
89
52
  await blobClient.delete();
90
53
  cb(null);
91
- } catch (error) {
54
+ }
55
+ catch (error) {
92
56
  cb(error);
93
57
  }
94
58
  }
95
-
96
- getUrl(key: string): string {
59
+ getUrl(key) {
97
60
  return `https://${this.options.account}.blob.core.windows.net/${this.options.container}/${key}`;
98
61
  }
99
-
100
-
101
- getSignedUrl(key: string, signatureValues: Partial<Omit<BlobSASSignatureValues, 'containerName'>> = {}): string {
102
- if (!key) return '';
103
-
62
+ getSignedUrl(key, signatureValues = {}) {
63
+ if (!key)
64
+ return '';
104
65
  const cloudFrontDomain = process.env['AZURE_CDN_DOMAIN_NAME'];
105
-
106
66
  if (cloudFrontDomain) {
107
67
  return `${cloudFrontDomain}/${key}`;
108
68
  }
109
-
110
69
  const containerClient = this.blobServiceClient.getContainerClient(this.options.container);
111
70
  const blobClient = containerClient.getBlobClient(key);
112
-
113
- const sharedKeyCredential = new StorageSharedKeyCredential(
114
- this.options.account,
115
- this.options.accountKey,
116
- );
117
-
71
+ const sharedKeyCredential = new storage_blob_1.StorageSharedKeyCredential(this.options.account, this.options.accountKey);
118
72
  // Set the SAS token options
119
73
  const expiresOn = new Date();
120
74
  expiresOn.setHours(expiresOn.getHours() + 1); // Set expiration time to 1 hour from now
121
-
122
- const sasToken = generateBlobSASQueryParameters(
123
- {
124
- containerName: this.options.container,
125
- blobName: key,
126
- permissions: BlobSASPermissions.parse('r'), // Read permissions
127
- protocol: SASProtocol.Https, // HTTPS only
128
- startsOn: new Date(), // Start time (now)
129
- expiresOn, // Expiration time
130
- ...signatureValues,
131
- },
132
- sharedKeyCredential,
133
- ).toString();
134
-
75
+ const sasToken = (0, storage_blob_1.generateBlobSASQueryParameters)({
76
+ containerName: this.options.container,
77
+ blobName: key,
78
+ permissions: storage_blob_1.BlobSASPermissions.parse('r'), // Read permissions
79
+ protocol: storage_blob_1.SASProtocol.Https, // HTTPS only
80
+ startsOn: new Date(), // Start time (now)
81
+ expiresOn, // Expiration time
82
+ ...signatureValues,
83
+ }, sharedKeyCredential).toString();
135
84
  return `${blobClient.url}?${sasToken}`;
136
85
  }
137
-
138
- async getFile(key: string): Promise<Buffer> {
86
+ async getFile(key) {
139
87
  const containerClient = this.blobServiceClient.getContainerClient(this.options.container);
140
88
  const blobClient = containerClient.getBlobClient(key);
141
89
  const downloadResponse = await blobClient.download();
142
90
  const stream = downloadResponse.readableStreamBody;
143
-
144
91
  return new Promise((resolve, reject) => {
145
- const chunks: Buffer[] = [];
92
+ const chunks = [];
146
93
  stream?.on('data', (chunk) => chunks.push(chunk));
147
94
  stream?.on('end', () => resolve(Buffer.concat(chunks)));
148
95
  stream?.on('error', reject);
149
96
  });
150
97
  }
151
-
152
- async putFile(buffer: Buffer, key: string): Promise<UploadedFile> {
98
+ async putFile(buffer, key) {
153
99
  try {
154
100
  const containerClient = this.blobServiceClient.getContainerClient(this.options.container);
155
101
  const blockBlobClient = containerClient.getBlockBlobClient(key);
156
-
157
102
  await blockBlobClient.uploadData(buffer);
158
-
159
- const fileInfo: UploadedFile = {
160
- originalName: basename(key),
161
- fileName: basename(key),
103
+ const fileInfo = {
104
+ originalName: (0, path_1.basename)(key),
105
+ fileName: (0, path_1.basename)(key),
162
106
  size: buffer.length,
163
107
  buffer,
164
108
  key,
165
109
  fullPath: key,
166
110
  url: this.getUrl(key),
167
111
  };
168
-
169
112
  return fileInfo;
170
- } catch (error) {
113
+ }
114
+ catch (error) {
171
115
  console.error(`Error uploading file "${key}":`, error);
172
116
  throw error;
173
117
  }
174
118
  }
175
-
176
- async deleteFile(key: string) {
119
+ async deleteFile(key) {
177
120
  try {
178
121
  const blobClient = this.blobServiceClient
179
122
  .getContainerClient(this.options.container)
180
123
  .getBlobClient(key);
181
-
182
124
  await blobClient.delete();
183
- } catch (error) {
125
+ }
126
+ catch (error) {
184
127
  console.error(`Error deleting blob "${key}":`, error);
185
128
  }
186
129
  }
187
-
188
- async copyFile(oldKey: string, newKey: string): Promise<UploadedFile> {
130
+ async copyFile(oldKey, newKey) {
189
131
  try {
190
132
  const containerClient = this.blobServiceClient.getContainerClient(this.options.container);
191
133
  const sourceBlobClient = containerClient.getBlobClient(oldKey);
192
134
  const destinationBlobClient = containerClient.getBlobClient(newKey);
193
-
194
135
  const copyPoller = await destinationBlobClient.beginCopyFromURL(sourceBlobClient.url);
195
136
  await copyPoller.pollUntilDone();
196
-
197
137
  const properties = await destinationBlobClient.getProperties();
198
-
199
138
  return {
200
- originalName: basename(newKey),
139
+ originalName: (0, path_1.basename)(newKey),
201
140
  size: properties.contentLength || 0,
202
- fileName: basename(newKey),
141
+ fileName: (0, path_1.basename)(newKey),
203
142
  key: newKey,
204
143
  fullPath: newKey,
205
144
  url: this.getUrl(newKey),
206
145
  };
207
- } catch (error) {
146
+ }
147
+ catch (error) {
208
148
  console.error('Error copying file in Azure Blob Storage:', error);
209
149
  throw error;
210
150
  }
211
151
  }
212
-
213
-
214
152
  }
153
+ exports.AzureStorage = AzureStorage;
@@ -0,0 +1,35 @@
1
+ import { StorageEngine } from 'multer';
2
+ import { LocalStorageOptions, Storage, UploadedFile } from '../types';
3
+ export declare class LocalStorage implements StorageEngine, Storage {
4
+ private options;
5
+ private rootPath;
6
+ private fileNameFunction;
7
+ private fileDistFunction;
8
+ /**
9
+ * Convert OS-specific file path to URL-friendly key
10
+ * This ensures keys are consistent across all platforms
11
+ * Windows: C:\uploads\2024\01\file.jpg -> 2024/01/file.jpg
12
+ * Unix: /uploads/2024/01/file.jpg -> 2024/01/file.jpg
13
+ */
14
+ private pathToUrl;
15
+ /**
16
+ * Convert URL-friendly key to OS-specific file path
17
+ * This converts stored keys back to valid file system paths
18
+ * 2024/01/file.jpg -> Windows: 2024\01\file.jpg, Unix: 2024/01/file.jpg
19
+ */
20
+ private urlToPath;
21
+ /**
22
+ * Get full file system path from URL-friendly key
23
+ */
24
+ private getFullPath;
25
+ constructor(options: LocalStorageOptions);
26
+ _handleFile(req: any, file: Express.Multer.File, cb: (error?: any, info?: any) => void): Promise<void>;
27
+ _removeFile(_req: any, file: any, cb: (error: Error | null) => void): void;
28
+ getUrl(urlKey: string): string;
29
+ getFile(urlKey: string): Promise<Buffer>;
30
+ deleteFile(urlKey: string): Promise<void>;
31
+ putFile(fileContent: Buffer, urlKey: string): Promise<UploadedFile>;
32
+ path(urlKey: string): string;
33
+ copyFile(oldUrlKey: string, newUrlKey: string): Promise<UploadedFile>;
34
+ }
35
+ //# sourceMappingURL=local.storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.storage.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/storage/local.storage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGtE,qBAAa,YAAa,YAAW,aAAa,EAAE,OAAO;IA8C3C,OAAO,CAAC,OAAO;IA5C3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,gBAAgB,CAAqE;IAE7F;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAajB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,CAAC,WAAW;gBAKC,OAAO,EAAE,mBAAmB;IAmB1C,WAAW,CACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EACzB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI;IAgCzC,WAAW,CACP,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI;IAarC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAgBxB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMxC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,OAAO,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC;IAiCxB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQtB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAgC9E"}
@@ -1,182 +1,140 @@
1
- import concat from 'concat-stream';
2
- import * as fs from 'fs';
3
- import moment from 'moment';
4
- import { StorageEngine } from 'multer';
5
- import * as path from 'path';
6
- import { basename, dirname, join, normalize, sep } from 'path';
7
- import { join as posixJoin } from 'path/posix';
8
- import { v4 as uuidv4 } from 'uuid';
9
-
10
- import { LocalStorageOptions, Storage, UploadedFile } from '../types';
11
-
12
-
13
- export class LocalStorage implements StorageEngine, Storage {
14
-
15
- private rootPath: string;
16
- private fileNameFunction: (file: Express.Multer.File, req?: any) => string | Promise<string>;
17
- private fileDistFunction: (file: Express.Multer.File, req?: any) => string | Promise<string>;
18
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalStorage = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const concat_stream_1 = tslib_1.__importDefault(require("concat-stream"));
6
+ const fs = tslib_1.__importStar(require("fs"));
7
+ const moment_1 = tslib_1.__importDefault(require("moment"));
8
+ const path_1 = require("path");
9
+ const uuid_1 = require("uuid");
10
+ class LocalStorage {
19
11
  /**
20
12
  * Convert OS-specific file path to URL-friendly key
21
13
  * This ensures keys are consistent across all platforms
22
14
  * Windows: C:\uploads\2024\01\file.jpg -> 2024/01/file.jpg
23
15
  * Unix: /uploads/2024/01/file.jpg -> 2024/01/file.jpg
24
16
  */
25
- private pathToUrl(filePath: string): string {
26
- if (!filePath) return '';
27
-
17
+ pathToUrl(filePath) {
18
+ if (!filePath)
19
+ return '';
28
20
  // Remove rootPath if present
29
21
  let relativePath = filePath;
30
22
  if (filePath.startsWith(this.rootPath)) {
31
23
  relativePath = filePath.substring(this.rootPath.length);
32
24
  }
33
-
34
25
  // Convert backslashes to forward slashes and remove leading slash
35
26
  return relativePath.replace(/\\/g, '/').replace(/^\/+/, '');
36
27
  }
37
-
38
28
  /**
39
29
  * Convert URL-friendly key to OS-specific file path
40
30
  * This converts stored keys back to valid file system paths
41
31
  * 2024/01/file.jpg -> Windows: 2024\01\file.jpg, Unix: 2024/01/file.jpg
42
32
  */
43
- private urlToPath(urlKey: string): string {
44
- if (!urlKey) return '';
45
-
33
+ urlToPath(urlKey) {
34
+ if (!urlKey)
35
+ return '';
46
36
  // Split by forward slashes and rejoin with OS-specific separator
47
37
  const parts = urlKey.split('/').filter(part => part.length > 0);
48
- return parts.join(sep);
38
+ return parts.join(path_1.sep);
49
39
  }
50
-
51
40
  /**
52
41
  * Get full file system path from URL-friendly key
53
42
  */
54
- private getFullPath(urlKey: string): string {
43
+ getFullPath(urlKey) {
55
44
  const osPath = this.urlToPath(urlKey);
56
- return join(this.rootPath, osPath);
45
+ return (0, path_1.join)(this.rootPath, osPath);
57
46
  }
58
-
59
- constructor(private options: LocalStorageOptions) {
47
+ constructor(options) {
48
+ this.options = options;
60
49
  // Normalize path for the current OS
61
- this.rootPath = normalize(options.rootPath || join(process.cwd(), 'public'));
62
-
50
+ this.rootPath = (0, path_1.normalize)(options.rootPath || (0, path_1.join)(process.cwd(), 'public'));
63
51
  this.fileNameFunction = options.fileName || ((file, _req) => {
64
- return `${uuidv4()}-${file.originalname}`;
52
+ return `${(0, uuid_1.v4)()}-${file.originalname}`;
65
53
  });
66
-
67
54
  this.fileDistFunction = options.fileDist || ((_file, _req) => {
68
- return join(this.rootPath, moment().format('YYYY'), moment().format('MM'), moment().format('DD'));
55
+ return (0, path_1.join)(this.rootPath, (0, moment_1.default)().format('YYYY'), (0, moment_1.default)().format('MM'), (0, moment_1.default)().format('DD'));
69
56
  });
70
-
71
-
72
57
  // Ensure the rootPath directory exists
73
58
  if (!fs.existsSync(this.rootPath)) {
74
59
  fs.mkdirSync(this.rootPath, { recursive: true });
75
60
  }
76
61
  }
77
-
78
- async _handleFile(
79
- req: any,
80
- file: Express.Multer.File,
81
- cb: (error?: any, info?: any) => void,
82
- ) {
62
+ async _handleFile(req, file, cb) {
83
63
  try {
84
64
  const dist = await this.fileDistFunction(file, req);
85
65
  const fileName = await this.fileNameFunction(file, req);
86
-
87
- const filePath = join(dist, fileName);
66
+ const filePath = (0, path_1.join)(dist, fileName);
88
67
  // Convert to URL-friendly key for storage
89
68
  const urlKey = this.pathToUrl(filePath);
90
-
91
- file.stream.pipe(concat({ encoding: 'buffer' }, async (buffer) => {
69
+ file.stream.pipe((0, concat_stream_1.default)({ encoding: 'buffer' }, async (buffer) => {
92
70
  const uploadedFile = await this.putFile(buffer, urlKey);
93
-
94
- const fileInfo: UploadedFile = {
71
+ const fileInfo = {
95
72
  ...uploadedFile,
96
73
  fieldName: file.fieldname,
97
74
  originalName: file.originalname,
98
75
  mimetype: file.mimetype,
99
76
  };
100
77
  let transformData = fileInfo;
101
-
102
78
  if (this.options?.transformUploadedFileObject) {
103
79
  transformData = await this.options.transformUploadedFileObject(fileInfo);
104
80
  }
105
81
  cb(null, transformData);
106
82
  }));
107
- } catch (error) {
83
+ }
84
+ catch (error) {
108
85
  console.error('error', error);
109
86
  cb(error);
110
87
  }
111
88
  }
112
-
113
- _removeFile(
114
- _req: any,
115
- file: any,
116
- cb: (error: Error | null) => void,
117
- ) {
89
+ _removeFile(_req, file, cb) {
118
90
  const filePath = file.path;
119
-
120
91
  fs.unlink(filePath, (err) => {
121
92
  if (err) {
122
93
  cb(err);
123
- } else {
94
+ }
95
+ else {
124
96
  cb(null);
125
97
  }
126
98
  });
127
99
  }
128
-
129
- getUrl(urlKey: string): string {
100
+ getUrl(urlKey) {
130
101
  if (urlKey && urlKey.startsWith('http')) {
131
102
  return urlKey;
132
103
  }
133
104
  if (!urlKey) {
134
105
  return '';
135
106
  }
136
-
137
107
  // Key is already in URL format (forward slashes)
138
108
  // Ensure baseUrl doesn't end with slash and key doesn't start with slash
139
109
  const baseUrl = this.options.baseUrl.replace(/\/$/, '');
140
110
  const cleanKey = urlKey.replace(/^\//, '');
141
-
142
111
  return `${baseUrl}/${cleanKey}`;
143
112
  }
144
-
145
- async getFile(urlKey: string): Promise<Buffer> {
113
+ async getFile(urlKey) {
146
114
  // Convert URL key to OS-specific path
147
115
  const fullPath = this.getFullPath(urlKey);
148
116
  return fs.promises.readFile(fullPath);
149
117
  }
150
-
151
- async deleteFile(urlKey: string): Promise<void> {
118
+ async deleteFile(urlKey) {
152
119
  // Convert URL key to OS-specific path
153
120
  const fullPath = this.getFullPath(urlKey);
154
121
  return fs.promises.unlink(fullPath);
155
122
  }
156
-
157
- async putFile(
158
- fileContent: Buffer,
159
- urlKey: string,
160
- ): Promise<UploadedFile> {
123
+ async putFile(fileContent, urlKey) {
161
124
  return new Promise((putFileResolve, reject) => {
162
125
  // Convert URL key to OS-specific path
163
126
  const filePath = this.getFullPath(urlKey);
164
-
165
- const directoryPath = dirname(filePath);
166
-
127
+ const directoryPath = (0, path_1.dirname)(filePath);
167
128
  // Create the directory if it doesn't exist
168
129
  fs.mkdirSync(directoryPath, { recursive: true });
169
-
170
130
  fs.writeFile(filePath, fileContent, (err) => {
171
131
  if (err) {
172
132
  reject(err);
173
133
  return;
174
134
  }
175
-
176
135
  const stats = fs.statSync(filePath);
177
136
  const fileName = urlKey.split('/').pop() || urlKey;
178
-
179
- const fileInfo: UploadedFile = {
137
+ const fileInfo = {
180
138
  originalName: fileName,
181
139
  size: stats.size,
182
140
  fileName: fileName,
@@ -188,35 +146,28 @@ export class LocalStorage implements StorageEngine, Storage {
188
146
  });
189
147
  });
190
148
  }
191
-
192
-
193
- path(urlKey: string): string {
149
+ path(urlKey) {
194
150
  if (!urlKey) {
195
151
  return '';
196
152
  }
197
153
  // Convert URL key to full OS-specific path
198
154
  return this.getFullPath(urlKey);
199
155
  }
200
-
201
- async copyFile(oldUrlKey: string, newUrlKey: string): Promise<UploadedFile> {
156
+ async copyFile(oldUrlKey, newUrlKey) {
202
157
  return new Promise((resolve, reject) => {
203
158
  // Convert URL keys to OS-specific paths
204
159
  const oldPath = this.getFullPath(oldUrlKey);
205
160
  const newPath = this.getFullPath(newUrlKey);
206
-
207
- const directoryPath = dirname(newPath);
161
+ const directoryPath = (0, path_1.dirname)(newPath);
208
162
  fs.mkdirSync(directoryPath, { recursive: true });
209
-
210
163
  fs.copyFile(oldPath, newPath, (err) => {
211
164
  if (err) {
212
165
  reject(err);
213
166
  return;
214
167
  }
215
-
216
168
  const stats = fs.statSync(newPath);
217
169
  const fileName = newUrlKey.split('/').pop() || newUrlKey;
218
-
219
- const fileInfo: UploadedFile = {
170
+ const fileInfo = {
220
171
  originalName: fileName,
221
172
  size: stats.size,
222
173
  fileName: fileName,
@@ -228,6 +179,5 @@ export class LocalStorage implements StorageEngine, Storage {
228
179
  });
229
180
  });
230
181
  }
231
-
232
-
233
182
  }
183
+ exports.LocalStorage = LocalStorage;
@@ -0,0 +1,20 @@
1
+ import { GetObjectCommandInput } from '@aws-sdk/client-s3';
2
+ import { StorageEngine } from 'multer';
3
+ import { S3StorageOptions, Storage, UploadedFile } from '../types';
4
+ export declare class S3Storage implements StorageEngine, Storage {
5
+ private options;
6
+ private s3;
7
+ private fileNameFunction;
8
+ private fileDistFunction;
9
+ constructor(options: S3StorageOptions);
10
+ _handleFile(req: any, file: Express.Multer.File, cb: (error?: any, info?: any) => void): Promise<void>;
11
+ _removeFile(_req: any, file: any, cb: (error: Error | null) => void): void;
12
+ getUrl(key: string): string;
13
+ getSignedUrl(key: string, objectConfig?: Partial<GetObjectCommandInput>): Promise<string>;
14
+ getFile(key: string): Promise<Buffer>;
15
+ putFile(fileContent: Buffer, key: string): Promise<any>;
16
+ deleteFile(key: string): Promise<void>;
17
+ private streamToBuffer;
18
+ copyFile(oldKey: string, newKey: string): Promise<UploadedFile>;
19
+ }
20
+ //# sourceMappingURL=s3.storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.storage.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/storage/s3.storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,qBAAqB,EAAM,MAAM,oBAAoB,CAAC;AAIlF,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGnE,qBAAa,SAAU,YAAW,aAAa,EAAE,OAAO;IAMxC,OAAO,CAAC,OAAO;IAJ3B,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,gBAAgB,CAAqE;gBAEzE,OAAO,EAAE,gBAAgB;IAmBvC,WAAW,CACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EACzB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;IAkChB,WAAW,CACP,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAClC,IAAI;IAYP,MAAM,CAAC,GAAG,EAAE,MAAM;IAOZ,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAezF,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BrC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IA0CvD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAmB9B,cAAc;IAQtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CA4BxE"}