@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.
- package/README.md +344 -48
- package/dist/cjs/index.d.ts +159 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/Storage.mjs.map +1 -0
- package/dist/esm/StorageProviderFactory.mjs.map +1 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/providers/AWSS3StorageProvider.mjs.map +1 -0
- package/dist/esm/providers/AzureBlobStorageProvider.mjs.map +1 -0
- package/dist/esm/providers/FTPStorageProvider.mjs.map +1 -0
- package/dist/esm/providers/GCPStorageProvider.mjs.map +1 -0
- package/dist/esm/providers/LocalStorageProvider.mjs.map +1 -0
- package/dist/esm/providers/SFTPStorageProvider.mjs.map +1 -0
- package/package.json +7 -7
- package/dist/Storage.mjs.map +0 -1
- package/dist/StorageProviderFactory.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/providers/AWSS3StorageProvider.mjs.map +0 -1
- package/dist/providers/AzureBlobStorageProvider.mjs.map +0 -1
- package/dist/providers/FTPStorageProvider.mjs.map +0 -1
- package/dist/providers/GCPStorageProvider.mjs.map +0 -1
- package/dist/providers/LocalStorageProvider.mjs.map +0 -1
- package/dist/providers/SFTPStorageProvider.mjs.map +0 -1
- /package/dist/{index.js → cjs/index.js} +0 -0
- /package/dist/{Storage.d.mts → esm/Storage.d.mts} +0 -0
- /package/dist/{Storage.mjs → esm/Storage.mjs} +0 -0
- /package/dist/{StorageProviderFactory.d.mts → esm/StorageProviderFactory.d.mts} +0 -0
- /package/dist/{StorageProviderFactory.mjs → esm/StorageProviderFactory.mjs} +0 -0
- /package/dist/{StorageProviderInterface.d.mts → esm/StorageProviderInterface.d.mts} +0 -0
- /package/dist/{StorageProviderInterface.mjs → esm/StorageProviderInterface.mjs} +0 -0
- /package/dist/{StorageProviderInterface.mjs.map → esm/StorageProviderInterface.mjs.map} +0 -0
- /package/dist/{index.d.mts → esm/index.d.mts} +0 -0
- /package/dist/{index.mjs → esm/index.mjs} +0 -0
- /package/dist/{providers → esm/providers}/AWSS3StorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/AWSS3StorageProvider.mjs +0 -0
- /package/dist/{providers → esm/providers}/AzureBlobStorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/AzureBlobStorageProvider.mjs +0 -0
- /package/dist/{providers → esm/providers}/FTPStorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/FTPStorageProvider.mjs +0 -0
- /package/dist/{providers → esm/providers}/GCPStorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/GCPStorageProvider.mjs +0 -0
- /package/dist/{providers → esm/providers}/LocalStorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/LocalStorageProvider.mjs +0 -0
- /package/dist/{providers → esm/providers}/SFTPStorageProvider.d.mts +0 -0
- /package/dist/{providers → esm/providers}/SFTPStorageProvider.mjs +0 -0
- /package/dist/{types.d.mts → esm/types.d.mts} +0 -0
- /package/dist/{types.mjs → esm/types.mjs} +0 -0
- /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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
73
|
+
const exists = await storage.exists('path/to/file.txt');
|
|
74
|
+
if (exists) {
|
|
75
|
+
console.log('File exists!');
|
|
76
|
+
}
|
|
77
|
+
```
|
|
9
78
|
|
|
10
|
-
|
|
79
|
+
### Reading Files
|
|
11
80
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
//
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
##
|
|
125
|
+
## Storage Providers
|
|
41
126
|
|
|
42
|
-
### Local
|
|
127
|
+
### Local File System
|
|
43
128
|
|
|
44
|
-
Store files on the local
|
|
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
|
|
50
|
-
|
|
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: '
|
|
161
|
+
bucket: 'my-app-uploads',
|
|
64
162
|
s3Config: {
|
|
65
163
|
region: 'us-east-1',
|
|
66
164
|
credentials: {
|
|
67
|
-
accessKeyId:
|
|
68
|
-
secretAccessKey:
|
|
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: '
|
|
194
|
+
bucket: 'my-app-uploads',
|
|
85
195
|
gcpConfig: {
|
|
86
|
-
projectId: '
|
|
196
|
+
projectId: 'my-project-id',
|
|
87
197
|
keyFilename: '/path/to/service-account-key.json',
|
|
88
|
-
//
|
|
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: '
|
|
106
|
-
accountKey:
|
|
107
|
-
|
|
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: '/
|
|
259
|
+
basePath: '/uploads',
|
|
123
260
|
FTPStorageProviderConfig: {
|
|
124
261
|
host: 'ftp.example.com',
|
|
125
262
|
port: 21,
|
|
126
|
-
user:
|
|
127
|
-
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: '/
|
|
296
|
+
basePath: '/home/user/uploads',
|
|
144
297
|
SFTPStorageProviderConfig: {
|
|
145
298
|
host: 'sftp.example.com',
|
|
146
299
|
port: 22,
|
|
147
|
-
username:
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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":";;AAAA,SAAS,UAAU,iBAAiB;AAIpC,OAAO,UAAU,UAAU,mBAAmB;AAC9C,YAAY,UAAU;AAEf,MAAM,mBAAuD;AAAA,EAClE,YAAoB,QAAkC;AAAlC;AAAA,EAAmC;AAAA,EARzD,OAOoE;AAAA;AAAA;AAAA,EAGlE,MAAc,YAAgC;AAC5C,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,OAAO,OAAO;AAAA,MAClB,MAAM,KAAK,OAAO;AAAA,MAClB,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1B,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1B,UAAU,KAAK,OAAO,YAAY;AAAA,MAClC,QAAQ,KAAK,OAAO,UAAU;AAAA,IAChC,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,OAAO,KAAK,IAAI;AACtB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,IACT,UAAE;AACA,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,MAAc,SAA8D;AACpF,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,UAAI;AACJ,UAAI,OAAO,YAAY,YAAY,mBAAmB,QAAQ;AAC5D,cAAM,WAAW,IAAI,SAAS;AAC9B,iBAAS,KAAK,OAAO,YAAY,WAAW,OAAO,KAAK,OAAO,IAAI,OAAO;AAC1E,iBAAS,KAAK,IAAI;AAClB,iBAAS;AAAA,MACX,WAAW,OAAO,YAAY,YAAY,EAAE,mBAAmB,SAAS;AACtE,cAAM,WAAW,IAAI,SAAS;AAC9B,iBAAS,KAAK,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,CAAC;AAClD,iBAAS,KAAK,IAAI;AAClB,iBAAS;AAAA,MACX,WAAW,mBAAmB,QAAQ;AACpC,iBAAS;AAAA,MACX,OAAO;AACL,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AAEA,YAAM,OAAO,WAAW,QAAoB,IAAI;AAChD,aAAO;AAAA,IACT,UAAE;AACA,aAAO,MAAM;AAAA,IACf;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,SAAmB,CAAC;AAC1B,YAAM,WAAW,IAAI,YAAY;AAEjC,eAAS,GAAG,QAAQ,CAAC,UAAU;AAC7B,eAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK,CAAC;AAAA,MACjE,CAAC;AAED,YAAM,OAAO,WAAW,UAAU,IAAI;AAEtC,aAAO,OAAO,OAAO,MAAM;AAAA,IAC7B,UAAE;AACA,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,MAAmC;AACjD,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,UAAM,cAAc,IAAI,YAAY;AAGpC,WACG,WAAW,aAAa,IAAI,EAC5B,KAAK,MAAM,OAAO,MAAM,CAAC,EACzB,MAAM,CAAC,UAAU;AAChB,aAAO,MAAM;AACb,kBAAY,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAGH,gBAAY,GAAG,SAAS,MAAM;AAC5B,UAAI;AACF,eAAO,MAAM;AAAA,MACf,QAAQ;AAAA,MAER;AAAA,IACF,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,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,MAAiC;AAC9C,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,KAAK,IAAI;AACnC,YAAM,UAAU,MAAM,OAAO,QAAQ,IAAI;AAEzC,aAAO;AAAA,QACL;AAAA,QACA,UAAU,KAAK,OAAO,IAAI,KAAK;AAAA,QAC/B,kBAAkB,SAAS,YAAY,MAAK,oBAAI,KAAK,CAAC,GAAE,YAAY;AAAA,MACtE;AAAA,IACF,UAAE;AACA,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;","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":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devbro/neko-storage",
|
|
3
|
-
"version": "0.1.
|
|
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": {
|
package/dist/Storage.mjs.map
DELETED
|
@@ -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"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -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":";;AAAA,SAAS,mBAAmB,kCAAkC;AAI9D,OAAO,YAA0B;AACjC,YAAY,UAAU;AAEf,MAAM,yBAA6D;AAAA,EAGxE,YAAsB,QAAwC;AAAxC;AACpB,UAAM,EAAE,aAAa,YAAY,SAAS,IAAI;AAE9C,QAAI,YAAY;AACd,YAAM,sBAAsB,IAAI,2BAA2B,aAAa,UAAU;AAClF,WAAK,oBAAoB,IAAI;AAAA,QAC3B,WAAW,WAAW;AAAA,QACtB;AAAA,MACF;AAAA,IACF,WAAW,UAAU;AACnB,WAAK,oBAAoB,IAAI;AAAA,QAC3B,WAAW,WAAW,0BAA0B,QAAQ;AAAA,MAC1D;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAAA,EACF;AAAA,EA1BF,OAO0E;AAAA;AAAA;AAAA,EAChE;AAAA,EAoBR,MAAM,OAAO,MAAgC;AAC3C,QAAI;AACF,YAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,YAAM,aAAa,gBAAgB,cAAc,IAAI;AACrD,aAAO,MAAM,WAAW,OAAO;AAAA,IACjC,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,MAAc,SAA8D;AACpF,UAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,UAAM,kBAAkB,gBAAgB,mBAAmB,IAAI;AAE/D,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,gBAAgB,aAAa,IAAgB;AAAA,IACrD,OAAO;AACL,YAAM,SAAS,OAAO,SAAS,WAAW,OAAO,KAAK,IAAI,IAAI;AAC9D,YAAM,gBAAgB,OAAO,QAAQ,OAAO,MAAM;AAAA,IACpD;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,SAAS,MAAM,KAAK,UAAU,IAAI;AACxC,WAAO,OAAO,SAAS,OAAO;AAAA,EAChC;AAAA,EAEA,MAAM,UAAU,MAA+B;AAC7C,UAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,UAAM,aAAa,gBAAgB,cAAc,IAAI;AACrD,UAAM,mBAAmB,MAAM,WAAW,SAAS;AAEnD,QAAI,CAAC,iBAAiB,oBAAoB;AACxC,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,WAAO,MAAM,KAAK,eAAe,iBAAiB,kBAAkB;AAAA,EACtE;AAAA,EAEA,MAAM,UAAU,MAAmC;AACjD,UAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,UAAM,aAAa,gBAAgB,cAAc,IAAI;AACrD,UAAM,mBAAmB,MAAM,WAAW,SAAS;AAEnD,QAAI,CAAC,iBAAiB,oBAAoB;AACxC,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,WAAO,iBAAiB;AAAA,EAC1B;AAAA,EAEA,MAAM,OAAO,MAAgC;AAC3C,UAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,UAAM,aAAa,gBAAgB,cAAc,IAAI;AACrD,UAAM,WAAW,OAAO;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAiC;AAC9C,UAAM,kBAAkB,KAAK,kBAAkB,mBAAmB,KAAK,OAAO,aAAa;AAC3F,UAAM,aAAa,gBAAgB,cAAc,IAAI;AACrD,UAAM,aAAa,MAAM,WAAW,cAAc;AAElD,WAAO;AAAA,MACL,MAAM,WAAW,iBAAiB;AAAA,MAClC,UAAU,WAAW,eAAe,KAAK,OAAO,IAAI,KAAK;AAAA,MACzD,kBAAkB,WAAW,cAAc,YAAY,MAAK,oBAAI,KAAK,CAAC,GAAE,YAAY;AAAA,IACtF;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,gBAAwD;AACnF,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,SAAmB,CAAC;AAC1B,qBAAe,GAAG,QAAQ,CAAC,UAAU;AACnC,eAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK,CAAC;AAAA,MACjE,CAAC;AACD,qBAAe,GAAG,OAAO,MAAM;AAC7B,gBAAQ,OAAO,OAAO,MAAM,CAAC;AAAA,MAC/B,CAAC;AACD,qBAAe,GAAG,SAAS,MAAM;AAAA,IACnC,CAAC;AAAA,EACH;AACF;","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":";;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":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|