@devbro/neko-storage 0.1.8 → 0.1.10

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 (48) hide show
  1. package/README.md +344 -48
  2. package/dist/cjs/index.d.ts +159 -0
  3. package/dist/cjs/index.js.map +1 -0
  4. package/dist/esm/Storage.mjs.map +1 -0
  5. package/dist/esm/StorageProviderFactory.mjs.map +1 -0
  6. package/dist/esm/index.mjs.map +1 -0
  7. package/dist/esm/providers/AWSS3StorageProvider.mjs.map +1 -0
  8. package/dist/esm/providers/AzureBlobStorageProvider.mjs.map +1 -0
  9. package/dist/esm/providers/FTPStorageProvider.mjs.map +1 -0
  10. package/dist/esm/providers/GCPStorageProvider.mjs.map +1 -0
  11. package/dist/esm/providers/LocalStorageProvider.mjs.map +1 -0
  12. package/dist/esm/providers/SFTPStorageProvider.mjs.map +1 -0
  13. package/package.json +7 -7
  14. package/dist/Storage.mjs.map +0 -1
  15. package/dist/StorageProviderFactory.mjs.map +0 -1
  16. package/dist/index.js.map +0 -1
  17. package/dist/index.mjs.map +0 -1
  18. package/dist/providers/AWSS3StorageProvider.mjs.map +0 -1
  19. package/dist/providers/AzureBlobStorageProvider.mjs.map +0 -1
  20. package/dist/providers/FTPStorageProvider.mjs.map +0 -1
  21. package/dist/providers/GCPStorageProvider.mjs.map +0 -1
  22. package/dist/providers/LocalStorageProvider.mjs.map +0 -1
  23. package/dist/providers/SFTPStorageProvider.mjs.map +0 -1
  24. /package/dist/{index.js → cjs/index.js} +0 -0
  25. /package/dist/{Storage.d.mts → esm/Storage.d.mts} +0 -0
  26. /package/dist/{Storage.mjs → esm/Storage.mjs} +0 -0
  27. /package/dist/{StorageProviderFactory.d.mts → esm/StorageProviderFactory.d.mts} +0 -0
  28. /package/dist/{StorageProviderFactory.mjs → esm/StorageProviderFactory.mjs} +0 -0
  29. /package/dist/{StorageProviderInterface.d.mts → esm/StorageProviderInterface.d.mts} +0 -0
  30. /package/dist/{StorageProviderInterface.mjs → esm/StorageProviderInterface.mjs} +0 -0
  31. /package/dist/{StorageProviderInterface.mjs.map → esm/StorageProviderInterface.mjs.map} +0 -0
  32. /package/dist/{index.d.mts → esm/index.d.mts} +0 -0
  33. /package/dist/{index.mjs → esm/index.mjs} +0 -0
  34. /package/dist/{providers → esm/providers}/AWSS3StorageProvider.d.mts +0 -0
  35. /package/dist/{providers → esm/providers}/AWSS3StorageProvider.mjs +0 -0
  36. /package/dist/{providers → esm/providers}/AzureBlobStorageProvider.d.mts +0 -0
  37. /package/dist/{providers → esm/providers}/AzureBlobStorageProvider.mjs +0 -0
  38. /package/dist/{providers → esm/providers}/FTPStorageProvider.d.mts +0 -0
  39. /package/dist/{providers → esm/providers}/FTPStorageProvider.mjs +0 -0
  40. /package/dist/{providers → esm/providers}/GCPStorageProvider.d.mts +0 -0
  41. /package/dist/{providers → esm/providers}/GCPStorageProvider.mjs +0 -0
  42. /package/dist/{providers → esm/providers}/LocalStorageProvider.d.mts +0 -0
  43. /package/dist/{providers → esm/providers}/LocalStorageProvider.mjs +0 -0
  44. /package/dist/{providers → esm/providers}/SFTPStorageProvider.d.mts +0 -0
  45. /package/dist/{providers → esm/providers}/SFTPStorageProvider.mjs +0 -0
  46. /package/dist/{types.d.mts → esm/types.d.mts} +0 -0
  47. /package/dist/{types.mjs → esm/types.mjs} +0 -0
  48. /package/dist/{types.mjs.map → esm/types.mjs.map} +0 -0
package/README.md CHANGED
@@ -1,56 +1,154 @@
1
1
  # @devbro/neko-storage
2
2
 
3
- a library to abstract file storage and management.
3
+ A unified, driver-based file storage abstraction library for Node.js and TypeScript. Store and manage files across multiple platforms using a consistent API.
4
4
 
5
- ## basic usage
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @devbro/neko-storage
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - 🔌 **Multiple Storage Providers** - Local, AWS S3, GCP, Azure, FTP, SFTP
14
+ - 🎯 **Unified API** - Same interface for all storage providers
15
+ - 📦 **Multiple Formats** - Support for JSON, String, Buffer, and Stream
16
+ - 🔄 **Easy Migration** - Switch storage providers without changing your code
17
+ - 🛡️ **Type-Safe** - Full TypeScript support
18
+ - ⚡ **Async/Await** - Modern promise-based API
19
+ - 🔍 **Metadata Support** - Get file information (size, mime type, modified date)
20
+
21
+ ## Quick Start
22
+
23
+ ```ts
24
+ import { Storage, LocalStorageProvider } from '@devbro/neko-storage';
25
+
26
+ // Create a storage instance
27
+ const provider = new LocalStorageProvider({
28
+ engine: 'local',
29
+ basePath: '/tmp/my-app-storage',
30
+ });
31
+ const storage = new Storage(provider);
32
+
33
+ // Store a file
34
+ await storage.put('documents/report.txt', 'Hello World');
35
+
36
+ // Check if file exists
37
+ const exists = await storage.exists('documents/report.txt'); // true
38
+
39
+ // Read the file
40
+ const content = await storage.getString('documents/report.txt'); // 'Hello World'
41
+
42
+ // Delete the file
43
+ await storage.delete('documents/report.txt');
44
+ ```
45
+
46
+ ## Core API
47
+
48
+ ### Storing Files
49
+
50
+ Store content in various formats:
51
+
52
+ ```ts
53
+ // Store string content
54
+ await storage.put('path/to/file.txt', 'Hello World');
55
+
56
+ // Store JSON object
57
+ await storage.put('path/to/data.json', { name: 'John', age: 30 });
58
+
59
+ // Store Buffer
60
+ const buffer = Buffer.from('Binary data');
61
+ await storage.put('path/to/file.bin', buffer);
62
+
63
+ // Store from Stream
64
+ const stream = fs.createReadStream('/path/to/source.txt');
65
+ await storage.put('path/to/destination.txt', stream);
66
+ ```
67
+
68
+ > **Note**: If a file already exists at the specified path, it will be overwritten.
69
+
70
+ ### Checking File Existence
6
71
 
7
72
  ```ts
8
- import { Storage, StorageFactory } from '@devbro/neko-storage';
73
+ const exists = await storage.exists('path/to/file.txt');
74
+ if (exists) {
75
+ console.log('File exists!');
76
+ }
77
+ ```
9
78
 
10
- const storage: Storage = StorageFactory.create(???);
79
+ ### Reading Files
11
80
 
12
- // put a file, if file exists already, it will override it.
13
- content : string | object | Stream | Buffer = ??? ;
14
- let success = await storage.put('path/to/file/filename.ext', content);
81
+ Retrieve files in different formats:
82
+
83
+ ```ts
84
+ // As JSON object
85
+ const data = await storage.getJson<{ name: string }>('config.json');
15
86
 
16
- // check if the file exists or not
17
- let file_exists = await storage.exists('path/to/file/filename.ext');
87
+ // As string
88
+ const text = await storage.getString('document.txt');
89
+
90
+ // As Buffer
91
+ const buffer = await storage.getBuffer('image.png');
92
+
93
+ // As Stream (for large files)
94
+ const stream = await storage.getStream('video.mp4');
95
+ stream.pipe(destination);
96
+ ```
18
97
 
19
- // get some details about the file, depending on type of drive metadata may differ
20
- let file_metadata = await storage.metadata('path/to/file/filename.ext');
21
- /*
98
+ > **Note**: All read methods throw an error if the file doesn't exist.
99
+
100
+ ### File Metadata
101
+
102
+ Get information about stored files:
103
+
104
+ ```ts
105
+ const metadata = await storage.metadata('path/to/file.txt');
106
+ console.log(metadata);
107
+ /* Output:
22
108
  {
23
- size: 12345; //bytes
24
- mimeType: 'application/json';
25
- lastModifiedDate: 'date string';
109
+ size: 12345, // File size in bytes
110
+ mimeType: 'text/plain', // MIME type
111
+ lastModifiedDate: '2026-01-31' // Last modified date
26
112
  }
27
113
  */
114
+ ```
28
115
 
29
- // get the file in the format you want, if fails it will throw an Error
30
- let file_content_as_Json = await storage.getJson('path/to/file/filename.ext');
31
- let file_content_as_String = await storage.getString('path/to/file/filename.ext');
32
- let file_content_as_Buffer = await storage.getBuffer('path/to/file/filename.ext');
33
- let file_content_as_Stream = await storage.getStream('path/to/file/filename.ext');
116
+ > **Note**: Available metadata fields may vary depending on the storage provider.
34
117
 
118
+ ### Deleting Files
35
119
 
36
- // delete a file
37
- let is_file_deleted = await storage.delete('path/to/file/filename.ext');
120
+ ```ts
121
+ const deleted = await storage.delete('path/to/file.txt');
122
+ console.log(deleted); // true if deleted, false if file didn't exist
38
123
  ```
39
124
 
40
- ## available drivers
125
+ ## Storage Providers
41
126
 
42
- ### Local Storage
127
+ ### Local File System
43
128
 
44
- Store files on the local file system.
129
+ Store files on the local disk.
45
130
 
46
131
  ```ts
47
132
  import { LocalStorageProvider, Storage } from '@devbro/neko-storage';
133
+ import path from 'path';
134
+ import os from 'os';
48
135
 
49
- const basePath = path.resolve(os.tmpdir(), `test-storage-${randomUUID()}`);
50
- const provider = new LocalStorageProvider({ engine: 'local', basePath });
136
+ const provider = new LocalStorageProvider({
137
+ engine: 'local',
138
+ basePath: path.join(os.tmpdir(), 'my-app-storage'),
139
+ });
51
140
  const storage = new Storage(provider);
52
141
  ```
53
142
 
143
+ **Configuration:**
144
+
145
+ - `engine`: `'local'`
146
+ - `basePath`: Absolute path to the storage directory
147
+
148
+ **Best for:** Development, testing, single-server deployments
149
+
150
+ ---
151
+
54
152
  ### AWS S3
55
153
 
56
154
  Store files in Amazon S3 buckets.
@@ -60,18 +158,30 @@ import { AWSS3StorageProvider, Storage } from '@devbro/neko-storage';
60
158
 
61
159
  const provider = new AWSS3StorageProvider({
62
160
  engine: 's3',
63
- bucket: 'your-bucket-name',
161
+ bucket: 'my-app-uploads',
64
162
  s3Config: {
65
163
  region: 'us-east-1',
66
164
  credentials: {
67
- accessKeyId: 'YOUR_ACCESS_KEY',
68
- secretAccessKey: 'YOUR_SECRET_KEY',
165
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
166
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
69
167
  },
70
168
  },
71
169
  });
72
170
  const storage = new Storage(provider);
73
171
  ```
74
172
 
173
+ **Configuration:**
174
+
175
+ - `engine`: `'s3'`
176
+ - `bucket`: S3 bucket name
177
+ - `s3Config`: AWS SDK configuration object
178
+ - `region`: AWS region
179
+ - `credentials`: Access credentials
180
+
181
+ **Best for:** Scalable cloud storage, CDN integration, high availability
182
+
183
+ ---
184
+
75
185
  ### Google Cloud Storage (GCP)
76
186
 
77
187
  Store files in Google Cloud Storage buckets.
@@ -81,20 +191,33 @@ import { GCPStorageProvider, Storage } from '@devbro/neko-storage';
81
191
 
