@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 CHANGED
@@ -1,43 +1,61 @@
1
1
  # @veloxts/storage Guide
2
2
 
3
- ## Drivers
3
+ File storage abstraction for VeloxTS applications with support for local filesystem and S3-compatible storage (AWS S3, Cloudflare R2, MinIO).
4
4
 
5
- ### Local Driver (default)
5
+ ## Installation
6
6
 
7
- Store files on the local filesystem.
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.use(storagePlugin({
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 Driver
35
+ ### Production (AWS S3)
22
36
 
23
- S3-compatible storage (AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces).
37
+ ```typescript
38
+ import { veloxApp } from '@veloxts/core';
39
+ import { storagePlugin } from '@veloxts/storage';
24
40
 
25
- ```bash
26
- npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
27
- ```
41
+ const app = veloxApp();
28
42
 
29
- ```typescript
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: 'us-east-1',
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
- // Cloudflare R2
40
- app.use(storagePlugin({
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
- // MinIO (local S3)
52
- app.use(storagePlugin({
53
- driver: 's3',
54
- config: {
55
- bucket: 'my-bucket',
56
- region: 'us-east-1',
57
- endpoint: 'http://localhost:9000',
58
- forcePathStyle: true,
59
- accessKeyId: 'minioadmin',
60
- secretAccessKey: 'minioadmin',
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 for large files)
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
- * Reset the standalone storage instance.
125
- * Primarily used for testing.
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 _resetStandaloneStorage() {
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.87",
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.87"
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": "22.15.29",
59
+ "@types/node": "25.0.3",
60
60
  "@vitest/coverage-v8": "4.0.16",
61
61
  "fastify": "5.6.2",
62
- "typescript": "5.8.3",
62
+ "typescript": "5.9.3",
63
63
  "vitest": "4.0.16",
64
- "@veloxts/testing": "0.6.87"
64
+ "@veloxts/testing": "0.6.89"
65
65
  },
66
66
  "publishConfig": {
67
67
  "access": "public"