@nuvix/storage 1.0.0 → 2.0.0
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 +141 -275
- package/dist/index.d.ts +14 -470
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/src/device/local.d.ts +28 -10
- package/dist/src/device/local.d.ts.map +1 -1
- package/dist/src/device/minio.d.ts +16 -10
- package/dist/src/device/minio.d.ts.map +1 -1
- package/dist/src/device/s3.d.ts +63 -53
- package/dist/src/device/s3.d.ts.map +1 -1
- package/dist/src/device/wasabi.d.ts +13 -11
- package/dist/src/device/wasabi.d.ts.map +1 -1
- package/dist/src/device.d.ts +74 -102
- package/dist/src/device.d.ts.map +1 -1
- package/dist/src/errors.d.ts +15 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/storage.d.ts +23 -36
- package/dist/src/storage.d.ts.map +1 -1
- package/dist/src/validator/file-ext.d.ts +1 -1
- package/dist/src/validator/file-ext.d.ts.map +1 -1
- package/dist/src/validator/file-name.d.ts +1 -1
- package/dist/src/validator/file-name.d.ts.map +1 -1
- package/dist/src/validator/file-size.d.ts +1 -1
- package/dist/src/validator/file-size.d.ts.map +1 -1
- package/dist/src/validator/file-type.d.ts +4 -8
- package/dist/src/validator/file-type.d.ts.map +1 -1
- package/dist/src/validator/file.d.ts +2 -2
- package/dist/src/validator/file.d.ts.map +1 -1
- package/dist/src/validator/upload.d.ts +1 -1
- package/dist/src/validator/upload.d.ts.map +1 -1
- package/package.json +23 -35
- package/dist/index.cjs.js +0 -1296
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.esm.js +0 -1283
- package/dist/index.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,361 +1,227 @@
|
|
|
1
1
|
# @nuvix/storage
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A TypeScript-first storage library for the Nuvix BaaS platform, built entirely on [Bun](https://bun.sh)'s native APIs (`Bun.file`, `Bun.S3Client`). Provides a unified API across local filesystem, AWS S3, Wasabi, and MinIO — with zero runtime dependencies.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Requirements
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- 🔌 **Multiple Storage Backends** - Local, AWS S3, Wasabi, MinIO, and more
|
|
9
|
-
- 📝 **TypeScript First** - Full type safety with comprehensive TypeScript definitions
|
|
10
|
-
- ✅ **File Validation** - Built-in validators for file types, sizes, names, and extensions
|
|
11
|
-
- 🔄 **Chunked Uploads** - Support for large file uploads with multipart upload
|
|
12
|
-
- 🌐 **Modern Builds** - ESM and CommonJS support for maximum compatibility
|
|
13
|
-
- 🧪 **Well Tested** - Comprehensive test suite with real implementation testing
|
|
7
|
+
- **[Bun](https://bun.sh) >= 1.2.0** (required at runtime — this library is Bun-only)
|
|
14
8
|
|
|
15
|
-
##
|
|
9
|
+
## Features
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
- 🚀 **Zero dependencies** — signing, multipart uploads, and XML parsing are handled natively by `Bun.S3Client`
|
|
12
|
+
- 🔌 **Multiple backends** — Local filesystem, AWS S3, Wasabi, and MinIO behind one interface
|
|
13
|
+
- ✍️ **Options-object constructors** — explicit, typed configuration for every device
|
|
14
|
+
- 🔏 **Presigned URLs** — generate time-limited upload/download URLs offline (no network call)
|
|
15
|
+
- 📊 **File stats** — size + MIME type in a single `stat()` call
|
|
16
|
+
- 🔄 **Chunked uploads** — large files assembled from ordered chunks, with abort support
|
|
17
|
+
- 🛡️ **Typed errors** — every failure throws a `StorageError` with a machine-readable `code`
|
|
18
|
+
- ✅ **Validators** — file extension, name, size, content type (magic bytes), and upload checks
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
pnpm add @nuvix/storage
|
|
20
|
+
## Installation
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
```bash
|
|
28
23
|
bun add @nuvix/storage
|
|
29
24
|
```
|
|
30
25
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
### ESM (Modern)
|
|
26
|
+
## Quick Start
|
|
34
27
|
|
|
35
28
|
```typescript
|
|
36
|
-
import {
|
|
37
|
-
Storage,
|
|
38
|
-
Local,
|
|
39
|
-
Wasabi,
|
|
40
|
-
MinIO,
|
|
41
|
-
FileExt,
|
|
42
|
-
FileSize,
|
|
43
|
-
} from "@nuvix/storage";
|
|
44
|
-
|
|
45
|
-
// Set up local storage
|
|
46
|
-
const localStorage = new Local("./uploads");
|
|
47
|
-
Storage.setDevice(Storage.DEVICE_LOCAL, localStorage);
|
|
48
|
-
|
|
49
|
-
// Upload a file
|
|
50
|
-
const localDevice = Storage.getDevice(Storage.DEVICE_LOCAL);
|
|
51
|
-
await localDevice.write("test.txt", "Hello, World!", "text/plain");
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### CommonJS (Legacy)
|
|
29
|
+
import { Storage, Local } from "@nuvix/storage";
|
|
55
30
|
|
|
56
|
-
|
|
57
|
-
const { Storage, Local, Wasabi, MinIO } = require("@nuvix/storage");
|
|
58
|
-
|
|
59
|
-
// Set up local storage
|
|
60
|
-
const localStorage = new Local("./uploads");
|
|
31
|
+
const localStorage = new Local({ root: "./uploads" });
|
|
61
32
|
Storage.setDevice(Storage.DEVICE_LOCAL, localStorage);
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## 🔧 Storage Devices
|
|
65
|
-
|
|
66
|
-
### Local File System
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
import { Local, Storage } from "@nuvix/storage";
|
|
70
|
-
|
|
71
|
-
const localStorage = new Local("./uploads");
|
|
72
|
-
Storage.setDevice("local", localStorage);
|
|
73
|
-
|
|
74
|
-
// Write file
|
|
75
|
-
await localStorage.write("documents/file.txt", "content", "text/plain");
|
|
76
33
|
|
|
77
|
-
|
|
78
|
-
|
|
34
|
+
const device = Storage.getDevice(Storage.DEVICE_LOCAL);
|
|
35
|
+
await device.write("hello.txt", "Hello, World!", "text/plain");
|
|
79
36
|
|
|
80
|
-
|
|
81
|
-
const exists = await localStorage.exists("documents/file.txt");
|
|
37
|
+
console.log(await device.read("hello.txt")); // Buffer("Hello, World!")
|
|
82
38
|
```
|
|
83
39
|
|
|
84
|
-
|
|
40
|
+
## Storage Devices
|
|
85
41
|
|
|
86
|
-
|
|
87
|
-
import { Wasabi, Storage } from "@nuvix/storage";
|
|
88
|
-
|
|
89
|
-
const wasabiStorage = new Wasabi(
|
|
90
|
-
"my-app-uploads", // root path
|
|
91
|
-
"your-access-key", // access key
|
|
92
|
-
"your-secret-key", // secret key
|
|
93
|
-
"your-bucket-name", // bucket name
|
|
94
|
-
Wasabi.US_CENTRAL_1, // region
|
|
95
|
-
Wasabi.ACL_PRIVATE, // ACL (optional)
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
Storage.setDevice("wasabi", wasabiStorage);
|
|
99
|
-
|
|
100
|
-
// Upload with metadata
|
|
101
|
-
await wasabiStorage.uploadData(
|
|
102
|
-
"Hello, Cloud!",
|
|
103
|
-
"cloud-file.txt",
|
|
104
|
-
"text/plain",
|
|
105
|
-
1,
|
|
106
|
-
1,
|
|
107
|
-
{ author: "user123" },
|
|
108
|
-
);
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### AWS S3
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
import { S3, Storage } from "@nuvix/storage";
|
|
115
|
-
|
|
116
|
-
const s3Storage = new S3(
|
|
117
|
-
"my-app-uploads", // root path
|
|
118
|
-
"your-access-key", // access key
|
|
119
|
-
"your-secret-key", // secret key
|
|
120
|
-
"your-bucket-name", // bucket name
|
|
121
|
-
S3.US_EAST_1, // region
|
|
122
|
-
S3.ACL_PRIVATE, // ACL (optional)
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
Storage.setDevice("s3", s3Storage);
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### MinIO
|
|
42
|
+
### Local Filesystem
|
|
129
43
|
|
|
130
44
|
```typescript
|
|
131
|
-
import {
|
|
132
|
-
|
|
133
|
-
const minioStorage = new MinIO(
|
|
134
|
-
"my-app-uploads", // root path
|
|
135
|
-
"minioadmin", // access key (default MinIO credentials)
|
|
136
|
-
"minioadmin", // secret key (default MinIO credentials)
|
|
137
|
-
"your-bucket-name", // bucket name
|
|
138
|
-
"localhost:9000", // MinIO endpoint
|
|
139
|
-
MinIO.ACL_PRIVATE, // ACL (optional)
|
|
140
|
-
false, // useSSL (optional, default: false)
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
Storage.setDevice("minio", minioStorage);
|
|
144
|
-
|
|
145
|
-
// Upload to MinIO
|
|
146
|
-
await minioStorage.write("local-file.txt", "Hello, MinIO!", "text/plain");
|
|
45
|
+
import { Local } from "@nuvix/storage";
|
|
147
46
|
|
|
148
|
-
//
|
|
149
|
-
const
|
|
47
|
+
// Root defaults to the current working directory
|
|
48
|
+
const device = new Local({ root: "./uploads" });
|
|
150
49
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// Get file information
|
|
155
|
-
const size = await minioStorage.getFileSize("local-file.txt");
|
|
156
|
-
const mimeType = await minioStorage.getFileMimeType("local-file.txt");
|
|
50
|
+
await device.write("docs/report.pdf", buffer);
|
|
51
|
+
await device.exists("docs/report.pdf"); // true
|
|
52
|
+
await device.stat("docs/report.pdf"); // { size, mimeType }
|
|
157
53
|
```
|
|
158
54
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
### File Extension Validation
|
|
55
|
+
### AWS S3
|
|
162
56
|
|
|
163
57
|
```typescript
|
|
164
|
-
import {
|
|
58
|
+
import { S3 } from "@nuvix/storage";
|
|
165
59
|
|
|
166
|
-
const
|
|
60
|
+
const device = new S3({
|
|
61
|
+
accessKeyId: "your-access-key",
|
|
62
|
+
secretAccessKey: "your-secret-key",
|
|
63
|
+
bucket: "your-bucket",
|
|
64
|
+
region: S3.US_EAST_1, // default
|
|
65
|
+
acl: S3.ACL_PRIVATE, // optional
|
|
66
|
+
root: "app-uploads", // optional key prefix
|
|
67
|
+
endpoint: "https://...", // optional custom endpoint (path-style URLs)
|
|
68
|
+
});
|
|
167
69
|
|
|
168
|
-
|
|
169
|
-
|
|
70
|
+
// Presigned URL — computed locally, no network round-trip
|
|
71
|
+
const url = device.presign("reports/q3.pdf", { expiresIn: 3600 });
|
|
170
72
|
```
|
|
171
73
|
|
|
172
|
-
###
|
|
74
|
+
### Wasabi
|
|
173
75
|
|
|
174
76
|
```typescript
|
|
175
|
-
import {
|
|
176
|
-
|
|
177
|
-
const sizeValidator = new FileSize(5 * 1024 * 1024); // 5MB limit
|
|
77
|
+
import { Wasabi } from "@nuvix/storage";
|
|
178
78
|
|
|
179
|
-
|
|
180
|
-
|
|
79
|
+
// Endpoint is derived automatically: https://s3.{region}.wasabisys.com
|
|
80
|
+
const device = new Wasabi({
|
|
81
|
+
accessKeyId: "your-access-key",
|
|
82
|
+
secretAccessKey: "your-secret-key",
|
|
83
|
+
bucket: "your-bucket",
|
|
84
|
+
region: Wasabi.EU_CENTRAL_1, // default
|
|
85
|
+
});
|
|
181
86
|
```
|
|
182
87
|
|
|
183
|
-
###
|
|
88
|
+
### MinIO
|
|
184
89
|
|
|
185
90
|
```typescript
|
|
186
|
-
import {
|
|
187
|
-
|
|
188
|
-
const nameValidator = new FileName();
|
|
91
|
+
import { MinIO } from "@nuvix/storage";
|
|
189
92
|
|
|
190
|
-
|
|
191
|
-
|
|
93
|
+
const device = new MinIO({
|
|
94
|
+
accessKeyId: "minioadmin",
|
|
95
|
+
secretAccessKey: "minioadmin",
|
|
96
|
+
bucket: "your-bucket",
|
|
97
|
+
endpoint: "localhost:9000", // default; protocol prefix is stripped
|
|
98
|
+
useSSL: false, // default
|
|
99
|
+
});
|
|
192
100
|
```
|
|
193
101
|
|
|
194
|
-
|
|
102
|
+
## File Validation
|
|
195
103
|
|
|
196
104
|
```typescript
|
|
197
|
-
import { FileType } from "@nuvix/storage";
|
|
198
|
-
|
|
199
|
-
const typeValidator = new FileType(["jpeg", "png", "gif"]);
|
|
200
|
-
|
|
201
|
-
// Validates based on file content, not extension
|
|
202
|
-
console.log(await typeValidator.isValid("./image.jpg")); // true if actual JPEG
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Upload File Validation
|
|
105
|
+
import { FileExt, FileName, FileSize, FileType, Upload } from "@nuvix/storage";
|
|
206
106
|
|
|
207
|
-
|
|
208
|
-
|
|
107
|
+
new FileExt(["jpg", "png"]).isValid("photo.jpg"); // true
|
|
108
|
+
new FileName().isValid("report_2024.pdf"); // true
|
|
109
|
+
new FileSize(5 * 1024 * 1024).isValid(1024); // true (< 5MB)
|
|
209
110
|
|
|
210
|
-
|
|
111
|
+
// Content-type check via magic bytes — reads only the first few bytes of the file
|
|
112
|
+
await new FileType([FileType.FILE_TYPE_PNG]).isValid("./maybe-image.png");
|
|
211
113
|
|
|
212
|
-
|
|
213
|
-
|
|
114
|
+
// Verifies the file actually exists on disk
|
|
115
|
+
await new Upload().isValid("./uploaded.txt");
|
|
214
116
|
```
|
|
215
117
|
|
|
216
|
-
##
|
|
118
|
+
## Error Handling
|
|
217
119
|
|
|
218
|
-
|
|
120
|
+
All failures throw a `StorageError` with a stable `code` you can branch on:
|
|
219
121
|
|
|
220
122
|
```typescript
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"text/plain",
|
|
230
|
-
i + 1, // current chunk
|
|
231
|
-
chunks.length, // total chunks
|
|
232
|
-
metadata,
|
|
233
|
-
);
|
|
123
|
+
import { StorageError } from "@nuvix/storage";
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
await device.read("missing.txt");
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof StorageError && error.code === "FILE_NOT_FOUND") {
|
|
129
|
+
// handle gracefully
|
|
130
|
+
}
|
|
234
131
|
}
|
|
235
132
|
```
|
|
236
133
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
134
|
+
| Code | Thrown when |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `DEVICE_NOT_FOUND` | `Storage.getDevice()` with an unregistered name |
|
|
137
|
+
| `FILE_NOT_FOUND` | Reading/stat a missing file, or aborting an upload with no staged parts |
|
|
138
|
+
| `WRITE_FAILED` / `READ_FAILED` | Filesystem or S3 I/O failure |
|
|
139
|
+
| `UPLOAD_FAILED` | A chunk could not be staged |
|
|
140
|
+
| `TRANSFER_FAILED` | Cross-device transfer failed mid-stream |
|
|
141
|
+
| `DELETE_FAILED` | Deletion failed |
|
|
142
|
+
| `UNSUPPORTED_OPERATION` | e.g. `presign()` on a device without support |
|
|
143
|
+
| `INVALID_CONFIG` | Device constructed with missing credentials |
|
|
242
144
|
|
|
243
|
-
|
|
244
|
-
await sourceDevice.transfer("local-file.txt", "cloud-file.txt", targetDevice);
|
|
245
|
-
```
|
|
145
|
+
## Chunked Uploads
|
|
246
146
|
|
|
247
|
-
|
|
147
|
+
Upload large files in ordered chunks; the final chunk triggers assembly:
|
|
248
148
|
|
|
249
149
|
```typescript
|
|
250
|
-
|
|
150
|
+
const metadata = {};
|
|
151
|
+
for (let chunk = 1; chunk <= totalChunks; chunk++) {
|
|
152
|
+
await device.uploadData(chunkBuffer, "big-file.bin", "application/octet-stream", chunk, totalChunks, metadata);
|
|
153
|
+
}
|
|
251
154
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
console.log(Storage.human(1024, 2, "binary")); // "1.00KiB"
|
|
155
|
+
// Or give up and clean any staged parts:
|
|
156
|
+
await device.abort("big-file.bin");
|
|
255
157
|
```
|
|
256
158
|
|
|
257
|
-
##
|
|
159
|
+
## Device Registry & Utilities
|
|
258
160
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
# Build and watch for changes
|
|
266
|
-
bun run build:watch
|
|
161
|
+
```typescript
|
|
162
|
+
Storage.setDevice("avatars", device); // register
|
|
163
|
+
Storage.getDevice("avatars"); // retrieve (throws DEVICE_NOT_FOUND)
|
|
164
|
+
Storage.exists("avatars"); // boolean
|
|
165
|
+
Storage.listDevices(); // string[]
|
|
166
|
+
Storage.removeDevice("avatars"); // unregister
|
|
267
167
|
|
|
268
|
-
|
|
269
|
-
|
|
168
|
+
Storage.human(1536); // "1.54kB"
|
|
169
|
+
Storage.human(1048576, 2, "binary"); // "1.00MiB"
|
|
270
170
|
```
|
|
271
171
|
|
|
272
|
-
|
|
172
|
+
### Common Device Methods
|
|
273
173
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
# Run all tests
|
|
278
|
-
bun test
|
|
174
|
+
Every device implements the same interface:
|
|
279
175
|
|
|
280
|
-
|
|
281
|
-
|
|
176
|
+
- `write(path, data, contentType?)` / `read(path, offset?, length?)`
|
|
177
|
+
- `upload(source, path, chunk?, chunks?, metadata?)` — move a file from disk into storage
|
|
178
|
+
- `uploadData(data, path, contentType, chunk?, chunks?, metadata?)` — upload raw data
|
|
179
|
+
- `exists(path)` / `delete(path)` / `deletePath(path)`
|
|
180
|
+
- `stat(path)` → `{ size, mimeType }`
|
|
181
|
+
- `getFileSize(path)` / `getFileMimeType(path)` / `getFileHash(path)` (MD5)
|
|
182
|
+
- `transfer(source, destination, targetDevice)` / `move(source, target)`
|
|
183
|
+
- `createDirectory(path)` / `getDirectorySize(path)` / `getFiles(dir)`
|
|
184
|
+
- `presign(path, options?)` — presigned URL where supported
|
|
185
|
+
- `getTransferChunkSize()` / `setTransferChunkSize(bytes)`
|
|
282
186
|
|
|
283
|
-
|
|
284
|
-
bun run test:coverage
|
|
187
|
+
## Migrating from v1
|
|
285
188
|
|
|
286
|
-
|
|
287
|
-
bun test storage.test.ts
|
|
288
|
-
bun test device/
|
|
289
|
-
bun test validator/
|
|
290
|
-
```
|
|
189
|
+
v2.0.0 is a breaking release:
|
|
291
190
|
|
|
292
|
-
|
|
191
|
+
- **Bun only** — Node.js is no longer supported. The hand-rolled SigV4/XML client was replaced by `Bun.S3Client`.
|
|
192
|
+
- **Constructors take a single options object** instead of positional arguments:
|
|
193
|
+
```diff
|
|
194
|
+
- new S3("root", accessKey, secretKey, bucket, S3.US_EAST_1)
|
|
195
|
+
+ new S3({ accessKeyId, secretAccessKey, bucket, region: S3.US_EAST_1, root: "root" })
|
|
196
|
+
```
|
|
197
|
+
- **ESM only** — CommonJS builds are no longer published.
|
|
198
|
+
- **Errors are typed** — methods throw `StorageError` (with `.code`) instead of plain `Error`s or silent booleans.
|
|
199
|
+
- **Fixed:** `S3.SA_EAST_1` now maps to `"sa-east-1"` (previously incorrectly mapped to `"eu-north-1"`).
|
|
200
|
+
- **New:** `stat()`, `presign()`, `Storage.removeDevice()`, `Storage.listDevices()`, `move()`, `abort()`.
|
|
293
201
|
|
|
294
|
-
|
|
202
|
+
## Development
|
|
295
203
|
|
|
296
204
|
```bash
|
|
297
|
-
#
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
#
|
|
303
|
-
export AWS_ACCESS_KEY="your-access-key"
|
|
304
|
-
export AWS_SECRET_KEY="your-secret-key"
|
|
305
|
-
export AWS_BUCKET="your-test-bucket"
|
|
306
|
-
|
|
307
|
-
# For MinIO testing
|
|
308
|
-
export MINIO_ACCESS_KEY="minioadmin"
|
|
309
|
-
export MINIO_SECRET_KEY="minioadmin"
|
|
310
|
-
export MINIO_BUCKET="test-bucket"
|
|
311
|
-
export MINIO_ENDPOINT="localhost:9000"
|
|
205
|
+
bun install # install dev dependencies
|
|
206
|
+
bun test # run test suite
|
|
207
|
+
bun run test:watch # watch mode
|
|
208
|
+
bun run lint # oxlint
|
|
209
|
+
bun run typecheck # tsc --noEmit
|
|
210
|
+
bun run build # bundle to dist/ (ESM + declarations)
|
|
312
211
|
```
|
|
313
212
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
### Storage Class
|
|
317
|
-
|
|
318
|
-
- `Storage.setDevice(name, device)` - Register a storage device
|
|
319
|
-
- `Storage.getDevice(name)` - Get a registered storage device
|
|
320
|
-
- `Storage.exists(name)` - Check if a device is registered
|
|
321
|
-
- `Storage.human(bytes, decimals?, system?)` - Format bytes to human-readable string
|
|
322
|
-
|
|
323
|
-
### Device Interface
|
|
213
|
+
Tests that hit real cloud services stay skipped unless credentials are provided via environment variables (`AWS_*`, `WASABI_*`, `MINIO_*`).
|
|
324
214
|
|
|
325
|
-
|
|
215
|
+
## Contributing
|
|
326
216
|
|
|
327
|
-
|
|
328
|
-
- `uploadData(data, path, contentType, chunk?, chunks?, metadata?)` - Upload data
|
|
329
|
-
- `read(path, offset?, length?)` - Read file content
|
|
330
|
-
- `write(path, data, contentType)` - Write file
|
|
331
|
-
- `delete(path, recursive?)` - Delete file/directory
|
|
332
|
-
- `exists(path)` - Check if file exists
|
|
333
|
-
- `getFileSize(path)` - Get file size
|
|
334
|
-
- `getFileMimeType(path)` - Get file MIME type
|
|
335
|
-
- `getFileHash(path)` - Get file MD5 hash
|
|
336
|
-
- `transfer(source, destination, targetDevice)` - Transfer file
|
|
337
|
-
|
|
338
|
-
## 🌍 Browser Support
|
|
339
|
-
|
|
340
|
-
This library is designed for Node.js environments. For browser usage, you'll need to provide polyfills for Node.js modules or use a bundler that can handle Node.js dependencies.
|
|
341
|
-
|
|
342
|
-
## 🤝 Contributing
|
|
343
|
-
|
|
344
|
-
Contributions are welcome! Please read our contributing guidelines and ensure all tests pass:
|
|
345
|
-
|
|
346
|
-
```bash
|
|
347
|
-
bun run lint # Check code style
|
|
348
|
-
bun run lint:fix # Fix code style issues
|
|
349
|
-
bun test # Run test suite
|
|
350
|
-
```
|
|
217
|
+
Contributions are welcome! Please ensure `bun test`, `bun run lint`, and `bun run typecheck` all pass before opening a PR.
|
|
351
218
|
|
|
352
|
-
##
|
|
219
|
+
## License
|
|
353
220
|
|
|
354
221
|
MIT © [Nuvix](https://github.com/nuvix-tech/storage)
|
|
355
222
|
|
|
356
|
-
##
|
|
223
|
+
## Links
|
|
357
224
|
|
|
358
225
|
- [GitHub Repository](https://github.com/nuvix-tech/storage)
|
|
359
226
|
- [NPM Package](https://www.npmjs.com/package/@nuvix/storage)
|
|
360
|
-
- [Documentation](https://github.com/nuvix-tech/storage#readme)
|
|
361
227
|
- [Issue Tracker](https://github.com/nuvix-tech/storage/issues)
|