82
192
  const provider = new GCPStorageProvider({
83
193
  engine: 'gcp',
84
- bucket: 'your-bucket-name',
194
+ bucket: 'my-app-uploads',
85
195
  gcpConfig: {
86
- projectId: 'your-project-id',
196
+ projectId: 'my-project-id',
87
197
  keyFilename: '/path/to/service-account-key.json',
88
- // Or use credentials object directly
89
- // credentials: {...}
198
+ // Alternative: Use credentials object
199
+ // credentials: require('./service-account-key.json'),
90
200
  },
91
201
  });
92
202
  const storage = new Storage(provider);
93
203
  ```
94
204
 
205
+ **Configuration:**
206
+
207
+ - `engine`: `'gcp'`
208
+ - `bucket`: GCS bucket name
209
+ - `gcpConfig`: Google Cloud configuration
210
+ - `projectId`: GCP project ID
211
+ - `keyFilename`: Path to service account JSON key file
212
+ - `credentials`: Or provide credentials object directly
213
+
214
+ **Best for:** Google Cloud Platform ecosystem, global distribution
215
+
216
+ ---
217
+
95
218
  ### Azure Blob Storage
96
219
 
97
- Store files in Azure Blob Storage containers.
220
+ Store files in Microsoft Azure Blob Storage containers.
98
221
 
99
222
  ```ts
100
223
  import { AzureBlobStorageProvider, Storage } from '@devbro/neko-storage';
@@ -102,14 +225,28 @@ import { AzureBlobStorageProvider, Storage } from '@devbro/neko-storage';
102
225
  const provider = new AzureBlobStorageProvider({
103
226
  engine: 'azure',
104
227
  azureConfig: {
105
- accountName: 'your-storage-account',
106
- accountKey: 'YOUR_ACCOUNT_KEY', // Or use sasToken instead
107
- containerName: 'your-container-name',
228
+ accountName: 'mystorageaccount',
229
+ accountKey: process.env.AZURE_STORAGE_KEY,
230
+ // Alternative: Use SAS token
231
+ // sasToken: process.env.AZURE_SAS_TOKEN,
232
+ containerName: 'uploads',
108
233
  },
109
234
  });
110
235
  const storage = new Storage(provider);
111
236
  ```
112
237
 
238
+ **Configuration:**
239
+
240
+ - `engine`: `'azure'`
241
+ - `azureConfig`: Azure storage configuration
242
+ - `accountName`: Azure storage account name
243
+ - `accountKey`: Account access key (or use `sasToken`)
244
+ - `containerName`: Blob container name
245
+
246
+ **Best for:** Microsoft Azure ecosystem, enterprise applications
247
+
248
+ ---
249
+
113
250
  ### FTP
114
251
 
115
252
  Store files on FTP servers.
@@ -119,39 +256,198 @@ import { FTPStorageProvider, Storage } from '@devbro/neko-storage';
119
256
 
120
257
  const provider = new FTPStorageProvider({
121
258
  engine: 'ftp',
122
- basePath: '/remote/path',
259
+ basePath: '/uploads',
123
260
  FTPStorageProviderConfig: {
124
261
  host: 'ftp.example.com',
125
262
  port: 21,
126
- user: 'username',
127
- password: 'password',
128
- secure: false, // Set to true for FTPS
263
+ user: process.env.FTP_USER,
264
+ password: process.env.FTP_PASSWORD,
265
+ secure: false, // Set to true for FTPS (FTP over SSL/TLS)
129
266
  },
130
267
  });
131
268
  const storage = new Storage(provider);
132
269
  ```
133
270
 
271
+ **Configuration:**
272
+
273
+ - `engine`: `'ftp'`
274
+ - `basePath`: Remote directory path
275
+ - `FTPStorageProviderConfig`: FTP connection settings
276
+ - `host`: FTP server hostname
277
+ - `port`: FTP port (default: 21)
278
+ - `user`: Username
279
+ - `password`: Password
280
+ - `secure`: Enable FTPS (default: false)
281
+
282
+ **Best for:** Legacy systems, shared hosting environments
283
+
284
+ ---
285
+
134
286
  ### SFTP
135
287
 
136
288
  Store files on SFTP servers via SSH.
137
289
 
138
290
  ```ts
139
291
  import { SFTPStorageProvider, Storage } from '@devbro/neko-storage';
292
+ import fs from 'fs';
140
293
 
141
294
  const provider = new SFTPStorageProvider({
142
295
  engine: 'sftp',
143
- basePath: '/remote/path',
296
+ basePath: '/home/user/uploads',
144
297
  SFTPStorageProviderConfig: {
145
298
  host: 'sftp.example.com',
146
299
  port: 22,
147
- username: 'username',
148
- password: 'password',
149
- // Or use private key authentication
300
+ username: process.env.SFTP_USER,
301
+ // Password authentication
302
+ password: process.env.SFTP_PASSWORD,
303
+ // Or use SSH key authentication
150
304
  // privateKey: fs.readFileSync('/path/to/private-key'),
151
- // passphrase: 'key-passphrase',
305
+ // passphrase: 'key-passphrase', // if key is encrypted
152
306
  },
153
307
  });
154
308
  const storage = new Storage(provider);
155
309
  ```
156
310
 
