@venizia/ignis-docs 0.2.0 → 0.2.1-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 +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +22 -11
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +6 -2
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +182 -93
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +107 -322
- package/content/extensions/components/authentication/api.md +454 -603
- package/content/extensions/components/authentication/errors.md +121 -498
- package/content/extensions/components/authentication/index.md +88 -801
- package/content/extensions/components/authentication/usage.md +207 -956
- package/content/extensions/components/authorization/api.md +736 -656
- package/content/extensions/components/authorization/errors.md +168 -206
- package/content/extensions/components/authorization/index.md +82 -797
- package/content/extensions/components/authorization/usage.md +194 -527
- package/content/extensions/components/health-check.md +71 -243
- package/content/extensions/components/mail/api.md +504 -287
- package/content/extensions/components/mail/errors.md +73 -61
- package/content/extensions/components/mail/index.md +96 -467
- package/content/extensions/components/mail/usage.md +130 -172
- package/content/extensions/components/request-tracker.md +66 -173
- package/content/extensions/components/socket-io/api.md +195 -13
- package/content/extensions/components/socket-io/errors.md +3 -3
- package/content/extensions/components/socket-io/index.md +50 -337
- package/content/extensions/components/socket-io/usage.md +143 -26
- package/content/extensions/components/static-asset/api.md +410 -142
- package/content/extensions/components/static-asset/errors.md +110 -53
- package/content/extensions/components/static-asset/index.md +79 -608
- package/content/extensions/components/static-asset/usage.md +180 -300
- package/content/extensions/components/websocket/api.md +275 -399
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +74 -407
- package/content/extensions/components/websocket/usage.md +110 -341
- package/content/extensions/helpers/cron/index.md +51 -160
- package/content/extensions/helpers/crypto/index.md +62 -483
- package/content/extensions/helpers/crypto/reference.md +456 -0
- package/content/extensions/helpers/env/index.md +60 -178
- package/content/extensions/helpers/error/index.md +221 -207
- package/content/extensions/helpers/inversion/index.md +65 -556
- package/content/extensions/helpers/inversion/reference.md +522 -0
- package/content/extensions/helpers/kafka/admin.md +20 -1
- package/content/extensions/helpers/kafka/compile-binary.md +41 -35
- package/content/extensions/helpers/kafka/consumer.md +54 -20
- package/content/extensions/helpers/kafka/examples.md +21 -16
- package/content/extensions/helpers/kafka/index.md +80 -610
- package/content/extensions/helpers/kafka/producer.md +134 -5
- package/content/extensions/helpers/kafka/schema-registry.md +45 -70
- package/content/extensions/helpers/logger/hf-logger.md +193 -0
- package/content/extensions/helpers/logger/index.md +64 -563
- package/content/extensions/helpers/logger/pino.md +85 -0
- package/content/extensions/helpers/logger/reference.md +746 -0
- package/content/extensions/helpers/network/api.md +241 -195
- package/content/extensions/helpers/network/index.md +72 -530
- package/content/extensions/helpers/queue/index.md +72 -900
- package/content/extensions/helpers/queue/reference.md +467 -0
- package/content/extensions/helpers/redis/index.md +73 -645
- package/content/extensions/helpers/redis/reference.md +727 -0
- package/content/extensions/helpers/secrets/index.md +66 -0
- package/content/extensions/helpers/socket-io/api.md +305 -203
- package/content/extensions/helpers/socket-io/index.md +66 -432
- package/content/extensions/helpers/storage/api.md +564 -462
- package/content/extensions/helpers/storage/index.md +77 -573
- package/content/extensions/helpers/types/index.md +66 -499
- package/content/extensions/helpers/types/reference.md +650 -0
- package/content/extensions/helpers/uid/index.md +58 -227
- package/content/extensions/helpers/websocket/api.md +329 -216
- package/content/extensions/helpers/websocket/index.md +65 -503
- package/content/extensions/helpers/worker-thread/index.md +58 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
- package/content/guides/core-concepts/persistent/transactions.md +1 -1
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/migrations/redis-helpers-migration.md +1 -1
- package/content/guides/migrations/unified-connectors-migration.md +2 -2
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/references/base/application.md +1 -1
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/datasources-reference.md +599 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +17 -39
- package/content/references/base/filter-system/application-usage.md +69 -121
- package/content/references/base/filter-system/array-operators.md +12 -0
- package/content/references/base/filter-system/comparison-operators.md +12 -0
- package/content/references/base/filter-system/default-filter.md +136 -348
- package/content/references/base/filter-system/fields-order-pagination.md +38 -16
- package/content/references/base/filter-system/index.md +106 -257
- package/content/references/base/filter-system/json-filtering.md +12 -2
- package/content/references/base/filter-system/list-operators.md +16 -2
- package/content/references/base/filter-system/logical-operators.md +13 -0
- package/content/references/base/filter-system/null-operators.md +13 -0
- package/content/references/base/filter-system/pattern-matching.md +12 -0
- package/content/references/base/filter-system/quick-reference.md +11 -2
- package/content/references/base/filter-system/range-operators.md +12 -0
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +156 -233
- package/content/references/base/middlewares.md +35 -21
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +80 -1452
- package/content/references/base/repositories/advanced.md +156 -192
- package/content/references/base/repositories/index.md +77 -650
- package/content/references/base/repositories/mixins.md +22 -18
- package/content/references/base/repositories/relations.md +123 -171
- package/content/references/base/repositories/soft-deletable.md +58 -56
- package/content/references/base/secrets.md +263 -0
- package/content/references/base/services.md +2 -2
- package/content/references/configuration/environment-variables.md +48 -4
- package/content/references/configuration/index.md +49 -31
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/index.md +1 -1
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +29 -62
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +57 -218
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/package.json +8 -8
|
@@ -1,238 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
| Class | Extends | Backend | Implements |
|
|
8
|
-
|-------|---------|---------|------------|
|
|
9
|
-
| **MinioHelper** | `BaseStorageHelper` | S3-compatible (MinIO) | `IStorageHelper` |
|
|
10
|
-
| **BunS3Helper** | `BaseStorageHelper` | S3-compatible (Bun-native) | `IStorageHelper` |
|
|
11
|
-
| **DiskHelper** | `BaseStorageHelper` | Local filesystem | `IStorageHelper` |
|
|
12
|
-
| **MemoryStorageHelper** | `BaseHelper` | In-memory key-value | -- |
|
|
13
|
-
|
|
14
|
-
#### Import Paths
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
// Disk and in-memory storage (from base package)
|
|
18
|
-
import { DiskHelper, MemoryStorageHelper } from '@venizia/ignis-helpers';
|
|
19
|
-
|
|
20
|
-
// MinIO storage (separate export path)
|
|
21
|
-
import { MinioHelper } from '@venizia/ignis-helpers/minio';
|
|
22
|
-
|
|
23
|
-
// Bun S3 storage (separate export path, Bun runtime only)
|
|
24
|
-
import { BunS3Helper } from '@venizia/ignis-helpers/bun-s3';
|
|
25
|
-
|
|
26
|
-
// Types
|
|
27
|
-
import type {
|
|
28
|
-
IStorageHelper,
|
|
29
|
-
IStorageHelperOptions,
|
|
30
|
-
IDiskHelperOptions,
|
|
31
|
-
IUploadFile,
|
|
32
|
-
IUploadResult,
|
|
33
|
-
IFileStat,
|
|
34
|
-
IBucketInfo,
|
|
35
|
-
IObjectInfo,
|
|
36
|
-
IListObjectsOptions,
|
|
37
|
-
} from '@venizia/ignis-helpers';
|
|
38
|
-
import type { IMinioHelperOptions } from '@venizia/ignis-helpers/minio';
|
|
39
|
-
import type { IBunS3HelperOptions } from '@venizia/ignis-helpers/bun-s3';
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Creating an Instance
|
|
43
|
-
|
|
44
|
-
### MinIO Storage
|
|
45
|
-
|
|
46
|
-
`MinioHelper` connects to MinIO or any S3-compatible object storage server. The constructor accepts all `minio.ClientOptions` properties alongside `IStorageHelperOptions`.
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
import { MinioHelper } from '@venizia/ignis-helpers/minio';
|
|
50
|
-
|
|
51
|
-
const storage = new MinioHelper({
|
|
52
|
-
endPoint: 'localhost',
|
|
53
|
-
port: 9000,
|
|
54
|
-
useSSL: false,
|
|
55
|
-
accessKey: 'minioadmin',
|
|
56
|
-
secretKey: 'minioadmin',
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
#### IMinioHelperOptions
|
|
61
|
-
|
|
62
|
-
`IMinioHelperOptions` extends both `IStorageHelperOptions` and the minio `ClientOptions` type, so all [minio Client options](https://min.io/docs/minio/linux/developers/javascript/API.html) are accepted.
|
|
1
|
+
---
|
|
2
|
+
title: Storage
|
|
3
|
+
description: A unified file storage interface with interchangeable S3-compatible, filesystem, and in-memory backends
|
|
4
|
+
difficulty: intermediate
|
|
5
|
+
---
|
|
63
6
|
|
|
64
|
-
|
|
65
|
-
interface IMinioHelperOptions extends IStorageHelperOptions, ClientOptions {}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
| Option | Type | Default | Description |
|
|
69
|
-
|--------|------|---------|-------------|
|
|
70
|
-
| `endPoint` | `string` | -- | MinIO server hostname. |
|
|
71
|
-
| `port` | `number` | -- | Server port. |
|
|
72
|
-
| `useSSL` | `boolean` | -- | Enable HTTPS. |
|
|
73
|
-
| `accessKey` | `string` | -- | Access key credential. |
|
|
74
|
-
| `secretKey` | `string` | -- | Secret key credential. |
|
|
75
|
-
| `scope` | `string` | `'MinioHelper'` | Logger scope name. |
|
|
76
|
-
| `identifier` | `string` | `'MinioHelper'` | Helper identifier. |
|
|
77
|
-
|
|
78
|
-
> [!NOTE]
|
|
79
|
-
> The underlying `minio.Client` is stored as a private property. Use the `IStorageHelper` methods for all operations. If you need direct minio SDK access, extend `MinioHelper` in a subclass.
|
|
80
|
-
|
|
81
|
-
### Bun S3 Storage
|
|
82
|
-
|
|
83
|
-
`BunS3Helper` provides S3-compatible storage using Bun's native `S3Client` for high-performance object operations. Bucket management operations (list, create, delete) use AWS Signature V4 signed requests, while object operations use Bun's native S3 API.
|
|
84
|
-
|
|
85
|
-
> [!IMPORTANT]
|
|
86
|
-
> `BunS3Helper` requires the **Bun runtime**. It uses Bun's built-in `S3Client` class which is not available in Node.js.
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
import { BunS3Helper } from '@venizia/ignis-helpers/bun-s3';
|
|
90
|
-
|
|
91
|
-
const storage = new BunS3Helper({
|
|
92
|
-
accessKey: 'minioadmin',
|
|
93
|
-
secretKey: 'minioadmin',
|
|
94
|
-
endpoint: 'http://localhost:9000',
|
|
95
|
-
region: 'us-east-1',
|
|
96
|
-
});
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
#### IBunS3HelperOptions
|
|
7
|
+
# Storage
|
|
100
8
|
|
|
101
|
-
|
|
102
|
-
|--------|------|---------|-------------|
|
|
103
|
-
| `accessKey` | `string` | -- | S3 access key credential. |
|
|
104
|
-
| `secretKey` | `string` | -- | S3 secret key credential. |
|
|
105
|
-
| `endpoint` | `string` | -- | S3-compatible endpoint URL (e.g., `'http://localhost:9000'`). |
|
|
106
|
-
| `region` | `string` | `'us-east-1'` | AWS region for signing. |
|
|
107
|
-
| `sessionToken` | `string` | -- | Optional session token for temporary credentials. |
|
|
108
|
-
| `scope` | `string` | `'BunS3Helper'` | Logger scope name. |
|
|
109
|
-
| `identifier` | `string` | `'BunS3Helper'` | Helper identifier. |
|
|
9
|
+
Storage gives you one file-storage interface with interchangeable backends for S3-compatible object storage, the local filesystem, and in-memory key-value caching.
|
|
110
10
|
|
|
111
|
-
|
|
11
|
+
## In one example
|
|
112
12
|
|
|
113
|
-
`DiskHelper`
|
|
13
|
+
`DiskHelper` needs no external server, so it is the fastest way to see the shape of the API - create a bucket, upload a file, get a link back.
|
|
114
14
|
|
|
115
15
|
```typescript
|
|
116
16
|
import { DiskHelper } from '@venizia/ignis-helpers';
|
|
117
17
|
|
|
118
|
-
const storage = new DiskHelper({
|
|
119
|
-
basePath: './app_data/storage',
|
|
120
|
-
});
|
|
121
|
-
```
|
|
18
|
+
const storage = new DiskHelper({ basePath: './app_data/storage' });
|
|
122
19
|
|
|
123
|
-
|
|
20
|
+
await storage.createBucket({ name: 'uploads' });
|
|
124
21
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
| `basePath` | `string` | -- | Base directory where buckets will be created. Resolved to an absolute path internally. Created automatically if it does not exist. |
|
|
128
|
-
| `scope` | `string` | `'DiskHelper'` | Logger scope name. |
|
|
129
|
-
| `identifier` | `string` | `'DiskHelper'` | Helper identifier. |
|
|
130
|
-
|
|
131
|
-
The resulting directory structure maps buckets to subdirectories:
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
app_data/storage/ <-- basePath
|
|
135
|
-
├── bucket-1/ <-- bucket (directory)
|
|
136
|
-
│ ├── file1.pdf <-- object (file)
|
|
137
|
-
│ └── file2.jpg
|
|
138
|
-
└── user-uploads/
|
|
139
|
-
├── avatar.png
|
|
140
|
-
└── resume.pdf
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### In-Memory Storage
|
|
144
|
-
|
|
145
|
-
`MemoryStorageHelper` is a standalone, generic key-value store for caching or temporary state within a single process. It does **not** implement `IStorageHelper` and has no bucket or file operations.
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
import { MemoryStorageHelper } from '@venizia/ignis-helpers';
|
|
149
|
-
|
|
150
|
-
// Direct instantiation
|
|
151
|
-
const cache = new MemoryStorageHelper();
|
|
152
|
-
|
|
153
|
-
// With custom scope for logging
|
|
154
|
-
const cache = new MemoryStorageHelper({ scope: 'SessionCache' });
|
|
155
|
-
|
|
156
|
-
// With typed container using the factory method
|
|
157
|
-
const cache = MemoryStorageHelper.newInstance<{ counter: number; name: string }>();
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
#### Constructor Options
|
|
161
|
-
|
|
162
|
-
| Option | Type | Default | Description |
|
|
163
|
-
|--------|------|---------|-------------|
|
|
164
|
-
| `scope` | `string` | `'MemoryStorageHelper'` | Logger scope name. |
|
|
165
|
-
|
|
166
|
-
## Usage
|
|
167
|
-
|
|
168
|
-
`DiskHelper`, `MinioHelper`, and `BunS3Helper` implement the same `IStorageHelper` interface, making them interchangeable. All examples below apply to all three unless noted otherwise.
|
|
169
|
-
|
|
170
|
-
### Uploading Files
|
|
171
|
-
|
|
172
|
-
Pass an array of `IUploadFile` objects to `upload()`. The method validates all file names before writing, then uploads in parallel.
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
const results = await storage.upload({
|
|
176
|
-
bucket: 'my-bucket',
|
|
22
|
+
const [result] = await storage.upload({
|
|
23
|
+
bucket: 'uploads',
|
|
177
24
|
files: [
|
|
178
25
|
{
|
|
179
26
|
originalName: 'report.pdf',
|
|
180
27
|
mimetype: 'application/pdf',
|
|
181
28
|
buffer: fileBuffer,
|
|
182
29
|
size: fileBuffer.length,
|
|
183
|
-
encoding: '7bit',
|
|
184
30
|
},
|
|
185
31
|
],
|
|
186
32
|
});
|
|
187
33
|
|
|
188
|
-
console.log(
|
|
189
|
-
//
|
|
34
|
+
console.log(result);
|
|
35
|
+
// { bucketName: 'uploads', objectName: 'report.pdf', link: '/static-resources/uploads/report.pdf' }
|
|
190
36
|
```
|
|
191
37
|
|
|
192
|
-
|
|
38
|
+
`MinioHelper` and `BunS3Helper` accept the same `upload()` call against S3-compatible storage - swap the constructor, keep everything else unchanged.
|
|
193
39
|
|
|
194
|
-
|
|
40
|
+
## How it works
|
|
195
41
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
: `${timestamp}_${originalName}`;
|
|
205
|
-
},
|
|
206
|
-
normalizeLinkFn: ({ bucketName, normalizeName }) => {
|
|
207
|
-
return `/files/${bucketName}/${normalizeName}`;
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
```
|
|
42
|
+
- **`BaseStorageHelper` owns the shared logic.** It's an abstract class implementing `IStorageHelper` - name/path validation, MIME type detection, and the `upload()` orchestration itself (check the bucket exists, validate every file, write in parallel). Each backend only supplies two protected hooks: `defaultLinkPrefix` and `writeObject()`.
|
|
43
|
+
- **Everything else is per-backend.** `isBucketExists`, `getBuckets`, `createBucket`, `getFile`, `getStat`, `removeObject`, `listObjects`, and the rest of `IStorageHelper` are implemented independently per backend - a filesystem `stat()` and a MinIO `statObject()` share nothing beyond the return shape.
|
|
44
|
+
- **The three backends are interchangeable.** Write services against `IStorageHelper`, not a concrete class, and swap backends by construction only.
|
|
45
|
+
- **`MemoryStorageHelper` is unrelated.** A standalone generic key-value store for in-process caching, extending `BaseHelper` directly - no bucket or file concept.
|
|
46
|
+
- **Every write path is validated first.** `originalName` and `folderPath` run through `isValidName()`/`isValidPath()` before touching the filesystem or object store, rejecting path traversal (`../`), shell-injection characters, hidden files, and folder nesting beyond `maxFolderDepth` (default `2`). The same check re-runs on whatever a custom `normalizeNameFn` returns, so a traversal payload smuggled back from application code is rejected too.
|
|
47
|
+
- **Two backends stay optional.** `MinioHelper` and `BunS3Helper` live behind separate sub-path exports, so apps that only need `DiskHelper` or `MemoryStorageHelper` don't pull in the `minio` package or require the Bun runtime.
|
|
48
|
+
|
|
49
|
+
**Backends**
|
|
211
50
|
|
|
212
|
-
|
|
213
|
-
|
|
51
|
+
| Backend | Storage | Mechanism | Import |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `MinioHelper` | S3-compatible object storage | `minio` SDK | `@venizia/ignis-helpers/minio` |
|
|
54
|
+
| `BunS3Helper` | S3-compatible object storage | Bun's native `S3Client` (Bun runtime only) | `@venizia/ignis-helpers/bun-s3` |
|
|
55
|
+
| `DiskHelper` | Local filesystem, one directory per bucket | Node `fs`/`fs/promises` | `@venizia/ignis-helpers` |
|
|
56
|
+
| `MemoryStorageHelper` | In-process key-value cache | Plain object | `@venizia/ignis-helpers` |
|
|
214
57
|
|
|
215
|
-
|
|
58
|
+
## Common tasks
|
|
216
59
|
|
|
217
|
-
|
|
60
|
+
### Choose and construct a backend
|
|
218
61
|
|
|
219
62
|
```typescript
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
63
|
+
import { DiskHelper } from '@venizia/ignis-helpers';
|
|
64
|
+
import { MinioHelper } from '@venizia/ignis-helpers/minio';
|
|
65
|
+
|
|
66
|
+
const disk = new DiskHelper({ basePath: './app_data/storage' });
|
|
67
|
+
|
|
68
|
+
const minio = new MinioHelper({
|
|
69
|
+
endPoint: 'localhost',
|
|
70
|
+
port: 9000,
|
|
71
|
+
useSSL: false,
|
|
72
|
+
accessKey: 'minioadmin',
|
|
73
|
+
secretKey: 'minioadmin',
|
|
224
74
|
});
|
|
225
75
|
```
|
|
226
76
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
#### Upload with Folder Path
|
|
77
|
+
### Upload with a folder path
|
|
230
78
|
|
|
231
|
-
When `folderPath` is
|
|
79
|
+
When `folderPath` is set, the default normalization creates a subdirectory-based object name.
|
|
232
80
|
|
|
233
81
|
```typescript
|
|
234
|
-
const
|
|
235
|
-
bucket: '
|
|
82
|
+
const [result] = await storage.upload({
|
|
83
|
+
bucket: 'uploads',
|
|
236
84
|
files: [
|
|
237
85
|
{
|
|
238
86
|
originalName: 'avatar.png',
|
|
@@ -246,410 +94,66 @@ const results = await storage.upload({
|
|
|
246
94
|
// objectName: 'users/avatar.png'
|
|
247
95
|
```
|
|
248
96
|
|
|
249
|
-
|
|
250
|
-
> DiskHelper uses `/static-resources/` as the default link prefix, while MinioHelper and BunS3Helper use `/static-assets/`. Provide a `normalizeLinkFn` if you need consistent links across storage backends.
|
|
251
|
-
|
|
252
|
-
### Downloading Files
|
|
97
|
+
### Download a file
|
|
253
98
|
|
|
254
|
-
|
|
99
|
+
`getFile()` returns a Node.js `Readable` on every backend, so piping to a response or a write stream works identically.
|
|
255
100
|
|
|
256
101
|
```typescript
|
|
257
|
-
const fileStream = await storage.getFile({
|
|
258
|
-
bucket: 'my-bucket',
|
|
259
|
-
name: 'report.pdf',
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Pipe to an HTTP response
|
|
102
|
+
const fileStream = await storage.getFile({ bucket: 'uploads', name: 'report.pdf' });
|
|
263
103
|
fileStream.pipe(response);
|
|
264
|
-
|
|
265
|
-
// Or write to disk
|
|
266
|
-
import fs from 'node:fs';
|
|
267
|
-
const writeStream = fs.createWriteStream('./downloads/report.pdf');
|
|
268
|
-
fileStream.pipe(writeStream);
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
#### MinIO-Specific Options
|
|
272
|
-
|
|
273
|
-
MinioHelper supports additional options for server-side encryption and versioning:
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
const fileStream = await minioStorage.getFile({
|
|
277
|
-
bucket: 'my-bucket',
|
|
278
|
-
name: 'report.pdf',
|
|
279
|
-
options: {
|
|
280
|
-
versionId: 'specific-version-id',
|
|
281
|
-
SSECustomerAlgorithm: 'AES256',
|
|
282
|
-
SSECustomerKey: 'encryption-key',
|
|
283
|
-
SSECustomerKeyMD5: 'key-md5-hash',
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Getting File Metadata
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
const stat = await storage.getStat({
|
|
292
|
-
bucket: 'my-bucket',
|
|
293
|
-
name: 'report.pdf',
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
console.log(stat);
|
|
297
|
-
// {
|
|
298
|
-
// size: 204800,
|
|
299
|
-
// lastModified: 2025-01-15T10:30:00.000Z,
|
|
300
|
-
// metadata: { mimetype: 'application/pdf' },
|
|
301
|
-
// etag: 'abc123', // MinioHelper and BunS3Helper only
|
|
302
|
-
// versionId: 'v1', // MinioHelper only (if versioning enabled)
|
|
303
|
-
// }
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
> [!NOTE]
|
|
307
|
-
> DiskHelper populates `metadata.mimetype` using the `getMimeType()` extension-based lookup. It does not return `etag` or `versionId`. MinioHelper returns full metadata from the MinIO server including the original upload metadata, `etag`, and `versionId`. BunS3Helper returns `metadata` with `contentType` and `mimetype` from the S3 stat response, plus `etag` and `lastModified`.
|
|
308
|
-
|
|
309
|
-
### Listing Files
|
|
310
|
-
|
|
311
|
-
```typescript
|
|
312
|
-
// List all objects in a bucket
|
|
313
|
-
const objects = await storage.listObjects({ bucket: 'my-bucket' });
|
|
314
|
-
|
|
315
|
-
// List with prefix filter
|
|
316
|
-
const docs = await storage.listObjects({
|
|
317
|
-
bucket: 'my-bucket',
|
|
318
|
-
prefix: 'documents/',
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
// Recursive listing (includes files in subdirectories)
|
|
322
|
-
const allFiles = await storage.listObjects({
|
|
323
|
-
bucket: 'my-bucket',
|
|
324
|
-
useRecursive: true,
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Limit the number of results
|
|
328
|
-
const firstTen = await storage.listObjects({
|
|
329
|
-
bucket: 'my-bucket',
|
|
330
|
-
maxKeys: 10,
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
console.log(allFiles);
|
|
334
|
-
// [
|
|
335
|
-
// { name: 'report.pdf', size: 204800, lastModified: Date, etag: '...' },
|
|
336
|
-
// { name: 'avatar.png', size: 51200, lastModified: Date },
|
|
337
|
-
// ]
|
|
338
104
|
```
|
|
339
105
|
|
|
340
|
-
###
|
|
106
|
+
### List and delete objects
|
|
341
107
|
|
|
342
108
|
```typescript
|
|
343
|
-
|
|
344
|
-
await storage.removeObject({ bucket: 'my-bucket', name: 'old-file.pdf' });
|
|
109
|
+
const objects = await storage.listObjects({ bucket: 'uploads', useRecursive: true });
|
|
345
110
|
|
|
346
|
-
// Delete multiple objects
|
|
347
111
|
await storage.removeObjects({
|
|
348
|
-
bucket: '
|
|
349
|
-
names:
|
|
112
|
+
bucket: 'uploads',
|
|
113
|
+
names: objects.map(object => object.name!),
|
|
350
114
|
});
|
|
351
115
|
```
|
|
352
116
|
|
|
353
|
-
|
|
354
|
-
> DiskHelper's `removeObject()` throws if the file does not exist. DiskHelper's `removeObjects()` processes deletions sequentially. MinioHelper's `removeObjects()` delegates to the minio SDK's batch removal. BunS3Helper's `removeObjects()` deletes in parallel via `Promise.all()`.
|
|
355
|
-
|
|
356
|
-
### Bucket Operations
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
// Check if a bucket exists
|
|
360
|
-
const exists = await storage.isBucketExists({ name: 'my-bucket' });
|
|
361
|
-
|
|
362
|
-
// Create a new bucket
|
|
363
|
-
const bucket = await storage.createBucket({ name: 'my-bucket' });
|
|
364
|
-
// Returns: { name: 'my-bucket', creationDate: Date }
|
|
365
|
-
|
|
366
|
-
// List all buckets
|
|
367
|
-
const buckets = await storage.getBuckets();
|
|
368
|
-
// Returns: [{ name: 'bucket-1', creationDate: Date }, ...]
|
|
369
|
-
|
|
370
|
-
// Get a specific bucket
|
|
371
|
-
const bucket = await storage.getBucket({ name: 'my-bucket' });
|
|
372
|
-
// Returns: { name: 'my-bucket', creationDate: Date } | null
|
|
373
|
-
|
|
374
|
-
// Remove a bucket
|
|
375
|
-
const removed = await storage.removeBucket({ name: 'my-bucket' });
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
> [!IMPORTANT]
|
|
379
|
-
> DiskHelper's `removeBucket()` requires the bucket directory to be empty. It throws if files remain. Remove all objects first, then remove the bucket.
|
|
380
|
-
|
|
381
|
-
### In-Memory Storage Operations
|
|
382
|
-
|
|
383
|
-
`MemoryStorageHelper` provides a simple key-value API, separate from the bucket-based `IStorageHelper` interface:
|
|
384
|
-
|
|
385
|
-
```typescript
|
|
386
|
-
const cache = new MemoryStorageHelper();
|
|
387
|
-
|
|
388
|
-
// Store a value
|
|
389
|
-
cache.set('user:123', { name: 'Alice', role: 'admin' });
|
|
390
|
-
|
|
391
|
-
// Retrieve a typed value
|
|
392
|
-
const user = cache.get<{ name: string; role: string }>('user:123');
|
|
393
|
-
|
|
394
|
-
// Check if a key exists
|
|
395
|
-
cache.isBound('user:123'); // true
|
|
396
|
-
|
|
397
|
-
// Get all keys
|
|
398
|
-
cache.keys(); // ['user:123']
|
|
399
|
-
|
|
400
|
-
// Access the underlying container
|
|
401
|
-
cache.getContainer(); // { 'user:123': { name: 'Alice', role: 'admin' } }
|
|
402
|
-
|
|
403
|
-
// Clear all stored data
|
|
404
|
-
cache.clear();
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Name Validation
|
|
408
|
-
|
|
409
|
-
Storage helpers use two validation methods depending on context:
|
|
410
|
-
|
|
411
|
-
- **`isValidName(name)`** - validates a single path segment (bucket names, raw file names). Rejects names that contain `/`, `\`, or `..`.
|
|
412
|
-
- **`isValidPath(pathStr)`** - validates a full object path that may include folder segments (e.g., `folder/file.pdf`). Splits on `/` and validates each segment with `isValidName`. Also enforces a max folder depth (default: 2).
|
|
413
|
-
|
|
414
|
-
Bucket operations (create, remove) validate the bucket name with `isValidName()`. `upload()` validates each file's `originalName` with `isValidName()` and, when provided, the file's `folderPath` with `isValidPath()` so that folder structures like `2025/uploads` are accepted. Read and delete operations (`getFile`, `getStat`, `removeObject`, `listObjects`) do not re-validate names.
|
|
415
|
-
|
|
416
|
-
The following single-segment inputs are rejected by `isValidName()`:
|
|
417
|
-
|
|
418
|
-
| Rule | Example | Reason |
|
|
419
|
-
|------|---------|--------|
|
|
420
|
-
| Contains `..`, `/`, or `\` | `../etc/passwd` | Path traversal |
|
|
421
|
-
| Starts with `.` | `.hidden` | Hidden file |
|
|
422
|
-
| Contains `;`, `\|`, `&`, `$`, `` ` ``, `<`, `>`, `{`, `}`, `[`, `]`, `!`, `#` | `file;rm -rf` | Shell injection |
|
|
423
|
-
| Contains `\n`, `\r`, or `\0` | `file\nname` | Header injection |
|
|
424
|
-
| Longer than 255 characters | (very long string) | DoS prevention |
|
|
425
|
-
| Empty or whitespace-only | `""`, `" "` | Invalid input |
|
|
426
|
-
|
|
427
|
-
```typescript
|
|
428
|
-
// Single-segment name validation (buckets, raw file names)
|
|
429
|
-
storage.isValidName('my-file.pdf'); // true
|
|
430
|
-
storage.isValidName('../etc/passwd'); // false - contains path separators
|
|
431
|
-
storage.isValidName('.hidden'); // false - starts with dot
|
|
432
|
-
|
|
433
|
-
// Multi-segment path validation (object names with folder structure)
|
|
434
|
-
storage.isValidPath('folder/file.pdf'); // true
|
|
435
|
-
storage.isValidPath('../etc/passwd'); // false - path traversal
|
|
436
|
-
storage.isValidPath('a/b/c/d/file.pdf'); // false - exceeds max depth (2)
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
### MIME Type Detection
|
|
440
|
-
|
|
441
|
-
`getMimeType()` determines the MIME type from a filename's extension:
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
storage.getMimeType('photo.jpg'); // 'image/jpeg'
|
|
445
|
-
storage.getMimeType('data.csv'); // 'text/csv'
|
|
446
|
-
storage.getMimeType('unknown.xyz'); // 'application/octet-stream'
|
|
447
|
-
```
|
|
117
|
+
### Write storage-agnostic services
|
|
448
118
|
|
|
449
|
-
`
|
|
119
|
+
Depend on `IStorageHelper`, not a concrete class, so backends swap without touching service code.
|
|
450
120
|
|
|
451
121
|
```typescript
|
|
452
|
-
|
|
453
|
-
storage.getFileType({ mimeType: 'video/mp4' }); // 'video'
|
|
454
|
-
storage.getFileType({ mimeType: 'text/plain' }); // 'text'
|
|
455
|
-
storage.getFileType({ mimeType: 'application/pdf' }); // 'unknown'
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
### Common Patterns
|
|
459
|
-
|
|
460
|
-
#### Storage Abstraction
|
|
122
|
+
import type { IStorageHelper, IUploadFile } from '@venizia/ignis-helpers';
|
|
461
123
|
|
|
462
|
-
Use `IStorageHelper` to write storage-agnostic code:
|
|
463
|
-
|
|
464
|
-
```typescript
|
|
465
124
|
class FileService {
|
|
466
125
|
constructor(private storage: IStorageHelper) {}
|
|
467
126
|
|
|
468
|
-
|
|
127
|
+
uploadFile(bucket: string, file: IUploadFile) {
|
|
469
128
|
return this.storage.upload({ bucket, files: [file] });
|
|
470
129
|
}
|
|
471
130
|
}
|
|
472
|
-
|
|
473
|
-
// Swap backends without changing service code
|
|
474
|
-
const devService = new FileService(new DiskHelper({ basePath: './files' }));
|
|
475
|
-
const prodService = new FileService(new MinioHelper({ /* ... */ }));
|
|
476
|
-
const bunService = new FileService(new BunS3Helper({ /* ... */ }));
|
|
477
131
|
```
|
|
478
132
|
|
|
479
|
-
|
|
133
|
+
### Cache values in-memory
|
|
480
134
|
|
|
481
|
-
|
|
482
|
-
import { applicationEnvironment } from '@venizia/ignis-helpers';
|
|
483
|
-
|
|
484
|
-
const createStorage = (): IStorageHelper => {
|
|
485
|
-
if (applicationEnvironment.get('STORAGE_TYPE') === 'minio') {
|
|
486
|
-
return new MinioHelper({
|
|
487
|
-
endPoint: applicationEnvironment.get('MINIO_HOST'),
|
|
488
|
-
port: Number(applicationEnvironment.get('MINIO_PORT')),
|
|
489
|
-
accessKey: applicationEnvironment.get('MINIO_ACCESS_KEY'),
|
|
490
|
-
secretKey: applicationEnvironment.get('MINIO_SECRET_KEY'),
|
|
491
|
-
useSSL: applicationEnvironment.get('MINIO_USE_SSL') === 'true',
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
return new DiskHelper({
|
|
496
|
-
basePath: applicationEnvironment.get('DISK_STORAGE_PATH') || './storage',
|
|
497
|
-
});
|
|
498
|
-
};
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
## Troubleshooting
|
|
502
|
-
|
|
503
|
-
### "[createBucket] Invalid name to create bucket!"
|
|
504
|
-
|
|
505
|
-
**Cause:** The bucket name failed `isValidName()` validation. The name may contain path traversal characters, start with a dot, contain shell-special characters, or exceed 255 characters.
|
|
506
|
-
|
|
507
|
-
**Fix:** Use a simple alphanumeric bucket name:
|
|
135
|
+
`MemoryStorageHelper` is a separate, generic key-value store - not a bucket-based backend.
|
|
508
136
|
|
|
509
137
|
```typescript
|
|
510
|
-
|
|
511
|
-
await storage.createBucket({ name: '../my-bucket' });
|
|
512
|
-
await storage.createBucket({ name: '.hidden-bucket' });
|
|
513
|
-
|
|
514
|
-
// Correct
|
|
515
|
-
await storage.createBucket({ name: 'my-bucket' });
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
### "[removeBucket] Invalid name to remove bucket!"
|
|
519
|
-
|
|
520
|
-
**Cause:** Same as above -- the bucket name failed validation.
|
|
521
|
-
|
|
522
|
-
**Fix:** Provide a valid bucket name that passes `isValidName()`.
|
|
523
|
-
|
|
524
|
-
### "[createBucket] Bucket already exists | name: {name}"
|
|
525
|
-
|
|
526
|
-
**Cause:** DiskHelper throws when calling `createBucket()` on an existing bucket directory.
|
|
527
|
-
|
|
528
|
-
**Fix:** Check existence first:
|
|
529
|
-
|
|
530
|
-
```typescript
|
|
531
|
-
const exists = await storage.isBucketExists({ name: 'my-bucket' });
|
|
532
|
-
if (!exists) {
|
|
533
|
-
await storage.createBucket({ name: 'my-bucket' });
|
|
534
|
-
}
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
### "[removeBucket] Bucket does not exist | name: {name}"
|
|
538
|
-
|
|
539
|
-
**Cause:** DiskHelper throws when attempting to remove a bucket directory that does not exist.
|
|
540
|
-
|
|
541
|
-
**Fix:** Check existence before removal:
|
|
542
|
-
|
|
543
|
-
```typescript
|
|
544
|
-
const exists = await storage.isBucketExists({ name: 'my-bucket' });
|
|
545
|
-
if (exists) {
|
|
546
|
-
await storage.removeBucket({ name: 'my-bucket' });
|
|
547
|
-
}
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
### "[removeBucket] Bucket is not empty | name: {name}"
|
|
551
|
-
|
|
552
|
-
**Cause:** DiskHelper's `removeBucket()` requires the bucket directory to be empty before removal.
|
|
553
|
-
|
|
554
|
-
**Fix:** Remove all objects first:
|
|
555
|
-
|
|
556
|
-
```typescript
|
|
557
|
-
const objects = await storage.listObjects({ bucket: 'my-bucket', useRecursive: true });
|
|
558
|
-
if (objects.length > 0) {
|
|
559
|
-
await storage.removeObjects({
|
|
560
|
-
bucket: 'my-bucket',
|
|
561
|
-
names: objects.map(o => o.name!),
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
await storage.removeBucket({ name: 'my-bucket' });
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
### "[upload] Bucket does not exist | name: {bucket}"
|
|
568
|
-
|
|
569
|
-
**Cause:** The target bucket does not exist. DiskHelper, MinioHelper, and BunS3Helper all validate bucket existence before uploading.
|
|
570
|
-
|
|
571
|
-
**Fix:** Create the bucket before uploading:
|
|
572
|
-
|
|
573
|
-
```typescript
|
|
574
|
-
const exists = await storage.isBucketExists({ name: 'uploads' });
|
|
575
|
-
if (!exists) {
|
|
576
|
-
await storage.createBucket({ name: 'uploads' });
|
|
577
|
-
}
|
|
578
|
-
await storage.upload({ bucket: 'uploads', files: [...] });
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
### "[upload] Invalid original file name"
|
|
582
|
-
|
|
583
|
-
**Cause:** A file's `originalName` failed `isValidName()` validation.
|
|
584
|
-
|
|
585
|
-
**Fix:** Sanitize file names before uploading, or use `normalizeNameFn` to control the stored name:
|
|
586
|
-
|
|
587
|
-
```typescript
|
|
588
|
-
await storage.upload({
|
|
589
|
-
bucket: 'my-bucket',
|
|
590
|
-
files: files,
|
|
591
|
-
normalizeNameFn: ({ originalName }) => {
|
|
592
|
-
return originalName.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
593
|
-
},
|
|
594
|
-
});
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### "[upload] Invalid file size"
|
|
598
|
-
|
|
599
|
-
**Cause:** A file's `size` property is `undefined`, `null`, or negative. A zero-byte file is a legal upload - it is not what triggers this error.
|
|
600
|
-
|
|
601
|
-
**Fix:** Ensure every file in the upload array has a valid `size` value:
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
const file: IUploadFile = {
|
|
605
|
-
originalName: 'doc.pdf',
|
|
606
|
-
mimetype: 'application/pdf',
|
|
607
|
-
buffer: fileBuffer,
|
|
608
|
-
size: fileBuffer.length, // Must be a number >= 0
|
|
609
|
-
};
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
### "[upload] Invalid normalized object name | name: {name}"
|
|
613
|
-
|
|
614
|
-
**Cause:** A custom `normalizeNameFn` returned a value that fails `isValidPath()` - typically a path-traversal payload (e.g. `../../../etc/cron.d/pwn`) or a name exceeding `maxFolderDepth`.
|
|
615
|
-
|
|
616
|
-
**Fix:** Ensure `normalizeNameFn` returns a plain relative name/path with no `..` segments, no leading `/`, and no more folder segments than `maxFolderDepth` (default `2`) allows.
|
|
617
|
-
|
|
618
|
-
### "[getFile] File not found | bucket: {bucket} | name: {name}"
|
|
619
|
-
|
|
620
|
-
**Cause:** DiskHelper throws when the requested file does not exist on the filesystem.
|
|
621
|
-
|
|
622
|
-
**Fix:** Verify the file exists before attempting to retrieve it, or handle the error:
|
|
138
|
+
import { MemoryStorageHelper } from '@venizia/ignis-helpers';
|
|
623
139
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
} catch (error) {
|
|
628
|
-
// File not found -- handle gracefully
|
|
629
|
-
}
|
|
140
|
+
const cache = MemoryStorageHelper.newInstance<{ counter: number }>();
|
|
141
|
+
cache.set('counter', 1);
|
|
142
|
+
cache.get<number>('counter'); // 1
|
|
630
143
|
```
|
|
631
144
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
**Cause:** Network or configuration issue between the application and the MinIO server.
|
|
635
|
-
|
|
636
|
-
**Checklist:**
|
|
637
|
-
- The MinIO server is running and reachable at the configured `endPoint` and `port`
|
|
638
|
-
- `useSSL` matches the server's TLS configuration
|
|
639
|
-
- `accessKey` and `secretKey` are correct
|
|
640
|
-
- Network and firewall rules allow the connection
|
|
641
|
-
|
|
642
|
-
## See Also
|
|
145
|
+
## See also
|
|
643
146
|
|
|
644
|
-
-
|
|
645
|
-
|
|
646
|
-
|
|
147
|
+
- [Full reference](./api) - every class, method signature, validation rule, and error message
|
|
148
|
+
- [Static Asset Component](/extensions/components/static-asset/) - serving stored files over HTTP
|
|
149
|
+
- [Request Utilities](/references/utilities/request) - `parseMultipartBody` for file uploads
|
|
150
|
+
- [Helpers Index](../index) - all available helpers
|
|
151
|
+
- [Queue Helper](../queue/) - message queue processing
|
|
647
152
|
|
|
648
|
-
|
|
649
|
-
- [Static Asset Component](/extensions/components/static-asset/) -- Serving stored files via HTTP
|
|
650
|
-
- [Request Utilities](/references/utilities/request) -- `parseMultipartBody` for file uploads
|
|
651
|
-
- [API Reference](./api) -- Full method signatures and types
|
|
153
|
+
**Files:**
|
|
652
154
|
|
|
653
|
-
-
|
|
654
|
-
|
|
655
|
-
|
|
155
|
+
- [`packages/helpers/src/modules/storage/base.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/storage/base.ts) - `BaseStorageHelper`
|
|
156
|
+
- [`packages/helpers/src/modules/storage/minio/helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/storage/minio/helper.ts) - `MinioHelper`
|
|
157
|
+
- [`packages/helpers/src/modules/storage/bun-s3/helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/storage/bun-s3/helper.ts) - `BunS3Helper`
|
|
158
|
+
- [`packages/helpers/src/modules/storage/disk/helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/storage/disk/helper.ts) - `DiskHelper`
|
|
159
|
+
- [`packages/helpers/src/modules/storage/in-memory/helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/storage/in-memory/helper.ts) - `MemoryStorageHelper`
|