@veloxts/storage 0.6.87 → 0.6.89
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/GUIDE.md +126 -29
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.d.ts +16 -0
- package/dist/plugin.js +21 -3
- package/package.json +5 -5
package/GUIDE.md
CHANGED
|
@@ -1,43 +1,61 @@
|
|
|
1
1
|
# @veloxts/storage Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
File storage abstraction for VeloxTS applications with support for local filesystem and S3-compatible storage (AWS S3, Cloudflare R2, MinIO).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @veloxts/storage
|
|
9
|
+
|
|
10
|
+
# For S3/R2 (production)
|
|
11
|
+
pnpm add @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Development (Local)
|
|
8
17
|
|
|
9
18
|
```typescript
|
|
19
|
+
import { veloxApp } from '@veloxts/core';
|
|
10
20
|
import { storagePlugin } from '@veloxts/storage';
|
|
11
21
|
|
|
12
|
-
app
|
|
22
|
+
const app = veloxApp();
|
|
23
|
+
|
|
24
|
+
app.register(storagePlugin({
|
|
13
25
|
driver: 'local',
|
|
14
26
|
config: {
|
|
15
27
|
root: './storage',
|
|
16
28
|
baseUrl: 'http://localhost:3030/files',
|
|
17
29
|
},
|
|
18
30
|
}));
|
|
31
|
+
|
|
32
|
+
await app.start();
|
|
19
33
|
```
|
|
20
34
|
|
|
21
|
-
### S3
|
|
35
|
+
### Production (AWS S3)
|
|
22
36
|
|
|
23
|
-
|
|
37
|
+
```typescript
|
|
38
|
+
import { veloxApp } from '@veloxts/core';
|
|
39
|
+
import { storagePlugin } from '@veloxts/storage';
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
|
|
27
|
-
```
|
|
41
|
+
const app = veloxApp();
|
|
28
42
|
|
|
29
|
-
|
|
30
|
-
// AWS S3
|
|
31
|
-
app.use(storagePlugin({
|
|
43
|
+
app.register(storagePlugin({
|
|
32
44
|
driver: 's3',
|
|
33
45
|
config: {
|
|
34
46
|
bucket: process.env.S3_BUCKET,
|
|
35
|
-
region:
|
|
47
|
+
region: process.env.S3_REGION,
|
|
48
|
+
// Uses AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from env
|
|
36
49
|
},
|
|
37
50
|
}));
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
await app.start();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Production (Cloudflare R2)
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
app.register(storagePlugin({
|
|
41
59
|
driver: 's3',
|
|
42
60
|
config: {
|
|
43
61
|
bucket: process.env.R2_BUCKET,
|
|
@@ -47,19 +65,22 @@ app.use(storagePlugin({
|
|
|
47
65
|
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
|
|
48
66
|
},
|
|
49
67
|
}));
|
|
68
|
+
```
|
|
50
69
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
**Environment Variables:**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# .env (AWS S3)
|
|
74
|
+
S3_BUCKET=my-bucket
|
|
75
|
+
S3_REGION=us-east-1
|
|
76
|
+
AWS_ACCESS_KEY_ID=AKIA...
|
|
77
|
+
AWS_SECRET_ACCESS_KEY=...
|
|
78
|
+
|
|
79
|
+
# .env (Cloudflare R2)
|
|
80
|
+
R2_BUCKET=my-bucket
|
|
81
|
+
R2_ACCOUNT_ID=your-account-id
|
|
82
|
+
R2_ACCESS_KEY_ID=...
|
|
83
|
+
R2_SECRET_ACCESS_KEY=...
|
|
63
84
|
```
|
|
64
85
|
|
|
65
86
|
## Basic Operations
|
|
@@ -77,7 +98,7 @@ await ctx.storage.put('videos/large.mp4', readableStream);
|
|
|
77
98
|
// Download a file
|
|
78
99
|
const content = await ctx.storage.get('documents/report.pdf');
|
|
79
100
|
|
|
80
|
-
// Stream a file (memory-efficient
|
|
101
|
+
// Stream a file (memory-efficient)
|
|
81
102
|
const stream = await ctx.storage.stream('videos/large.mp4');
|
|
82
103
|
|
|
83
104
|
// Check if file exists
|
|
@@ -98,7 +119,7 @@ const url = await ctx.storage.url('avatars/user-123.jpg');
|
|
|
98
119
|
|
|
99
120
|
// Signed URL (temporary access to private files)
|
|
100
121
|
const signedUrl = await ctx.storage.signedUrl('documents/private.pdf', {
|
|
101
|
-
expiresIn: 3600, // 1 hour
|
|
122
|
+
expiresIn: 3600, // 1 hour in seconds
|
|
102
123
|
});
|
|
103
124
|
```
|
|
104
125
|
|
|
@@ -143,3 +164,79 @@ do {
|
|
|
143
164
|
// Set visibility
|
|
144
165
|
await ctx.storage.setVisibility('file.jpg', 'public'); // or 'private'
|
|
145
166
|
```
|
|
167
|
+
|
|
168
|
+
## Production Deployment
|
|
169
|
+
|
|
170
|
+
### Choosing a Provider
|
|
171
|
+
|
|
172
|
+
| Provider | Best For |
|
|
173
|
+
|----------|----------|
|
|
174
|
+
| [Cloudflare R2](https://developers.cloudflare.com/r2/) | Zero egress fees, global edge |
|
|
175
|
+
| [AWS S3](https://aws.amazon.com/s3/) | Mature ecosystem, extensive features |
|
|
176
|
+
| [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces) | Simple pricing, S3-compatible |
|
|
177
|
+
| [MinIO](https://min.io/) | Self-hosted, S3-compatible |
|
|
178
|
+
|
|
179
|
+
### Production Checklist
|
|
180
|
+
|
|
181
|
+
1. **Use S3-compatible storage** - Local filesystem doesn't scale
|
|
182
|
+
2. **Configure bucket policies** - Least privilege access
|
|
183
|
+
3. **Set proper CORS** - For direct browser uploads
|
|
184
|
+
4. **Use signed URLs for private files** - Time-limited access
|
|
185
|
+
5. **Enable versioning** - For critical files (optional)
|
|
186
|
+
|
|
187
|
+
### Complete S3 Configuration
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
app.register(storagePlugin({
|
|
191
|
+
driver: 's3',
|
|
192
|
+
config: {
|
|
193
|
+
bucket: process.env.S3_BUCKET,
|
|
194
|
+
region: process.env.S3_REGION,
|
|
195
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
196
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
197
|
+
|
|
198
|
+
// Optional settings
|
|
199
|
+
endpoint: process.env.S3_ENDPOINT, // For R2, MinIO, etc.
|
|
200
|
+
forcePathStyle: false, // true for MinIO
|
|
201
|
+
defaultVisibility: 'private',
|
|
202
|
+
},
|
|
203
|
+
}));
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Serving Files in Production
|
|
207
|
+
|
|
208
|
+
For public files, use a CDN in front of your storage:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
app.register(storagePlugin({
|
|
212
|
+
driver: 's3',
|
|
213
|
+
config: {
|
|
214
|
+
bucket: process.env.S3_BUCKET,
|
|
215
|
+
region: process.env.S3_REGION,
|
|
216
|
+
publicUrl: 'https://cdn.example.com', // CDN URL
|
|
217
|
+
},
|
|
218
|
+
}));
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Standalone Usage
|
|
222
|
+
|
|
223
|
+
Use storage outside of Fastify request context (CLI commands, background jobs):
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { getStorage, closeStorage } from '@veloxts/storage';
|
|
227
|
+
|
|
228
|
+
// Get standalone storage instance
|
|
229
|
+
const storage = await getStorage({
|
|
230
|
+
driver: 's3',
|
|
231
|
+
config: {
|
|
232
|
+
bucket: process.env.S3_BUCKET,
|
|
233
|
+
region: process.env.S3_REGION,
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
await storage.put('file.txt', Buffer.from('Hello'));
|
|
238
|
+
const content = await storage.get('file.txt');
|
|
239
|
+
|
|
240
|
+
// Clean up when done
|
|
241
|
+
await closeStorage();
|
|
242
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export { createLocalStore, DRIVER_NAME as LOCAL_DRIVER } from './drivers/local.j
|
|
|
41
41
|
export { createS3Store, DRIVER_NAME as S3_DRIVER } from './drivers/s3.js';
|
|
42
42
|
export { FileExistsError, FileNotFoundError, InvalidPathError, isFileNotFoundError, isPermissionDeniedError, isStorageError, PermissionDeniedError, QuotaExceededError, S3Error, StorageConfigError, StorageError, } from './errors.js';
|
|
43
43
|
export { createStorageManager, type StorageManager, storage } from './manager.js';
|
|
44
|
-
export { _resetStandaloneStorage, getStorage, getStorageFromInstance, storagePlugin, } from './plugin.js';
|
|
44
|
+
export { _resetStandaloneStorage, closeStorage, getStorage, getStorageFromInstance, storagePlugin, } from './plugin.js';
|
|
45
45
|
export type { CopyOptions, FileMetadata, FileVisibility, GetOptions, ListOptions, ListResult, LocalStorageConfig, PutOptions, S3StorageConfig, SignedUrlOptions, StorageBaseOptions, StorageConfig, StorageDefaultOptions, StorageDriver, StorageLocalOptions, StorageManagerOptions, StoragePluginOptions, StorageS3Options, StorageStore, } from './types.js';
|
|
46
46
|
/**
|
|
47
47
|
* Utility functions for storage operations.
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ export { FileExistsError, FileNotFoundError, InvalidPathError, isFileNotFoundErr
|
|
|
45
45
|
// Manager
|
|
46
46
|
export { createStorageManager, storage } from './manager.js';
|
|
47
47
|
// Plugin
|
|
48
|
-
export { _resetStandaloneStorage, getStorage, getStorageFromInstance, storagePlugin, } from './plugin.js';
|
|
48
|
+
export { _resetStandaloneStorage, closeStorage, getStorage, getStorageFromInstance, storagePlugin, } from './plugin.js';
|
|
49
49
|
/**
|
|
50
50
|
* Utility functions for storage operations.
|
|
51
51
|
*
|
package/dist/plugin.d.ts
CHANGED
|
@@ -100,8 +100,24 @@ export declare function getStorageFromInstance(fastify: FastifyInstance): Storag
|
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
102
|
export declare function getStorage(options?: StoragePluginOptions): Promise<StorageManager>;
|
|
103
|
+
/**
|
|
104
|
+
* Close the standalone storage instance.
|
|
105
|
+
*
|
|
106
|
+
* Call this when shutting down your application to release resources.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import { closeStorage } from '@veloxts/storage';
|
|
111
|
+
*
|
|
112
|
+
* // On shutdown
|
|
113
|
+
* await closeStorage();
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function closeStorage(): Promise<void>;
|
|
103
117
|
/**
|
|
104
118
|
* Reset the standalone storage instance.
|
|
105
119
|
* Primarily used for testing.
|
|
120
|
+
*
|
|
121
|
+
* @deprecated Use `closeStorage()` instead. Will be removed in v2.0.
|
|
106
122
|
*/
|
|
107
123
|
export declare function _resetStandaloneStorage(): Promise<void>;
|
package/dist/plugin.js
CHANGED
|
@@ -121,12 +121,30 @@ export async function getStorage(options) {
|
|
|
121
121
|
return standaloneStorage;
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
124
|
+
* Close the standalone storage instance.
|
|
125
|
+
*
|
|
126
|
+
* Call this when shutting down your application to release resources.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* import { closeStorage } from '@veloxts/storage';
|
|
131
|
+
*
|
|
132
|
+
* // On shutdown
|
|
133
|
+
* await closeStorage();
|
|
134
|
+
* ```
|
|
126
135
|
*/
|
|
127
|
-
export async function
|
|
136
|
+
export async function closeStorage() {
|
|
128
137
|
if (standaloneStorage) {
|
|
129
138
|
await standaloneStorage.close();
|
|
130
139
|
standaloneStorage = null;
|
|
131
140
|
}
|
|
132
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Reset the standalone storage instance.
|
|
144
|
+
* Primarily used for testing.
|
|
145
|
+
*
|
|
146
|
+
* @deprecated Use `closeStorage()` instead. Will be removed in v2.0.
|
|
147
|
+
*/
|
|
148
|
+
export async function _resetStandaloneStorage() {
|
|
149
|
+
await closeStorage();
|
|
150
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veloxts/storage",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.89",
|
|
4
4
|
"description": "Multi-driver file storage abstraction for VeloxTS framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"fastify-plugin": "5.1.0",
|
|
34
34
|
"mime-types": "2.1.35",
|
|
35
|
-
"@veloxts/core": "0.6.
|
|
35
|
+
"@veloxts/core": "0.6.89"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@aws-sdk/client-s3": ">=3.0.0",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"@aws-sdk/lib-storage": "3.821.0",
|
|
57
57
|
"@aws-sdk/s3-request-presigner": "3.821.0",
|
|
58
58
|
"@types/mime-types": "2.1.4",
|
|
59
|
-
"@types/node": "
|
|
59
|
+
"@types/node": "25.0.3",
|
|
60
60
|
"@vitest/coverage-v8": "4.0.16",
|
|
61
61
|
"fastify": "5.6.2",
|
|
62
|
-
"typescript": "5.
|
|
62
|
+
"typescript": "5.9.3",
|
|
63
63
|
"vitest": "4.0.16",
|
|
64
|
-
"@veloxts/testing": "0.6.
|
|
64
|
+
"@veloxts/testing": "0.6.89"
|
|
65
65
|
},
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|