157
- More driver available upon request or through PR.
311
+ **Configuration:**
312
+
313
+ - `engine`: `'sftp'`
314
+ - `basePath`: Remote directory path
315
+ - `SFTPStorageProviderConfig`: SSH/SFTP connection settings
316
+ - `host`: SFTP server hostname
317
+ - `port`: SSH port (default: 22)
318
+ - `username`: Username
319
+ - `password`: Password (or use `privateKey`)
320
+ - `privateKey`: SSH private key (Buffer or string)
321
+ - `passphrase`: Private key passphrase (if encrypted)
322
+
323
+ **Best for:** Secure file transfers, SSH-enabled servers
324
+
325
+ ## Advanced Usage
326
+
327
+ ### Environment-Based Provider Selection
328
+
329
+ Switch storage providers based on environment:
330
+
331
+ ```ts
332
+ import { Storage, LocalStorageProvider, AWSS3StorageProvider } from '@devbro/neko-storage';
333
+
334
+ function createStorage(): Storage {
335
+ if (process.env.NODE_ENV === 'production') {
336
+ // Use S3 in production
337
+ return new Storage(
338
+ new AWSS3StorageProvider({
339
+ engine: 's3',
340
+ bucket: process.env.S3_BUCKET,
341
+ s3Config: {
342
+ region: process.env.AWS_REGION,
343
+ credentials: {
344
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
345
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
346
+ },
347
+ },
348
+ })
349
+ );
350
+ } else {
351
+ // Use local storage in development
352
+ return new Storage(
353
+ new LocalStorageProvider({
354
+ engine: 'local',
355
+ basePath: './storage',
356
+ })
357
+ );
358
+ }
359
+ }
360
+
361
+ export const storage = createStorage();
362
+ ```
363
+
364
+ ### Handling Large Files with Streams
365
+
366
+ For large files, use streams to avoid memory issues:
367
+
368
+ ```ts
369
+ import fs from 'fs';
370
+
371
+ // Upload large file
372
+ const uploadStream = fs.createReadStream('./large-video.mp4');
373
+ await storage.put('videos/upload.mp4', uploadStream);
374
+
375
+ // Download large file
376
+ const downloadStream = await storage.getStream('videos/upload.mp4');
377
+ const writeStream = fs.createWriteStream('./downloaded-video.mp4');
378
+ downloadStream.pipe(writeStream);
379
+
380
+ await new Promise((resolve, reject) => {
381
+ writeStream.on('finish', resolve);
382
+ writeStream.on('error', reject);
383
+ });
384
+ ```
385
+
386
+ ### Error Handling
387
+
388
+ ```ts
389
+ try {
390
+ const content = await storage.getString('path/to/file.txt');
391
+ console.log(content);
392
+ } catch (error) {
393
+ if (error.code === 'ENOENT') {
394
+ console.error('File not found');
395
+ } else {
396
+ console.error('Error reading file:', error.message);
397
+ }
398
+ }
399
+ ```
400
+
401
+ ## Best Practices
402
+
403
+ 1. **Use Environment Variables** - Store credentials in environment variables, never in code
404
+ 2. **Check Existence** - Use `exists()` before reading if the file might not exist
405
+ 3. **Use Streams for Large Files** - Avoid loading large files into memory
406
+ 4. **Handle Errors** - Always wrap storage operations in try-catch blocks
407
+ 5. **Path Consistency** - Use forward slashes `/` in paths for all providers
408
+ 6. **Provider Abstraction** - Design your app to work with any provider
409
+
410
+ ## TypeScript Support
411
+
412
+ Full TypeScript definitions are included:
413
+
414
+ ```ts
415
+ import { Storage, StorageProvider, FileMetadata } from '@devbro/neko-storage';
416
+
417
+ // Type-safe metadata
418
+ const metadata: FileMetadata = await storage.metadata('file.txt');
419
+
420
+ // Generic type support for JSON
421
+ interface UserConfig {
422
+ theme: string;
423
+ language: string;
424
+ }
425
+
426
+ const config = await storage.getJson<UserConfig>('config.json');
427
+ console.log(config.theme); // Type-safe!
428
+ ```
429
+
430
+ ## Contributing
431
+
432
+ We welcome contributions! If you need a storage provider that's not listed:
433
+
434
+ 1. Open an issue to discuss the provider
435
+ 2. Submit a pull request with implementation
436
+ 3. Ensure tests are included
437
+
438
+ Popular providers we'd love to see:
439
+
440
+ - DigitalOcean Spaces
441
+ - Cloudflare R2
442
+ - MinIO
443
+ - WebDAV
444
+
445
+ ## License
446
+
447
+ MIT
448
+
449
+ ## Related Packages
450
+
451
+ - [@devbro/neko-cache](https://www.npmjs.com/package/@devbro/neko-cache) - Caching solution
452
+ - [@devbro/neko-config](https://www.npmjs.com/package/@devbro/neko-config) - Configuration management
453
+ - [@devbro/pashmak](https://www.npmjs.com/package/@devbro/pashmak) - Full-stack TypeScript framework
@@ -0,0 +1,159 @@
1
+ import { S3ClientConfig } from '@aws-sdk/client-s3';
2
+ import { StorageOptions } from '@google-cloud/storage';
3
+ import { ReadStream } from 'fs';
4
+ import Stream$1, { Stream } from 'stream';
5
+ import { FlexibleFactory } from '@devbro/neko-helper';
6
+
7
+ type Metadata = {
8
+ size: number;
9
+ mimeType: string;
10
+ lastModifiedDate: string;
11
+ };
12
+ type AzureBlobStorageProviderConfig = {
13
+ accountName: string;
14
+ accountKey?: string;
15
+ sasToken?: string;
16
+ containerName: string;
17
+ };
18
+ type FTPStorageProviderConfig = {
19
+ host: string;
20
+ port?: number;
21
+ user?: string;
22
+ password?: string;
23
+ secure?: boolean;
24
+ };
25
+ type SFTPStorageProviderConfig = {
26
+ host: string;
27
+ port?: number;
28
+ username?: string;
29
+ password?: string;
30
+ privateKey?: string;
31
+ passphrase?: string;
32
+ };
33
+ type AWSS3StorageProviderConfig = S3ClientConfig & {
34
+ bucket: string;
35
+ };
36
+ type LocalStorageProviderConfig = {
37
+ basePath: string;
38
+ };
39
+ type GCPStorageProviderConfig = StorageOptions & {
40
+ bucket: string;
41
+ };
42
+
43
+ interface StorageProviderInterface {
44
+ exists(path: string): Promise<boolean>;
45
+ put(path: string, content: string | object | Stream | Buffer): Promise<boolean>;
46
+ getJson(path: string): Promise<object>;
47
+ getString(path: string): Promise<string>;
48
+ getBuffer(path: string): Promise<Buffer>;
49
+ getStream(path: string): Promise<ReadStream>;
50
+ delete(path: string): Promise<boolean>;
51
+ metadata(path: string): Promise<Metadata>;
52
+ }
53
+
54
+ declare class Storage {
55
+ protected provider: StorageProviderInterface;
56
+ constructor(provider: StorageProviderInterface);
57
+ exists(path: string): Promise<boolean>;
58
+ put(path: string, content: string | object | Stream | Buffer): Promise<boolean>;
59
+ getJson(path: string): Promise<object>;
60
+ getString(path: string): Promise<string>;
61
+ getBuffer(path: string): Promise<Buffer>;
62
+ getStream(path: string): Promise<ReadStream>;
63
+ delete(path: string): Promise<boolean>;
64
+ metadata(path: string): Promise<Metadata>;
65
+ }
66
+
67
+ declare class AWSS3StorageProvider implements StorageProviderInterface {
68
+ protected config: AWSS3StorageProviderConfig;
69
+ private s3;
70
+ constructor(config: AWSS3StorageProviderConfig);
71
+ exists(path: string): Promise<boolean>;
72
+ put(path: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
73
+ getJson(path: string): Promise<object>;
74
+ getString(path: string): Promise<string>;
75
+ delete(path: string): Promise<boolean>;
76
+ private streamToString;
77
+ getBuffer(path: string): Promise<Buffer>;
78
+ getStream(path: string): Promise<ReadStream>;
79
+ metadata(path: string): Promise<Metadata>;
80
+ }
81
+
82
+ declare class LocalStorageProvider implements StorageProviderInterface {
83
+ private config;
84
+ constructor(config: LocalStorageProviderConfig);
85
+ metadata(path: string): Promise<Metadata>;
86
+ getFullPath(filePath: string): string;
87
+ exists(path: string): Promise<boolean>;
88
+ put(filepath: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
89
+ getJson(path: string): Promise<object>;
90
+ getString(path: string, encoding?: BufferEncoding): Promise<string>;
91
+ getBuffer(path: string): Promise<Buffer>;
92
+ getStream(path: string): Promise<ReadStream>;
93
+ delete(path: string): Promise<boolean>;
94
+ }
95
+
96
+ declare class GCPStorageProvider implements StorageProviderInterface {
97
+ protected config: GCPStorageProviderConfig;
98
+ private storage;
99
+ constructor(config: GCPStorageProviderConfig);
100
+ exists(path: string): Promise<boolean>;
101
+ put(path: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
102
+ getJson(path: string): Promise<object>;
103
+ getString(path: string): Promise<string>;
104
+ getBuffer(path: string): Promise<Buffer>;
105
+ getStream(path: string): Promise<ReadStream>;
106
+ delete(path: string): Promise<boolean>;
107
+ metadata(path: string): Promise<Metadata>;
108
+ }
109
+
110
+ declare class AzureBlobStorageProvider implements StorageProviderInterface {
111
+ protected config: AzureBlobStorageProviderConfig;
112
+ private blobServiceClient;
113
+ constructor(config: AzureBlobStorageProviderConfig);
114
+ exists(path: string): Promise<boolean>;
115
+ put(path: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
116
+ getJson(path: string): Promise<object>;
117
+ getString(path: string): Promise<string>;
118
+ getBuffer(path: string): Promise<Buffer>;
119
+ getStream(path: string): Promise<ReadStream>;
120
+ delete(path: string): Promise<boolean>;
121
+ metadata(path: string): Promise<Metadata>;
122
+ private streamToBuffer;
123
+ }
124
+
125
+ declare class FTPStorageProvider implements StorageProviderInterface {
126
+ private config;
127
+ constructor(config: FTPStorageProviderConfig);
128
+ private getClient;
129
+ exists(path: string): Promise<boolean>;
130
+ put(path: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
131
+ getJson(path: string): Promise<object>;
132
+ getString(path: string): Promise<string>;
133
+ getBuffer(path: string): Promise<Buffer>;
134
+ getStream(path: string): Promise<ReadStream>;
135
+ delete(path: string): Promise<boolean>;
136
+ metadata(path: string): Promise<Metadata>;
137
+ }
138
+
139
+ declare class SFTPStorageProvider implements StorageProviderInterface {
140
+ private config;
141
+ constructor(config: SFTPStorageProviderConfig);
142
+ private getClient;
143
+ exists(path: string): Promise<boolean>;
144
+ put(path: string, content: string | object | Stream$1 | Buffer): Promise<boolean>;
145
+ getJson(path: string): Promise<object>;
146
+ getString(path: string): Promise<string>;
147
+ getBuffer(path: string): Promise<Buffer>;
148
+ getStream(path: string): Promise<ReadStream>;
149
+ delete(path: string): Promise<boolean>;
150
+ metadata(path: string): Promise<Metadata>;
151
+ }
152
+
153
+ declare class StorageProviderFactory {
154
+ static instance: FlexibleFactory<StorageProviderInterface>;
155
+ static register(key: string, factory: (...args: any[]) => StorageProviderInterface): void;
156
+ static create(key: string, ...args: any[]): StorageProviderInterface;
157
+ }
158
+
159
+ export { AWSS3StorageProvider, type AWSS3StorageProviderConfig, AzureBlobStorageProvider, type AzureBlobStorageProviderConfig, FTPStorageProvider, type FTPStorageProviderConfig, GCPStorageProvider, type GCPStorageProviderConfig, LocalStorageProvider, type LocalStorageProviderConfig, type Metadata, SFTPStorageProvider, type SFTPStorageProviderConfig, Storage, StorageProviderFactory, type StorageProviderInterface };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Storage.mts","../../src/providers/AWSS3StorageProvider.mts","../../src/providers/LocalStorageProvider.mts","../../src/providers/GCPStorageProvider.mts","../../src/providers/AzureBlobStorageProvider.mts","../../src/providers/FTPStorageProvider.mts","../../src/providers/SFTPStorageProvider.mts","../../src/StorageProviderFactory.mts"],"sourcesContent":["export * from './types.mjs';\nexport * from './Storage.mjs';\nexport * from './providers/AWSS3StorageProvider.mjs';\nexport * from './providers/LocalStorageProvider.mjs';\nexport * from './providers/GCPStorageProvider.mjs';\nexport * from './providers/AzureBlobStorageProvider.mjs';\nexport * from './providers/FTPStorageProvider.mjs';\nexport * from './providers/SFTPStorageProvider.mjs';\nexport * from './StorageProviderFactory.mjs';\nexport * from './StorageProviderInterface.mjs';\n","import { ReadStream } from 'fs';\nimport { Stream } from 'stream';\nimport { Metadata } from './types.mjs';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class Storage {\n constructor(protected provider: StorageProviderInterface) {}\n\n exists(path: string): Promise<boolean> {\n return this.provider.exists(path);\n }\n\n put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n return this.provider.put(path, content);\n }\n\n getJson(path: string): Promise<object> {\n return this.provider.getJson(path);\n }\n\n getString(path: string): Promise<string> {\n return this.provider.getString(path);\n }\n\n getBuffer(path: string): Promise<Buffer> {\n return this.provider.getBuffer(path);\n }\n\n getStream(path: string): Promise<ReadStream> {\n return this.provider.getStream(path);\n }\n\n delete(path: string): Promise<boolean> {\n return this.provider.delete(path);\n }\n\n metadata(path: string): Promise<Metadata> {\n return this.provider.metadata(path);\n }\n}\n","import { Metadata, AWSS3StorageProviderConfig } from '../types.mjs';\nimport {\n S3Client,\n HeadObjectCommand,\n PutObjectCommand,\n GetObjectCommand,\n DeleteObjectCommand,\n} from '@aws-sdk/client-s3';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class AWSS3StorageProvider implements StorageProviderInterface {\n private s3: S3Client;\n\n constructor(protected config: AWSS3StorageProviderConfig) {\n this.s3 = new S3Client(this.config);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.s3.send(new HeadObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound') {\n return false;\n }\n throw error;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n let body: any;\n if (typeof content === 'string' || content instanceof Buffer) {\n body = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n body = JSON.stringify(content);\n } else if (content instanceof Stream) {\n body = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.config.bucket,\n Key: path,\n Body: body,\n })\n );\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const body = await this.streamToString(data.Body as Stream);\n return JSON.parse(body);\n }\n\n async getString(path: string): Promise<string> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return await this.streamToString(data.Body as Stream);\n }\n\n async delete(path: string): Promise<boolean> {\n await this.s3.send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n }\n\n private async streamToString(stream: Stream): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stream.on('error', reject);\n });\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const chunks: Uint8Array[] = [];\n const stream = data.Body as Readable;\n\n return new Promise((resolve, reject) => {\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return data.Body as unknown as ReadStream;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const metadata = await this.s3.send(\n new HeadObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return {\n size: metadata.ContentLength || 0,\n mimeType: metadata.ContentType || 'unknown',\n lastModifiedDate: (metadata.LastModified || new Date(0)).toISOString(),\n };\n }\n}\n","import Stream from 'stream';\nimport * as fs from 'fs/promises';\nimport { createWriteStream, createReadStream, ReadStream } from 'fs';\nimport * as path from 'path';\nimport * as mime from 'mime-types';\nimport { Metadata, LocalStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class LocalStorageProvider implements StorageProviderInterface {\n constructor(private config: LocalStorageProviderConfig) {\n // Ensure the base folder exists\n fs.mkdir(this.config.basePath, { recursive: true }).catch((error) => {\n throw error;\n });\n }\n\n async metadata(path: string): Promise<Metadata> {\n const fullPath = this.getFullPath(path);\n const stats = await fs.stat(fullPath);\n return {\n size: stats.size,\n mimeType: mime.lookup(fullPath) || 'unknown',\n lastModifiedDate: stats.mtime.toISOString(),\n };\n }\n\n getFullPath(filePath: string) {\n return path.join(this.config.basePath, filePath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await fs.access(this.getFullPath(path));\n return true;\n } catch {\n return false;\n }\n }\n\n async put(filepath: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const fullPath = this.getFullPath(filepath);\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n if (typeof content === 'string' || content instanceof Buffer) {\n await fs.writeFile(fullPath, content);\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n await fs.writeFile(fullPath, JSON.stringify(content, null, 2));\n } else if (typeof content === 'object' && content instanceof Stream) {\n const writeStream = createWriteStream(fullPath);\n await new Promise((resolve, reject) => {\n (content as Stream).pipe(writeStream);\n (content as Stream).on('end', resolve);\n (content as Stream).on('error', reject);\n });\n } else {\n throw new Error('Unsupported content type');\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const fullPath = this.getFullPath(path);\n const content = await fs.readFile(fullPath, 'utf-8');\n return JSON.parse(content);\n }\n\n async getString(path: string, encoding: BufferEncoding = 'utf-8'): Promise<string> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath, encoding);\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const fullPath = this.getFullPath(path);\n return createReadStream(fullPath);\n }\n\n async delete(path: string): Promise<boolean> {\n const fullPath = this.getFullPath(path);\n await fs.unlink(fullPath);\n return true;\n }\n}\n","import { Storage as GCPStorage } from '@google-cloud/storage';\nimport { Metadata, GCPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream from 'stream';\nimport * as mime from 'mime-types';\n\nexport class GCPStorageProvider implements StorageProviderInterface {\n private storage: GCPStorage;\n\n constructor(protected config: GCPStorageProviderConfig) {\n const { bucket, ...gcpOptions } = config;\n this.storage = new GCPStorage(gcpOptions);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [exists] = await file.exists();\n return exists;\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await new Promise<void>((resolve, reject) => {\n data\n .pipe(file.createWriteStream())\n .on('finish', () => resolve())\n .on('error', reject);\n });\n } else {\n await file.save(data);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content;\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n return file.createReadStream() as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n await file.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [metadata] = await file.getMetadata();\n\n return {\n size: typeof metadata.size === 'number' ? metadata.size : parseInt(metadata.size || '0', 10),\n mimeType: metadata.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: metadata.updated || new Date(0).toISOString(),\n };\n }\n}\n","import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';\nimport { Metadata, AzureBlobStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class AzureBlobStorageProvider implements StorageProviderInterface {\n private blobServiceClient: BlobServiceClient;\n\n constructor(protected config: AzureBlobStorageProviderConfig) {\n const { accountName, accountKey, sasToken } = config;\n\n if (accountKey) {\n const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n sharedKeyCredential\n );\n } else if (sasToken) {\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net?${sasToken}`\n );\n } else {\n throw new Error('Either accountKey or sasToken is required for Azure Blob Storage');\n }\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n return await blobClient.exists();\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blockBlobClient = containerClient.getBlockBlobClient(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await blockBlobClient.uploadStream(data as Readable);\n } else {\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n await blockBlobClient.upload(buffer, buffer.length);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return await this.streamToBuffer(downloadResponse.readableStreamBody);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return downloadResponse.readableStreamBody as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n await blobClient.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const properties = await blobClient.getProperties();\n\n return {\n size: properties.contentLength || 0,\n mimeType: properties.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: properties.lastModified?.toISOString() || new Date(0).toISOString(),\n };\n }\n\n private async streamToBuffer(readableStream: NodeJS.ReadableStream): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n readableStream.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n readableStream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n readableStream.on('error', reject);\n });\n }\n}\n","import { Client as FTPClient } from 'basic-ftp';\nimport { Metadata, FTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class FTPStorageProvider implements StorageProviderInterface {\n constructor(private config: FTPStorageProviderConfig) {}\n\n private async getClient(): Promise<FTPClient> {\n const client = new FTPClient();\n await client.access({\n host: this.config.host,\n port: this.config.port || 21,\n user: this.config.user || 'anonymous',\n password: this.config.password || '',\n secure: this.config.secure || false,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.size(path);\n return true;\n } catch (error) {\n return false;\n } finally {\n client.close();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let stream: Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n const readable = new Readable();\n readable.push(typeof content === 'string' ? Buffer.from(content) : content);\n readable.push(null);\n stream = readable;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n const readable = new Readable();\n readable.push(Buffer.from(JSON.stringify(content)));\n readable.push(null);\n stream = readable;\n } else if (content instanceof Stream) {\n stream = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.uploadFrom(stream as Readable, path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const chunks: Buffer[] = [];\n const writable = new PassThrough();\n\n writable.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n await client.downloadTo(writable, path);\n\n return Buffer.concat(chunks);\n } finally {\n client.close();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Download to stream and close client when done\n client\n .downloadTo(passThrough, path)\n .then(() => client.close())\n .catch((error) => {\n client.close();\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n try {\n client.close();\n } catch {\n // Ignore errors if already closed\n }\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.remove(path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const size = await client.size(path);\n const lastMod = await client.lastMod(path);\n\n return {\n size: size,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: lastMod?.toISOString() || new Date(0).toISOString(),\n };\n } finally {\n client.close();\n }\n }\n}\n","import SFTPClient from 'ssh2-sftp-client';\nimport { Metadata, SFTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class SFTPStorageProvider implements StorageProviderInterface {\n constructor(private config: SFTPStorageProviderConfig) {}\n\n private async getClient(): Promise<SFTPClient> {\n const client = new SFTPClient();\n await client.connect({\n host: this.config.host,\n port: this.config.port || 22,\n username: this.config.username,\n password: this.config.password,\n privateKey: this.config.privateKey,\n passphrase: this.config.passphrase,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n const result = await client.exists(path);\n return result !== false;\n } catch (error) {\n return false;\n } finally {\n await client.end();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let data: string | Buffer | Readable;\n if (typeof content === 'string') {\n data = content;\n } else if (content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = Buffer.from(JSON.stringify(content));\n } else if (content instanceof Stream) {\n data = content as Readable;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.put(data, path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const buffer = await client.get(path);\n return buffer as Buffer;\n } finally {\n await client.end();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Get the file as a stream and close client when done\n client\n .get(path)\n .then((data) => {\n if (data instanceof Buffer) {\n const readable = new Readable();\n readable.push(data);\n readable.push(null);\n readable.pipe(passThrough);\n } else if (data instanceof Stream) {\n (data as Stream).pipe(passThrough);\n }\n return client.end();\n })\n .catch((error) => {\n client.end().catch(() => {\n // Ignore errors when closing client during error handling\n });\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n client.end().catch(() => {\n // Ignore errors if already closed\n });\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.delete(path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const stats = await client.stat(path);\n\n return {\n size: stats.size || 0,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: new Date((stats.modifyTime || 0) * 1000).toISOString(),\n };\n } finally {\n await client.end();\n }\n }\n}\n","import { FlexibleFactory } from '@devbro/neko-helper';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class StorageProviderFactory {\n static instance: FlexibleFactory<StorageProviderInterface> =\n new FlexibleFactory<StorageProviderInterface>();\n\n static register(key: string, factory: (...args: any[]) => StorageProviderInterface): void {\n StorageProviderFactory.instance.register(key, factory);\n }\n\n static create(key: string, ...args: any[]): StorageProviderInterface {\n return StorageProviderFactory.instance.create(key, ...args);\n }\n}\n"],"mappings":"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","names":["path","path","Stream","import_stream","path","Stream","import_stream","mime","GCPStorage","path","Stream","import_stream","mime","path","Stream","import_stream","mime","FTPClient","path","Stream","import_stream","mime","SFTPClient","path","Stream"]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Storage.mts"],"sourcesContent":["import { ReadStream } from 'fs';\nimport { Stream } from 'stream';\nimport { Metadata } from './types.mjs';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class Storage {\n constructor(protected provider: StorageProviderInterface) {}\n\n exists(path: string): Promise<boolean> {\n return this.provider.exists(path);\n }\n\n put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n return this.provider.put(path, content);\n }\n\n getJson(path: string): Promise<object> {\n return this.provider.getJson(path);\n }\n\n getString(path: string): Promise<string> {\n return this.provider.getString(path);\n }\n\n getBuffer(path: string): Promise<Buffer> {\n return this.provider.getBuffer(path);\n }\n\n getStream(path: string): Promise<ReadStream> {\n return this.provider.getStream(path);\n }\n\n delete(path: string): Promise<boolean> {\n return this.provider.delete(path);\n }\n\n metadata(path: string): Promise<Metadata> {\n return this.provider.metadata(path);\n }\n}\n"],"mappings":";;AAKO,MAAM,QAAQ;AAAA,EACnB,YAAsB,UAAoC;AAApC;AAAA,EAAqC;AAAA,EAN7D,OAKqB;AAAA;AAAA;AAAA,EAGnB,OAAO,MAAgC;AACrC,WAAO,KAAK,SAAS,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,IAAI,MAAc,SAA8D;AAC9E,WAAO,KAAK,SAAS,IAAI,MAAM,OAAO;AAAA,EACxC;AAAA,EAEA,QAAQ,MAA+B;AACrC,WAAO,KAAK,SAAS,QAAQ,IAAI;AAAA,EACnC;AAAA,EAEA,UAAU,MAA+B;AACvC,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,UAAU,MAA+B;AACvC,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,UAAU,MAAmC;AAC3C,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,OAAO,MAAgC;AACrC,WAAO,KAAK,SAAS,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,SAAS,MAAiC;AACxC,WAAO,KAAK,SAAS,SAAS,IAAI;AAAA,EACpC;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/StorageProviderFactory.mts"],"sourcesContent":["import { FlexibleFactory } from '@devbro/neko-helper';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class StorageProviderFactory {\n static instance: FlexibleFactory<StorageProviderInterface> =\n new FlexibleFactory<StorageProviderInterface>();\n\n static register(key: string, factory: (...args: any[]) => StorageProviderInterface): void {\n StorageProviderFactory.instance.register(key, factory);\n }\n\n static create(key: string, ...args: any[]): StorageProviderInterface {\n return StorageProviderFactory.instance.create(key, ...args);\n }\n}\n"],"mappings":";;AAAA,SAAS,uBAAuB;AAGzB,MAAM,uBAAuB;AAAA,EAHpC,OAGoC;AAAA;AAAA;AAAA,EAClC,OAAO,WACL,IAAI,gBAA0C;AAAA,EAEhD,OAAO,SAAS,KAAa,SAA6D;AACxF,2BAAuB,SAAS,SAAS,KAAK,OAAO;AAAA,EACvD;AAAA,EAEA,OAAO,OAAO,QAAgB,MAAuC;AACnE,WAAO,uBAAuB,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EAC5D;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from './types.mjs';\nexport * from './Storage.mjs';\nexport * from './providers/AWSS3StorageProvider.mjs';\nexport * from './providers/LocalStorageProvider.mjs';\nexport * from './providers/GCPStorageProvider.mjs';\nexport * from './providers/AzureBlobStorageProvider.mjs';\nexport * from './providers/FTPStorageProvider.mjs';\nexport * from './providers/SFTPStorageProvider.mjs';\nexport * from './StorageProviderFactory.mjs';\nexport * from './StorageProviderInterface.mjs';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/AWSS3StorageProvider.mts"],"sourcesContent":["import { Metadata, AWSS3StorageProviderConfig } from '../types.mjs';\nimport {\n S3Client,\n HeadObjectCommand,\n PutObjectCommand,\n GetObjectCommand,\n DeleteObjectCommand,\n} from '@aws-sdk/client-s3';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class AWSS3StorageProvider implements StorageProviderInterface {\n private s3: S3Client;\n\n constructor(protected config: AWSS3StorageProviderConfig) {\n this.s3 = new S3Client(this.config);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.s3.send(new HeadObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound') {\n return false;\n }\n throw error;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n let body: any;\n if (typeof content === 'string' || content instanceof Buffer) {\n body = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n body = JSON.stringify(content);\n } else if (content instanceof Stream) {\n body = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.config.bucket,\n Key: path,\n Body: body,\n })\n );\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const body = await this.streamToString(data.Body as Stream);\n return JSON.parse(body);\n }\n\n async getString(path: string): Promise<string> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return await this.streamToString(data.Body as Stream);\n }\n\n async delete(path: string): Promise<boolean> {\n await this.s3.send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n }\n\n private async streamToString(stream: Stream): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stream.on('error', reject);\n });\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const chunks: Uint8Array[] = [];\n const stream = data.Body as Readable;\n\n return new Promise((resolve, reject) => {\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return data.Body as unknown as ReadStream;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const metadata = await this.s3.send(\n new HeadObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return {\n size: metadata.ContentLength || 0,\n mimeType: metadata.ContentType || 'unknown',\n lastModifiedDate: (metadata.LastModified || new Date(0)).toISOString(),\n };\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/AzureBlobStorageProvider.mts"],"sourcesContent":["import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';\nimport { Metadata, AzureBlobStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class AzureBlobStorageProvider implements StorageProviderInterface {\n private blobServiceClient: BlobServiceClient;\n\n constructor(protected config: AzureBlobStorageProviderConfig) {\n const { accountName, accountKey, sasToken } = config;\n\n if (accountKey) {\n const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n sharedKeyCredential\n );\n } else if (sasToken) {\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net?${sasToken}`\n );\n } else {\n throw new Error('Either accountKey or sasToken is required for Azure Blob Storage');\n }\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n return await blobClient.exists();\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blockBlobClient = containerClient.getBlockBlobClient(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await blockBlobClient.uploadStream(data as Readable);\n } else {\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n await blockBlobClient.upload(buffer, buffer.length);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return await this.streamToBuffer(downloadResponse.readableStreamBody);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return downloadResponse.readableStreamBody as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n await blobClient.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const properties = await blobClient.getProperties();\n\n return {\n size: properties.contentLength || 0,\n mimeType: properties.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: properties.lastModified?.toISOString() || new Date(0).toISOString(),\n };\n }\n\n private async streamToBuffer(readableStream: NodeJS.ReadableStream): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n readableStream.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n readableStream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n readableStream.on('error', reject);\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/FTPStorageProvider.mts"],"sourcesContent":["import { Client as FTPClient } from 'basic-ftp';\nimport { Metadata, FTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class FTPStorageProvider implements StorageProviderInterface {\n constructor(private config: FTPStorageProviderConfig) {}\n\n private async getClient(): Promise<FTPClient> {\n const client = new FTPClient();\n await client.access({\n host: this.config.host,\n port: this.config.port || 21,\n user: this.config.user || 'anonymous',\n password: this.config.password || '',\n secure: this.config.secure || false,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.size(path);\n return true;\n } catch (error) {\n return false;\n } finally {\n client.close();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let stream: Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n const readable = new Readable();\n readable.push(typeof content === 'string' ? Buffer.from(content) : content);\n readable.push(null);\n stream = readable;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n const readable = new Readable();\n readable.push(Buffer.from(JSON.stringify(content)));\n readable.push(null);\n stream = readable;\n } else if (content instanceof Stream) {\n stream = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.uploadFrom(stream as Readable, path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const chunks: Buffer[] = [];\n const writable = new PassThrough();\n\n writable.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n await client.downloadTo(writable, path);\n\n return Buffer.concat(chunks);\n } finally {\n client.close();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Download to stream and close client when done\n client\n .downloadTo(passThrough, path)\n .then(() => client.close())\n .catch((error) => {\n client.close();\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n try {\n client.close();\n } catch {\n // Ignore errors if already closed\n }\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.remove(path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const size = await client.size(path);\n const lastMod = await client.lastMod(path);\n\n return {\n size: size,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: lastMod?.toISOString() || new Date(0).toISOString(),\n };\n } finally {\n client.close();\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/GCPStorageProvider.mts"],"sourcesContent":["import { Storage as GCPStorage } from '@google-cloud/storage';\nimport { Metadata, GCPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream from 'stream';\nimport * as mime from 'mime-types';\n\nexport class GCPStorageProvider implements StorageProviderInterface {\n private storage: GCPStorage;\n\n constructor(protected config: GCPStorageProviderConfig) {\n const { bucket, ...gcpOptions } = config;\n this.storage = new GCPStorage(gcpOptions);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [exists] = await file.exists();\n return exists;\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await new Promise<void>((resolve, reject) => {\n data\n .pipe(file.createWriteStream())\n .on('finish', () => resolve())\n .on('error', reject);\n });\n } else {\n await file.save(data);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content;\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n return file.createReadStream() as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n await file.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [metadata] = await file.getMetadata();\n\n return {\n size: typeof metadata.size === 'number' ? metadata.size : parseInt(metadata.size || '0', 10),\n mimeType: metadata.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: metadata.updated || new Date(0).toISOString(),\n };\n }\n}\n"],"mappings":";;AAAA,SAAS,WAAW,kBAAkB;AAItC,OAAO,YAAY;AACnB,YAAY,UAAU;AAEf,MAAM,mBAAuD;AAAA,EAGlE,YAAsB,QAAkC;AAAlC;AACpB,UAAM,EAAE,QAAQ,GAAG,WAAW,IAAI;AAClC,SAAK,UAAU,IAAI,WAAW,UAAU;AAAA,EAC1C;AAAA,EAbF,OAOoE;AAAA;AAAA;AAAA,EAC1D;AAAA,EAOR,MAAM,OAAO,MAAgC;AAC3C,QAAI;AACF,YAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,YAAM,CAAC,MAAM,IAAI,MAAM,KAAK,OAAO;AACnC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,MAAc,SAA8D;AACpF,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAE9D,QAAI;AACJ,QAAI,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AAC5D,aAAO;AAAA,IACT,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,aAAO,KAAK,UAAU,OAAO;AAAA,IAC/B,WAAW,mBAAmB,QAAQ;AACpC,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,QAAI,gBAAgB,QAAQ;AAC1B,YAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,aACG,KAAK,KAAK,kBAAkB,CAAC,EAC7B,GAAG,UAAU,MAAM,QAAQ,CAAC,EAC5B,GAAG,SAAS,MAAM;AAAA,MACvB,CAAC;AAAA,IACH,OAAO;AACL,YAAM,KAAK,KAAK,IAAI;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,MAA+B;AAC3C,UAAM,OAAO,MAAM,KAAK,UAAU,IAAI;AACtC,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,OAAO,IAAI,MAAM,KAAK,SAAS;AACtC,WAAO,QAAQ,SAAS,OAAO;AAAA,EACjC;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,OAAO,IAAI,MAAM,KAAK,SAAS;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,MAAmC;AACjD,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,KAAK,OAAO;AAClB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAiC;AAC9C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,QAAQ,IAAI,MAAM,KAAK,YAAY;AAE1C,WAAO;AAAA,MACL,MAAM,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS,QAAQ,KAAK,EAAE;AAAA,MAC3F,UAAU,SAAS,eAAe,KAAK,OAAO,IAAI,KAAK;AAAA,MACvD,kBAAkB,SAAS,YAAW,oBAAI,KAAK,CAAC,GAAE,YAAY;AAAA,IAChE;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/LocalStorageProvider.mts"],"sourcesContent":["import Stream from 'stream';\nimport * as fs from 'fs/promises';\nimport { createWriteStream, createReadStream, ReadStream } from 'fs';\nimport * as path from 'path';\nimport * as mime from 'mime-types';\nimport { Metadata, LocalStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class LocalStorageProvider implements StorageProviderInterface {\n constructor(private config: LocalStorageProviderConfig) {\n // Ensure the base folder exists\n fs.mkdir(this.config.basePath, { recursive: true }).catch((error) => {\n throw error;\n });\n }\n\n async metadata(path: string): Promise<Metadata> {\n const fullPath = this.getFullPath(path);\n const stats = await fs.stat(fullPath);\n return {\n size: stats.size,\n mimeType: mime.lookup(fullPath) || 'unknown',\n lastModifiedDate: stats.mtime.toISOString(),\n };\n }\n\n getFullPath(filePath: string) {\n return path.join(this.config.basePath, filePath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await fs.access(this.getFullPath(path));\n return true;\n } catch {\n return false;\n }\n }\n\n async put(filepath: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const fullPath = this.getFullPath(filepath);\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n if (typeof content === 'string' || content instanceof Buffer) {\n await fs.writeFile(fullPath, content);\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n await fs.writeFile(fullPath, JSON.stringify(content, null, 2));\n } else if (typeof content === 'object' && content instanceof Stream) {\n const writeStream = createWriteStream(fullPath);\n await new Promise((resolve, reject) => {\n (content as Stream).pipe(writeStream);\n (content as Stream).on('end', resolve);\n (content as Stream).on('error', reject);\n });\n } else {\n throw new Error('Unsupported content type');\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const fullPath = this.getFullPath(path);\n const content = await fs.readFile(fullPath, 'utf-8');\n return JSON.parse(content);\n }\n\n async getString(path: string, encoding: BufferEncoding = 'utf-8'): Promise<string> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath, encoding);\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const fullPath = this.getFullPath(path);\n return createReadStream(fullPath);\n }\n\n async delete(path: string): Promise<boolean> {\n const fullPath = this.getFullPath(path);\n await fs.unlink(fullPath);\n return true;\n }\n}\n"],"mappings":";;AAAA,OAAO,YAAY;AACnB,YAAY,QAAQ;AACpB,SAAS,mBAAmB,wBAAoC;AAChE,YAAY,UAAU;AACtB,YAAY,UAAU;AAIf,MAAM,qBAAyD;AAAA,EACpE,YAAoB,QAAoC;AAApC;AAElB,OAAG,MAAM,KAAK,OAAO,UAAU,EAAE,WAAW,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU;AACnE,YAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EAdF,OAQsE;AAAA;AAAA;AAAA,EAQpE,MAAM,SAASA,OAAiC;AAC9C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,QAAQ,MAAM,GAAG,KAAK,QAAQ;AACpC,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,UAAU,KAAK,OAAO,QAAQ,KAAK;AAAA,MACnC,kBAAkB,MAAM,MAAM,YAAY;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,YAAY,UAAkB;AAC5B,WAAO,KAAK,KAAK,KAAK,OAAO,UAAU,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,OAAOA,OAAgC;AAC3C,QAAI;AACF,YAAM,GAAG,OAAO,KAAK,YAAYA,KAAI,CAAC;AACtC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,UAAkB,SAA8D;AACxF,UAAM,WAAW,KAAK,YAAY,QAAQ;AAE1C,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,UAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAI,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AAC5D,YAAM,GAAG,UAAU,UAAU,OAAO;AAAA,IACtC,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,YAAM,GAAG,UAAU,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,IAC/D,WAAW,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AACnE,YAAM,cAAc,kBAAkB,QAAQ;AAC9C,YAAM,IAAI,QAAQ,CAAC,SAAS,WAAW;AACrC,QAAC,QAAmB,KAAK,WAAW;AACpC,QAAC,QAAmB,GAAG,OAAO,OAAO;AACrC,QAAC,QAAmB,GAAG,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQA,OAA+B;AAC3C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,UAAU,MAAM,GAAG,SAAS,UAAU,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAM,UAAUA,OAAc,WAA2B,SAA0B;AACjF,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,MAAM,GAAG,SAAS,UAAU,QAAQ;AAAA,EAC7C;AAAA,EAEA,MAAM,UAAUA,OAA+B;AAC7C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,MAAM,GAAG,SAAS,QAAQ;AAAA,EACnC;AAAA,EAEA,MAAM,UAAUA,OAAmC;AACjD,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,iBAAiB,QAAQ;AAAA,EAClC;AAAA,EAEA,MAAM,OAAOA,OAAgC;AAC3C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,GAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT;AACF;","names":["path"]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/SFTPStorageProvider.mts"],"sourcesContent":["import SFTPClient from 'ssh2-sftp-client';\nimport { Metadata, SFTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class SFTPStorageProvider implements StorageProviderInterface {\n constructor(private config: SFTPStorageProviderConfig) {}\n\n private async getClient(): Promise<SFTPClient> {\n const client = new SFTPClient();\n await client.connect({\n host: this.config.host,\n port: this.config.port || 22,\n username: this.config.username,\n password: this.config.password,\n privateKey: this.config.privateKey,\n passphrase: this.config.passphrase,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n const result = await client.exists(path);\n return result !== false;\n } catch (error) {\n return false;\n } finally {\n await client.end();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let data: string | Buffer | Readable;\n if (typeof content === 'string') {\n data = content;\n } else if (content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = Buffer.from(JSON.stringify(content));\n } else if (content instanceof Stream) {\n data = content as Readable;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.put(data, path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const buffer = await client.get(path);\n return buffer as Buffer;\n } finally {\n await client.end();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Get the file as a stream and close client when done\n client\n .get(path)\n .then((data) => {\n if (data instanceof Buffer) {\n const readable = new Readable();\n readable.push(data);\n readable.push(null);\n readable.pipe(passThrough);\n } else if (data instanceof Stream) {\n (data as Stream).pipe(passThrough);\n }\n return client.end();\n })\n .catch((error) => {\n client.end().catch(() => {\n // Ignore errors when closing client during error handling\n });\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n client.end().catch(() => {\n // Ignore errors if already closed\n });\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.delete(path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const stats = await client.stat(path);\n\n return {\n size: stats.size || 0,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: new Date((stats.modifyTime || 0) * 1000).toISOString(),\n };\n } finally {\n await client.end();\n }\n }\n}\n"],"mappings":";;AAAA,OAAO,gBAAgB;AAIvB,OAAO,UAAU,UAAU,mBAAmB;AAC9C,YAAY,UAAU;AAEf,MAAM,oBAAwD;AAAA,EACnE,YAAoB,QAAmC;AAAnC;AAAA,EAAoC;AAAA,EAR1D,OAOqE;AAAA;AAAA;AAAA,EAGnE,MAAc,YAAiC;AAC7C,UAAM,SAAS,IAAI,WAAW;AAC9B,UAAM,OAAO,QAAQ;AAAA,MACnB,MAAM,KAAK,OAAO;AAAA,MAClB,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1B,UAAU,KAAK,OAAO;AAAA,MACtB,UAAU,KAAK,OAAO;AAAA,MACtB,YAAY,KAAK,OAAO;AAAA,MACxB,YAAY,KAAK,OAAO;AAAA,IAC1B,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,OAAO,IAAI;AACvC,aAAO,WAAW;AAAA,IACpB,SAAS,OAAO;AACd,aAAO;AAAA,IACT,UAAE;AACA,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,MAAc,SAA8D;AACpF,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,UAAI;AACJ,UAAI,OAAO,YAAY,UAAU;AAC/B,eAAO;AAAA,MACT,WAAW,mBAAmB,QAAQ;AACpC,eAAO;AAAA,MACT,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,eAAO,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,MAC5C,WAAW,mBAAmB,QAAQ;AACpC,eAAO;AAAA,MACT,OAAO;AACL,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AAEA,YAAM,OAAO,IAAI,MAAM,IAAI;AAC3B,aAAO;AAAA,IACT,UAAE;AACA,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,MAA+B;AAC3C,UAAM,OAAO,MAAM,KAAK,UAAU,IAAI;AACtC,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,SAAS,MAAM,KAAK,UAAU,IAAI;AACxC,WAAO,OAAO,SAAS,OAAO;AAAA,EAChC;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,IAAI,IAAI;AACpC,aAAO;AAAA,IACT,UAAE;AACA,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,MAAmC;AACjD,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,UAAM,cAAc,IAAI,YAAY;AAGpC,WACG,IAAI,IAAI,EACR,KAAK,CAAC,SAAS;AACd,UAAI,gBAAgB,QAAQ;AAC1B,cAAM,WAAW,IAAI,SAAS;AAC9B,iBAAS,KAAK,IAAI;AAClB,iBAAS,KAAK,IAAI;AAClB,iBAAS,KAAK,WAAW;AAAA,MAC3B,WAAW,gBAAgB,QAAQ;AACjC,QAAC,KAAgB,KAAK,WAAW;AAAA,MACnC;AACA,aAAO,OAAO,IAAI;AAAA,IACpB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,aAAO,IAAI,EAAE,MAAM,MAAM;AAAA,MAEzB,CAAC;AACD,kBAAY,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAGH,gBAAY,GAAG,SAAS,MAAM;AAC5B,aAAO,IAAI,EAAE,MAAM,MAAM;AAAA,MAEzB,CAAC;AAAA,IACH,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,OAAO,OAAO,IAAI;AACxB,aAAO;AAAA,IACT,UAAE;AACA,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,MAAiC;AAC9C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,QAAQ,MAAM,OAAO,KAAK,IAAI;AAEpC,aAAO;AAAA,QACL,MAAM,MAAM,QAAQ;AAAA,QACpB,UAAU,KAAK,OAAO,IAAI,KAAK;AAAA,QAC/B,kBAAkB,IAAI,MAAM,MAAM,cAAc,KAAK,GAAI,EAAE,YAAY;AAAA,MACzE;AAAA,IACF,UAAE;AACA,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@devbro/neko-storage",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "abstracted file storage implementation",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
5
+ "main": "./dist/cjs/index.js",
6
+ "module": "./dist/esm/index.mjs",
7
+ "types": "./dist/cjs/index.d.ts",
8
8
  "files": [
9
9
  "dist"
10
10
  ],
11
11
  "exports": {
12
12
  ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.mjs",
15
- "require": "./dist/index.js"
13
+ "types": "./dist/esm/index.d.ts",
14
+ "import": "./dist/esm/index.mjs",
15
+ "require": "./dist/cjs/index.js"
16
16
  }
17
17
  },
18
18
  "scripts": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/Storage.mts"],"sourcesContent":["import { ReadStream } from 'fs';\nimport { Stream } from 'stream';\nimport { Metadata } from './types.mjs';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class Storage {\n constructor(protected provider: StorageProviderInterface) {}\n\n exists(path: string): Promise<boolean> {\n return this.provider.exists(path);\n }\n\n put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n return this.provider.put(path, content);\n }\n\n getJson(path: string): Promise<object> {\n return this.provider.getJson(path);\n }\n\n getString(path: string): Promise<string> {\n return this.provider.getString(path);\n }\n\n getBuffer(path: string): Promise<Buffer> {\n return this.provider.getBuffer(path);\n }\n\n getStream(path: string): Promise<ReadStream> {\n return this.provider.getStream(path);\n }\n\n delete(path: string): Promise<boolean> {\n return this.provider.delete(path);\n }\n\n metadata(path: string): Promise<Metadata> {\n return this.provider.metadata(path);\n }\n}\n"],"mappings":";;AAKO,MAAM,QAAQ;AAAA,EACnB,YAAsB,UAAoC;AAApC;AAAA,EAAqC;AAAA,EAN7D,OAKqB;AAAA;AAAA;AAAA,EAGnB,OAAO,MAAgC;AACrC,WAAO,KAAK,SAAS,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,IAAI,MAAc,SAA8D;AAC9E,WAAO,KAAK,SAAS,IAAI,MAAM,OAAO;AAAA,EACxC;AAAA,EAEA,QAAQ,MAA+B;AACrC,WAAO,KAAK,SAAS,QAAQ,IAAI;AAAA,EACnC;AAAA,EAEA,UAAU,MAA+B;AACvC,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,UAAU,MAA+B;AACvC,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,UAAU,MAAmC;AAC3C,WAAO,KAAK,SAAS,UAAU,IAAI;AAAA,EACrC;AAAA,EAEA,OAAO,MAAgC;AACrC,WAAO,KAAK,SAAS,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,SAAS,MAAiC;AACxC,WAAO,KAAK,SAAS,SAAS,IAAI;AAAA,EACpC;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/StorageProviderFactory.mts"],"sourcesContent":["import { FlexibleFactory } from '@devbro/neko-helper';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class StorageProviderFactory {\n static instance: FlexibleFactory<StorageProviderInterface> =\n new FlexibleFactory<StorageProviderInterface>();\n\n static register(key: string, factory: (...args: any[]) => StorageProviderInterface): void {\n StorageProviderFactory.instance.register(key, factory);\n }\n\n static create(key: string, ...args: any[]): StorageProviderInterface {\n return StorageProviderFactory.instance.create(key, ...args);\n }\n}\n"],"mappings":";;AAAA,SAAS,uBAAuB;AAGzB,MAAM,uBAAuB;AAAA,EAHpC,OAGoC;AAAA;AAAA;AAAA,EAClC,OAAO,WACL,IAAI,gBAA0C;AAAA,EAEhD,OAAO,SAAS,KAAa,SAA6D;AACxF,2BAAuB,SAAS,SAAS,KAAK,OAAO;AAAA,EACvD;AAAA,EAEA,OAAO,OAAO,QAAgB,MAAuC;AACnE,WAAO,uBAAuB,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EAC5D;AACF;","names":[]}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/Storage.mts","../src/providers/AWSS3StorageProvider.mts","../src/providers/LocalStorageProvider.mts","../src/providers/GCPStorageProvider.mts","../src/providers/AzureBlobStorageProvider.mts","../src/providers/FTPStorageProvider.mts","../src/providers/SFTPStorageProvider.mts","../src/StorageProviderFactory.mts"],"sourcesContent":["export * from './types.mjs';\nexport * from './Storage.mjs';\nexport * from './providers/AWSS3StorageProvider.mjs';\nexport * from './providers/LocalStorageProvider.mjs';\nexport * from './providers/GCPStorageProvider.mjs';\nexport * from './providers/AzureBlobStorageProvider.mjs';\nexport * from './providers/FTPStorageProvider.mjs';\nexport * from './providers/SFTPStorageProvider.mjs';\nexport * from './StorageProviderFactory.mjs';\nexport * from './StorageProviderInterface.mjs';\n","import { ReadStream } from 'fs';\nimport { Stream } from 'stream';\nimport { Metadata } from './types.mjs';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class Storage {\n constructor(protected provider: StorageProviderInterface) {}\n\n exists(path: string): Promise<boolean> {\n return this.provider.exists(path);\n }\n\n put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n return this.provider.put(path, content);\n }\n\n getJson(path: string): Promise<object> {\n return this.provider.getJson(path);\n }\n\n getString(path: string): Promise<string> {\n return this.provider.getString(path);\n }\n\n getBuffer(path: string): Promise<Buffer> {\n return this.provider.getBuffer(path);\n }\n\n getStream(path: string): Promise<ReadStream> {\n return this.provider.getStream(path);\n }\n\n delete(path: string): Promise<boolean> {\n return this.provider.delete(path);\n }\n\n metadata(path: string): Promise<Metadata> {\n return this.provider.metadata(path);\n }\n}\n","import { Metadata, AWSS3StorageProviderConfig } from '../types.mjs';\nimport {\n S3Client,\n HeadObjectCommand,\n PutObjectCommand,\n GetObjectCommand,\n DeleteObjectCommand,\n} from '@aws-sdk/client-s3';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class AWSS3StorageProvider implements StorageProviderInterface {\n private s3: S3Client;\n\n constructor(protected config: AWSS3StorageProviderConfig) {\n this.s3 = new S3Client(this.config);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.s3.send(new HeadObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound') {\n return false;\n }\n throw error;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n let body: any;\n if (typeof content === 'string' || content instanceof Buffer) {\n body = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n body = JSON.stringify(content);\n } else if (content instanceof Stream) {\n body = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.config.bucket,\n Key: path,\n Body: body,\n })\n );\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const body = await this.streamToString(data.Body as Stream);\n return JSON.parse(body);\n }\n\n async getString(path: string): Promise<string> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return await this.streamToString(data.Body as Stream);\n }\n\n async delete(path: string): Promise<boolean> {\n await this.s3.send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n }\n\n private async streamToString(stream: Stream): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stream.on('error', reject);\n });\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const chunks: Uint8Array[] = [];\n const stream = data.Body as Readable;\n\n return new Promise((resolve, reject) => {\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return data.Body as unknown as ReadStream;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const metadata = await this.s3.send(\n new HeadObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return {\n size: metadata.ContentLength || 0,\n mimeType: metadata.ContentType || 'unknown',\n lastModifiedDate: (metadata.LastModified || new Date(0)).toISOString(),\n };\n }\n}\n","import Stream from 'stream';\nimport * as fs from 'fs/promises';\nimport { createWriteStream, createReadStream, ReadStream } from 'fs';\nimport * as path from 'path';\nimport * as mime from 'mime-types';\nimport { Metadata, LocalStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class LocalStorageProvider implements StorageProviderInterface {\n constructor(private config: LocalStorageProviderConfig) {\n // Ensure the base folder exists\n fs.mkdir(this.config.basePath, { recursive: true }).catch((error) => {\n throw error;\n });\n }\n\n async metadata(path: string): Promise<Metadata> {\n const fullPath = this.getFullPath(path);\n const stats = await fs.stat(fullPath);\n return {\n size: stats.size,\n mimeType: mime.lookup(fullPath) || 'unknown',\n lastModifiedDate: stats.mtime.toISOString(),\n };\n }\n\n getFullPath(filePath: string) {\n return path.join(this.config.basePath, filePath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await fs.access(this.getFullPath(path));\n return true;\n } catch {\n return false;\n }\n }\n\n async put(filepath: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const fullPath = this.getFullPath(filepath);\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n if (typeof content === 'string' || content instanceof Buffer) {\n await fs.writeFile(fullPath, content);\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n await fs.writeFile(fullPath, JSON.stringify(content, null, 2));\n } else if (typeof content === 'object' && content instanceof Stream) {\n const writeStream = createWriteStream(fullPath);\n await new Promise((resolve, reject) => {\n (content as Stream).pipe(writeStream);\n (content as Stream).on('end', resolve);\n (content as Stream).on('error', reject);\n });\n } else {\n throw new Error('Unsupported content type');\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const fullPath = this.getFullPath(path);\n const content = await fs.readFile(fullPath, 'utf-8');\n return JSON.parse(content);\n }\n\n async getString(path: string, encoding: BufferEncoding = 'utf-8'): Promise<string> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath, encoding);\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const fullPath = this.getFullPath(path);\n return createReadStream(fullPath);\n }\n\n async delete(path: string): Promise<boolean> {\n const fullPath = this.getFullPath(path);\n await fs.unlink(fullPath);\n return true;\n }\n}\n","import { Storage as GCPStorage } from '@google-cloud/storage';\nimport { Metadata, GCPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream from 'stream';\nimport * as mime from 'mime-types';\n\nexport class GCPStorageProvider implements StorageProviderInterface {\n private storage: GCPStorage;\n\n constructor(protected config: GCPStorageProviderConfig) {\n const { bucket, ...gcpOptions } = config;\n this.storage = new GCPStorage(gcpOptions);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [exists] = await file.exists();\n return exists;\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await new Promise<void>((resolve, reject) => {\n data\n .pipe(file.createWriteStream())\n .on('finish', () => resolve())\n .on('error', reject);\n });\n } else {\n await file.save(data);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content;\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n return file.createReadStream() as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n await file.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [metadata] = await file.getMetadata();\n\n return {\n size: typeof metadata.size === 'number' ? metadata.size : parseInt(metadata.size || '0', 10),\n mimeType: metadata.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: metadata.updated || new Date(0).toISOString(),\n };\n }\n}\n","import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';\nimport { Metadata, AzureBlobStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class AzureBlobStorageProvider implements StorageProviderInterface {\n private blobServiceClient: BlobServiceClient;\n\n constructor(protected config: AzureBlobStorageProviderConfig) {\n const { accountName, accountKey, sasToken } = config;\n\n if (accountKey) {\n const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n sharedKeyCredential\n );\n } else if (sasToken) {\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net?${sasToken}`\n );\n } else {\n throw new Error('Either accountKey or sasToken is required for Azure Blob Storage');\n }\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n return await blobClient.exists();\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blockBlobClient = containerClient.getBlockBlobClient(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await blockBlobClient.uploadStream(data as Readable);\n } else {\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n await blockBlobClient.upload(buffer, buffer.length);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return await this.streamToBuffer(downloadResponse.readableStreamBody);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return downloadResponse.readableStreamBody as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n await blobClient.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const properties = await blobClient.getProperties();\n\n return {\n size: properties.contentLength || 0,\n mimeType: properties.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: properties.lastModified?.toISOString() || new Date(0).toISOString(),\n };\n }\n\n private async streamToBuffer(readableStream: NodeJS.ReadableStream): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n readableStream.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n readableStream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n readableStream.on('error', reject);\n });\n }\n}\n","import { Client as FTPClient } from 'basic-ftp';\nimport { Metadata, FTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class FTPStorageProvider implements StorageProviderInterface {\n constructor(private config: FTPStorageProviderConfig) {}\n\n private async getClient(): Promise<FTPClient> {\n const client = new FTPClient();\n await client.access({\n host: this.config.host,\n port: this.config.port || 21,\n user: this.config.user || 'anonymous',\n password: this.config.password || '',\n secure: this.config.secure || false,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.size(path);\n return true;\n } catch (error) {\n return false;\n } finally {\n client.close();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let stream: Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n const readable = new Readable();\n readable.push(typeof content === 'string' ? Buffer.from(content) : content);\n readable.push(null);\n stream = readable;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n const readable = new Readable();\n readable.push(Buffer.from(JSON.stringify(content)));\n readable.push(null);\n stream = readable;\n } else if (content instanceof Stream) {\n stream = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.uploadFrom(stream as Readable, path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const chunks: Buffer[] = [];\n const writable = new PassThrough();\n\n writable.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n await client.downloadTo(writable, path);\n\n return Buffer.concat(chunks);\n } finally {\n client.close();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Download to stream and close client when done\n client\n .downloadTo(passThrough, path)\n .then(() => client.close())\n .catch((error) => {\n client.close();\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n try {\n client.close();\n } catch {\n // Ignore errors if already closed\n }\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.remove(path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const size = await client.size(path);\n const lastMod = await client.lastMod(path);\n\n return {\n size: size,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: lastMod?.toISOString() || new Date(0).toISOString(),\n };\n } finally {\n client.close();\n }\n }\n}\n","import SFTPClient from 'ssh2-sftp-client';\nimport { Metadata, SFTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class SFTPStorageProvider implements StorageProviderInterface {\n constructor(private config: SFTPStorageProviderConfig) {}\n\n private async getClient(): Promise<SFTPClient> {\n const client = new SFTPClient();\n await client.connect({\n host: this.config.host,\n port: this.config.port || 22,\n username: this.config.username,\n password: this.config.password,\n privateKey: this.config.privateKey,\n passphrase: this.config.passphrase,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n const result = await client.exists(path);\n return result !== false;\n } catch (error) {\n return false;\n } finally {\n await client.end();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let data: string | Buffer | Readable;\n if (typeof content === 'string') {\n data = content;\n } else if (content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = Buffer.from(JSON.stringify(content));\n } else if (content instanceof Stream) {\n data = content as Readable;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.put(data, path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const buffer = await client.get(path);\n return buffer as Buffer;\n } finally {\n await client.end();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Get the file as a stream and close client when done\n client\n .get(path)\n .then((data) => {\n if (data instanceof Buffer) {\n const readable = new Readable();\n readable.push(data);\n readable.push(null);\n readable.pipe(passThrough);\n } else if (data instanceof Stream) {\n (data as Stream).pipe(passThrough);\n }\n return client.end();\n })\n .catch((error) => {\n client.end().catch(() => {\n // Ignore errors when closing client during error handling\n });\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n client.end().catch(() => {\n // Ignore errors if already closed\n });\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.delete(path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const stats = await client.stat(path);\n\n return {\n size: stats.size || 0,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: new Date((stats.modifyTime || 0) * 1000).toISOString(),\n };\n } finally {\n await client.end();\n }\n }\n}\n","import { FlexibleFactory } from '@devbro/neko-helper';\nimport { StorageProviderInterface } from './StorageProviderInterface.mjs';\n\nexport class StorageProviderFactory {\n static instance: FlexibleFactory<StorageProviderInterface> =\n new FlexibleFactory<StorageProviderInterface>();\n\n static register(key: string, factory: (...args: any[]) => StorageProviderInterface): void {\n StorageProviderFactory.instance.register(key, factory);\n }\n\n static create(key: string, ...args: any[]): StorageProviderInterface {\n return StorageProviderFactory.instance.create(key, ...args);\n }\n}\n"],"mappings":"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","names":["path","path","Stream","import_stream","path","Stream","import_stream","mime","GCPStorage","path","Stream","import_stream","mime","path","Stream","import_stream","mime","FTPClient","path","Stream","import_stream","mime","SFTPClient","path","Stream"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './types.mjs';\nexport * from './Storage.mjs';\nexport * from './providers/AWSS3StorageProvider.mjs';\nexport * from './providers/LocalStorageProvider.mjs';\nexport * from './providers/GCPStorageProvider.mjs';\nexport * from './providers/AzureBlobStorageProvider.mjs';\nexport * from './providers/FTPStorageProvider.mjs';\nexport * from './providers/SFTPStorageProvider.mjs';\nexport * from './StorageProviderFactory.mjs';\nexport * from './StorageProviderInterface.mjs';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/AWSS3StorageProvider.mts"],"sourcesContent":["import { Metadata, AWSS3StorageProviderConfig } from '../types.mjs';\nimport {\n S3Client,\n HeadObjectCommand,\n PutObjectCommand,\n GetObjectCommand,\n DeleteObjectCommand,\n} from '@aws-sdk/client-s3';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class AWSS3StorageProvider implements StorageProviderInterface {\n private s3: S3Client;\n\n constructor(protected config: AWSS3StorageProviderConfig) {\n this.s3 = new S3Client(this.config);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.s3.send(new HeadObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound') {\n return false;\n }\n throw error;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n let body: any;\n if (typeof content === 'string' || content instanceof Buffer) {\n body = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n body = JSON.stringify(content);\n } else if (content instanceof Stream) {\n body = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.config.bucket,\n Key: path,\n Body: body,\n })\n );\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const body = await this.streamToString(data.Body as Stream);\n return JSON.parse(body);\n }\n\n async getString(path: string): Promise<string> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return await this.streamToString(data.Body as Stream);\n }\n\n async delete(path: string): Promise<boolean> {\n await this.s3.send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: path }));\n return true;\n }\n\n private async streamToString(stream: Stream): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n stream.on('error', reject);\n });\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n const chunks: Uint8Array[] = [];\n const stream = data.Body as Readable;\n\n return new Promise((resolve, reject) => {\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const data = await this.s3.send(\n new GetObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return data.Body as unknown as ReadStream;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const metadata = await this.s3.send(\n new HeadObjectCommand({ Bucket: this.config.bucket, Key: path })\n );\n return {\n size: metadata.ContentLength || 0,\n mimeType: metadata.ContentType || 'unknown',\n lastModifiedDate: (metadata.LastModified || new Date(0)).toISOString(),\n };\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/AzureBlobStorageProvider.mts"],"sourcesContent":["import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';\nimport { Metadata, AzureBlobStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class AzureBlobStorageProvider implements StorageProviderInterface {\n private blobServiceClient: BlobServiceClient;\n\n constructor(protected config: AzureBlobStorageProviderConfig) {\n const { accountName, accountKey, sasToken } = config;\n\n if (accountKey) {\n const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net`,\n sharedKeyCredential\n );\n } else if (sasToken) {\n this.blobServiceClient = new BlobServiceClient(\n `https://${accountName}.blob.core.windows.net?${sasToken}`\n );\n } else {\n throw new Error('Either accountKey or sasToken is required for Azure Blob Storage');\n }\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n return await blobClient.exists();\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blockBlobClient = containerClient.getBlockBlobClient(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await blockBlobClient.uploadStream(data as Readable);\n } else {\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n await blockBlobClient.upload(buffer, buffer.length);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return await this.streamToBuffer(downloadResponse.readableStreamBody);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const downloadResponse = await blobClient.download();\n\n if (!downloadResponse.readableStreamBody) {\n throw new Error('Failed to download blob');\n }\n\n return downloadResponse.readableStreamBody as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n await blobClient.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const containerClient = this.blobServiceClient.getContainerClient(this.config.containerName);\n const blobClient = containerClient.getBlobClient(path);\n const properties = await blobClient.getProperties();\n\n return {\n size: properties.contentLength || 0,\n mimeType: properties.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: properties.lastModified?.toISOString() || new Date(0).toISOString(),\n };\n }\n\n private async streamToBuffer(readableStream: NodeJS.ReadableStream): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n readableStream.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n readableStream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n readableStream.on('error', reject);\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/FTPStorageProvider.mts"],"sourcesContent":["import { Client as FTPClient } from 'basic-ftp';\nimport { Metadata, FTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class FTPStorageProvider implements StorageProviderInterface {\n constructor(private config: FTPStorageProviderConfig) {}\n\n private async getClient(): Promise<FTPClient> {\n const client = new FTPClient();\n await client.access({\n host: this.config.host,\n port: this.config.port || 21,\n user: this.config.user || 'anonymous',\n password: this.config.password || '',\n secure: this.config.secure || false,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.size(path);\n return true;\n } catch (error) {\n return false;\n } finally {\n client.close();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let stream: Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n const readable = new Readable();\n readable.push(typeof content === 'string' ? Buffer.from(content) : content);\n readable.push(null);\n stream = readable;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n const readable = new Readable();\n readable.push(Buffer.from(JSON.stringify(content)));\n readable.push(null);\n stream = readable;\n } else if (content instanceof Stream) {\n stream = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.uploadFrom(stream as Readable, path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const chunks: Buffer[] = [];\n const writable = new PassThrough();\n\n writable.on('data', (chunk) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n await client.downloadTo(writable, path);\n\n return Buffer.concat(chunks);\n } finally {\n client.close();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Download to stream and close client when done\n client\n .downloadTo(passThrough, path)\n .then(() => client.close())\n .catch((error) => {\n client.close();\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n try {\n client.close();\n } catch {\n // Ignore errors if already closed\n }\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.remove(path);\n return true;\n } finally {\n client.close();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const size = await client.size(path);\n const lastMod = await client.lastMod(path);\n\n return {\n size: size,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: lastMod?.toISOString() || new Date(0).toISOString(),\n };\n } finally {\n client.close();\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/GCPStorageProvider.mts"],"sourcesContent":["import { Storage as GCPStorage } from '@google-cloud/storage';\nimport { Metadata, GCPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream from 'stream';\nimport * as mime from 'mime-types';\n\nexport class GCPStorageProvider implements StorageProviderInterface {\n private storage: GCPStorage;\n\n constructor(protected config: GCPStorageProviderConfig) {\n const { bucket, ...gcpOptions } = config;\n this.storage = new GCPStorage(gcpOptions);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [exists] = await file.exists();\n return exists;\n } catch (error) {\n return false;\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n\n let data: string | Buffer | Stream;\n if (typeof content === 'string' || content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = JSON.stringify(content);\n } else if (content instanceof Stream) {\n data = content;\n } else {\n throw new Error('Unsupported content type');\n }\n\n if (data instanceof Stream) {\n await new Promise<void>((resolve, reject) => {\n data\n .pipe(file.createWriteStream())\n .on('finish', () => resolve())\n .on('error', reject);\n });\n } else {\n await file.save(data);\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [content] = await file.download();\n return content;\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n return file.createReadStream() as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n await file.delete();\n return true;\n }\n\n async metadata(path: string): Promise<Metadata> {\n const file = this.storage.bucket(this.config.bucket).file(path);\n const [metadata] = await file.getMetadata();\n\n return {\n size: typeof metadata.size === 'number' ? metadata.size : parseInt(metadata.size || '0', 10),\n mimeType: metadata.contentType || mime.lookup(path) || 'unknown',\n lastModifiedDate: metadata.updated || new Date(0).toISOString(),\n };\n }\n}\n"],"mappings":";;AAAA,SAAS,WAAW,kBAAkB;AAItC,OAAO,YAAY;AACnB,YAAY,UAAU;AAEf,MAAM,mBAAuD;AAAA,EAGlE,YAAsB,QAAkC;AAAlC;AACpB,UAAM,EAAE,QAAQ,GAAG,WAAW,IAAI;AAClC,SAAK,UAAU,IAAI,WAAW,UAAU;AAAA,EAC1C;AAAA,EAbF,OAOoE;AAAA;AAAA;AAAA,EAC1D;AAAA,EAOR,MAAM,OAAO,MAAgC;AAC3C,QAAI;AACF,YAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,YAAM,CAAC,MAAM,IAAI,MAAM,KAAK,OAAO;AACnC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,MAAc,SAA8D;AACpF,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAE9D,QAAI;AACJ,QAAI,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AAC5D,aAAO;AAAA,IACT,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,aAAO,KAAK,UAAU,OAAO;AAAA,IAC/B,WAAW,mBAAmB,QAAQ;AACpC,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,QAAI,gBAAgB,QAAQ;AAC1B,YAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,aACG,KAAK,KAAK,kBAAkB,CAAC,EAC7B,GAAG,UAAU,MAAM,QAAQ,CAAC,EAC5B,GAAG,SAAS,MAAM;AAAA,MACvB,CAAC;AAAA,IACH,OAAO;AACL,YAAM,KAAK,KAAK,IAAI;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,MAA+B;AAC3C,UAAM,OAAO,MAAM,KAAK,UAAU,IAAI;AACtC,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,OAAO,IAAI,MAAM,KAAK,SAAS;AACtC,WAAO,QAAQ,SAAS,OAAO;AAAA,EACjC;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,OAAO,IAAI,MAAM,KAAK,SAAS;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,MAAmC;AACjD,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,KAAK,OAAO;AAClB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAiC;AAC9C,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM,EAAE,KAAK,IAAI;AAC9D,UAAM,CAAC,QAAQ,IAAI,MAAM,KAAK,YAAY;AAE1C,WAAO;AAAA,MACL,MAAM,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO,SAAS,SAAS,QAAQ,KAAK,EAAE;AAAA,MAC3F,UAAU,SAAS,eAAe,KAAK,OAAO,IAAI,KAAK;AAAA,MACvD,kBAAkB,SAAS,YAAW,oBAAI,KAAK,CAAC,GAAE,YAAY;AAAA,IAChE;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/LocalStorageProvider.mts"],"sourcesContent":["import Stream from 'stream';\nimport * as fs from 'fs/promises';\nimport { createWriteStream, createReadStream, ReadStream } from 'fs';\nimport * as path from 'path';\nimport * as mime from 'mime-types';\nimport { Metadata, LocalStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\n\nexport class LocalStorageProvider implements StorageProviderInterface {\n constructor(private config: LocalStorageProviderConfig) {\n // Ensure the base folder exists\n fs.mkdir(this.config.basePath, { recursive: true }).catch((error) => {\n throw error;\n });\n }\n\n async metadata(path: string): Promise<Metadata> {\n const fullPath = this.getFullPath(path);\n const stats = await fs.stat(fullPath);\n return {\n size: stats.size,\n mimeType: mime.lookup(fullPath) || 'unknown',\n lastModifiedDate: stats.mtime.toISOString(),\n };\n }\n\n getFullPath(filePath: string) {\n return path.join(this.config.basePath, filePath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await fs.access(this.getFullPath(path));\n return true;\n } catch {\n return false;\n }\n }\n\n async put(filepath: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const fullPath = this.getFullPath(filepath);\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n if (typeof content === 'string' || content instanceof Buffer) {\n await fs.writeFile(fullPath, content);\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n await fs.writeFile(fullPath, JSON.stringify(content, null, 2));\n } else if (typeof content === 'object' && content instanceof Stream) {\n const writeStream = createWriteStream(fullPath);\n await new Promise((resolve, reject) => {\n (content as Stream).pipe(writeStream);\n (content as Stream).on('end', resolve);\n (content as Stream).on('error', reject);\n });\n } else {\n throw new Error('Unsupported content type');\n }\n\n return true;\n }\n\n async getJson(path: string): Promise<object> {\n const fullPath = this.getFullPath(path);\n const content = await fs.readFile(fullPath, 'utf-8');\n return JSON.parse(content);\n }\n\n async getString(path: string, encoding: BufferEncoding = 'utf-8'): Promise<string> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath, encoding);\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const fullPath = this.getFullPath(path);\n return await fs.readFile(fullPath);\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const fullPath = this.getFullPath(path);\n return createReadStream(fullPath);\n }\n\n async delete(path: string): Promise<boolean> {\n const fullPath = this.getFullPath(path);\n await fs.unlink(fullPath);\n return true;\n }\n}\n"],"mappings":";;AAAA,OAAO,YAAY;AACnB,YAAY,QAAQ;AACpB,SAAS,mBAAmB,wBAAoC;AAChE,YAAY,UAAU;AACtB,YAAY,UAAU;AAIf,MAAM,qBAAyD;AAAA,EACpE,YAAoB,QAAoC;AAApC;AAElB,OAAG,MAAM,KAAK,OAAO,UAAU,EAAE,WAAW,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU;AACnE,YAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EAdF,OAQsE;AAAA;AAAA;AAAA,EAQpE,MAAM,SAASA,OAAiC;AAC9C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,QAAQ,MAAM,GAAG,KAAK,QAAQ;AACpC,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,UAAU,KAAK,OAAO,QAAQ,KAAK;AAAA,MACnC,kBAAkB,MAAM,MAAM,YAAY;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,YAAY,UAAkB;AAC5B,WAAO,KAAK,KAAK,KAAK,OAAO,UAAU,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,OAAOA,OAAgC;AAC3C,QAAI;AACF,YAAM,GAAG,OAAO,KAAK,YAAYA,KAAI,CAAC;AACtC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,UAAkB,SAA8D;AACxF,UAAM,WAAW,KAAK,YAAY,QAAQ;AAE1C,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,UAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAI,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AAC5D,YAAM,GAAG,UAAU,UAAU,OAAO;AAAA,IACtC,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,YAAM,GAAG,UAAU,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,IAC/D,WAAW,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AACnE,YAAM,cAAc,kBAAkB,QAAQ;AAC9C,YAAM,IAAI,QAAQ,CAAC,SAAS,WAAW;AACrC,QAAC,QAAmB,KAAK,WAAW;AACpC,QAAC,QAAmB,GAAG,OAAO,OAAO;AACrC,QAAC,QAAmB,GAAG,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQA,OAA+B;AAC3C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,UAAU,MAAM,GAAG,SAAS,UAAU,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAM,UAAUA,OAAc,WAA2B,SAA0B;AACjF,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,MAAM,GAAG,SAAS,UAAU,QAAQ;AAAA,EAC7C;AAAA,EAEA,MAAM,UAAUA,OAA+B;AAC7C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,MAAM,GAAG,SAAS,QAAQ;AAAA,EACnC;AAAA,EAEA,MAAM,UAAUA,OAAmC;AACjD,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,WAAO,iBAAiB,QAAQ;AAAA,EAClC;AAAA,EAEA,MAAM,OAAOA,OAAgC;AAC3C,UAAM,WAAW,KAAK,YAAYA,KAAI;AACtC,UAAM,GAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT;AACF;","names":["path"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/providers/SFTPStorageProvider.mts"],"sourcesContent":["import SFTPClient from 'ssh2-sftp-client';\nimport { Metadata, SFTPStorageProviderConfig } from '../types.mjs';\nimport { StorageProviderInterface } from '../StorageProviderInterface.mjs';\nimport { ReadStream } from 'fs';\nimport Stream, { Readable, PassThrough } from 'stream';\nimport * as mime from 'mime-types';\n\nexport class SFTPStorageProvider implements StorageProviderInterface {\n constructor(private config: SFTPStorageProviderConfig) {}\n\n private async getClient(): Promise<SFTPClient> {\n const client = new SFTPClient();\n await client.connect({\n host: this.config.host,\n port: this.config.port || 22,\n username: this.config.username,\n password: this.config.password,\n privateKey: this.config.privateKey,\n passphrase: this.config.passphrase,\n });\n return client;\n }\n\n async exists(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n const result = await client.exists(path);\n return result !== false;\n } catch (error) {\n return false;\n } finally {\n await client.end();\n }\n }\n\n async put(path: string, content: string | object | Stream | Buffer): Promise<boolean> {\n const client = await this.getClient();\n try {\n let data: string | Buffer | Readable;\n if (typeof content === 'string') {\n data = content;\n } else if (content instanceof Buffer) {\n data = content;\n } else if (typeof content === 'object' && !(content instanceof Stream)) {\n data = Buffer.from(JSON.stringify(content));\n } else if (content instanceof Stream) {\n data = content as Readable;\n } else {\n throw new Error('Unsupported content type');\n }\n\n await client.put(data, path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async getJson(path: string): Promise<object> {\n const data = await this.getString(path);\n return JSON.parse(data);\n }\n\n async getString(path: string): Promise<string> {\n const buffer = await this.getBuffer(path);\n return buffer.toString('utf-8');\n }\n\n async getBuffer(path: string): Promise<Buffer> {\n const client = await this.getClient();\n try {\n const buffer = await client.get(path);\n return buffer as Buffer;\n } finally {\n await client.end();\n }\n }\n\n async getStream(path: string): Promise<ReadStream> {\n const client = await this.getClient();\n const passThrough = new PassThrough();\n\n // Get the file as a stream and close client when done\n client\n .get(path)\n .then((data) => {\n if (data instanceof Buffer) {\n const readable = new Readable();\n readable.push(data);\n readable.push(null);\n readable.pipe(passThrough);\n } else if (data instanceof Stream) {\n (data as Stream).pipe(passThrough);\n }\n return client.end();\n })\n .catch((error) => {\n client.end().catch(() => {\n // Ignore errors when closing client during error handling\n });\n passThrough.destroy(error);\n });\n\n // Ensure client is closed when stream is destroyed\n passThrough.on('close', () => {\n client.end().catch(() => {\n // Ignore errors if already closed\n });\n });\n\n return passThrough as unknown as ReadStream;\n }\n\n async delete(path: string): Promise<boolean> {\n const client = await this.getClient();\n try {\n await client.delete(path);\n return true;\n } finally {\n await client.end();\n }\n }\n\n async metadata(path: string): Promise<Metadata> {\n const client = await this.getClient();\n try {\n const stats = await client.stat(path);\n\n return {\n size: stats.size || 0,\n mimeType: mime.lookup(path) || 'unknown',\n lastModifiedDate: new Date((stats.modifyTime || 0) * 1000).toISOString(),\n };\n } finally {\n await client.end();\n }\n }\n}\n"],"mappings":"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","names":[]}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes