@venturialstd/file-system 0.0.1 → 0.0.2
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 +106 -66
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,57 +1,91 @@
|
|
|
1
1
|
# @venturialstd/file-system
|
|
2
2
|
|
|
3
|
-
Provider-agnostic file
|
|
3
|
+
Provider-agnostic file storage and tree API for Venturial backends. Ships with **Backblaze B2**; designed so additional providers (e.g. AWS S3) can be added without changing consumer code.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
- [Features](#features)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Configuration](#configuration)
|
|
12
|
+
- [Quick start](#quick-start)
|
|
13
|
+
- [API](#api)
|
|
14
|
+
- [Adding a provider](#adding-a-provider)
|
|
15
|
+
- [License](#license)
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
## Features
|
|
6
20
|
|
|
7
|
-
- **Unified API
|
|
8
|
-
- **File and folder
|
|
9
|
-
- **Tree operations
|
|
10
|
-
- **
|
|
11
|
-
- **Domain errors
|
|
21
|
+
- **Unified API** — Upload, download, delete, list, exists/head; optional signed URLs
|
|
22
|
+
- **File and folder model** — TypeORM entities with parent-child relationships; tree stored in your DB
|
|
23
|
+
- **Tree operations** — Create/read folders and files; get full tree or subtree; list children
|
|
24
|
+
- **Settings-driven** — Provider and bucket come from Settings; credentials come from the Backblaze package only
|
|
25
|
+
- **Domain errors** — Provider errors mapped to `FileSystemNotFoundError`, `FileSystemPermissionDeniedError`, `FileSystemRateLimitError`, `FileSystemNotSupportedError`
|
|
26
|
+
- **Permanent delete** — Backblaze: delete uses `exists` → `versionId` for permanent deletion when supported
|
|
27
|
+
|
|
28
|
+
---
|
|
12
29
|
|
|
13
30
|
## Installation
|
|
14
31
|
|
|
32
|
+
**npm (standalone):**
|
|
33
|
+
|
|
15
34
|
```bash
|
|
16
|
-
npm install @venturialstd/file-system @venturialstd/backblaze
|
|
35
|
+
npm install @venturialstd/file-system @venturialstd/backblaze @venturialstd/core
|
|
17
36
|
```
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
**Monorepo** — in your app’s `package.json`:
|
|
20
39
|
|
|
21
40
|
```json
|
|
22
|
-
|
|
23
|
-
"
|
|
41
|
+
{
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@venturialstd/file-system": "file:src/file-system",
|
|
44
|
+
"@venturialstd/backblaze": "file:src/backblaze",
|
|
45
|
+
"@venturialstd/core": "^2.0.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
24
48
|
```
|
|
25
49
|
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
All file-system runtime config is read from **Settings** (no arguments to `FileSystemModule.forRoot()`).
|
|
55
|
+
|
|
56
|
+
| Purpose | Setting key | Scope / section | Example |
|
|
57
|
+
|----------------|-------------------------------------|----------------------|-----------|
|
|
58
|
+
| Provider | `FILE_SYSTEM_SETTING_KEYS.GENERAL_PROVIDER` | FILE-SYSTEM / GENERAL / PROVIDER | `backblaze` |
|
|
59
|
+
| Bucket name | `FILE_SYSTEM_SETTING_KEYS.BACKBLAZE_BUCKET_NAME` | FILE-SYSTEM / BACKBLAZE / BUCKET_NAME | `my-bucket` |
|
|
60
|
+
|
|
61
|
+
- The package exports **`FILE_SYSTEM_SETTINGS`** (and **`SETTINGS`**) so `@venturialstd/core` can discover and register these keys.
|
|
62
|
+
- **Credentials and region** are not configured in file-system; they are taken only from the Backblaze package configuration.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
26
66
|
## Quick start
|
|
27
67
|
|
|
28
|
-
|
|
68
|
+
**1. Register entities and module**
|
|
29
69
|
|
|
30
|
-
|
|
70
|
+
Ensure TypeORM loads the file-system entities (e.g. via `SharedModule` or your entity glob). Then import the module:
|
|
31
71
|
|
|
32
72
|
```ts
|
|
33
|
-
import {
|
|
34
|
-
import { FileSystemFile, FileSystemFolder } from '@venturialstd/file-system';
|
|
73
|
+
import { FileSystemModule } from '@venturialstd/file-system';
|
|
35
74
|
|
|
36
75
|
@Module({
|
|
37
76
|
imports: [
|
|
38
|
-
|
|
39
|
-
entities: [FileSystemFile, FileSystemFolder, /* your other entities */],
|
|
40
|
-
}),
|
|
77
|
+
// ... TypeORM with FileSystemFile, FileSystemFolder
|
|
41
78
|
FileSystemModule.forRoot(),
|
|
42
79
|
],
|
|
43
80
|
})
|
|
44
81
|
export class AppModule {}
|
|
45
82
|
```
|
|
46
83
|
|
|
47
|
-
**
|
|
48
|
-
|
|
49
|
-
- **Provider:** `FILE-SYSTEM` / `GENERAL` / `PROVIDER` (e.g. `backblaze`)
|
|
50
|
-
- **Bucket name:** `FILE-SYSTEM` / `BACKBLAZE` / `BUCKET_NAME`
|
|
84
|
+
**2. Configure Settings**
|
|
51
85
|
|
|
52
|
-
|
|
86
|
+
Create or seed settings for the keys above (provider and bucket). If you use a settings admin UI, add entries for FILE-SYSTEM / GENERAL / PROVIDER and FILE-SYSTEM / BACKBLAZE / BUCKET_NAME.
|
|
53
87
|
|
|
54
|
-
|
|
88
|
+
**3. Use the service**
|
|
55
89
|
|
|
56
90
|
```ts
|
|
57
91
|
import { FileSystemService } from '@venturialstd/file-system';
|
|
@@ -61,66 +95,72 @@ export class MyService {
|
|
|
61
95
|
constructor(private readonly fileSystem: FileSystemService) {}
|
|
62
96
|
|
|
63
97
|
async example() {
|
|
64
|
-
// Blob
|
|
65
|
-
await this.fileSystem.upload('path/
|
|
66
|
-
const data = await this.fileSystem.download('path/
|
|
67
|
-
const meta = await this.fileSystem.exists('path/
|
|
68
|
-
const list = await this.fileSystem.list('path/
|
|
69
|
-
|
|
70
|
-
// Tree
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const file = await this.fileSystem.uploadAndCreateFile(
|
|
98
|
+
// Blob
|
|
99
|
+
await this.fileSystem.upload('path/file.pdf', buffer, { contentType: 'application/pdf' });
|
|
100
|
+
const data = await this.fileSystem.download('path/file.pdf');
|
|
101
|
+
const meta = await this.fileSystem.exists('path/file.pdf');
|
|
102
|
+
const list = await this.fileSystem.list('path/', { maxKeys: 100 });
|
|
103
|
+
|
|
104
|
+
// Tree
|
|
105
|
+
const root = await this.fileSystem.createFolder('Documents', null);
|
|
106
|
+
const sub = await this.fileSystem.createFolder('Projects', root.id);
|
|
107
|
+
const file = await this.fileSystem.uploadAndCreateFile(sub.id, 'readme.txt', Buffer.from('Hello'));
|
|
74
108
|
const tree = await this.fileSystem.getTree();
|
|
75
|
-
const children = await this.fileSystem.getChildren(
|
|
109
|
+
const children = await this.fileSystem.getChildren(sub.id);
|
|
76
110
|
}
|
|
77
111
|
}
|
|
78
112
|
```
|
|
79
113
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
All providers implement `IFileSystemProvider`:
|
|
83
|
-
|
|
84
|
-
- `upload(key, body, options?)` – upload buffer/string to key
|
|
85
|
-
- `download(key)` – download as `ArrayBuffer`
|
|
86
|
-
- `delete(key)` – delete object
|
|
87
|
-
- `deleteMany(keys?)` – optional bulk delete
|
|
88
|
-
- `list(prefix, options?)` – list with pagination
|
|
89
|
-
- `exists(key)` – head object, returns metadata or throws
|
|
90
|
-
- `getSignedDownloadUrl(key, expiresInSeconds?)` – optional
|
|
91
|
-
- `getSignedUploadUrl(key, contentType?, expiresInSeconds?)` – optional
|
|
114
|
+
---
|
|
92
115
|
|
|
93
|
-
|
|
116
|
+
## API
|
|
94
117
|
|
|
95
|
-
|
|
118
|
+
### FileSystemService (main entry)
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
| Method | Description |
|
|
121
|
+
|--------|-------------|
|
|
122
|
+
| `upload(key, body, options?)` | Upload buffer/string to key |
|
|
123
|
+
| `download(key)` | Download as `ArrayBuffer` |
|
|
124
|
+
| `deleteObject(key, options?)` | Delete object; `options.versionId` for permanent delete (Backblaze) |
|
|
125
|
+
| `list(prefix, options?)` | List objects with pagination |
|
|
126
|
+
| `exists(key)` | Head object; returns metadata (includes `versionId` when available) |
|
|
127
|
+
| `createFolder(name, parentId)` | Create folder; `parentId === null` for root |
|
|
128
|
+
| `getFolder(id)`, `getFile(id)` | Load folder or file entity |
|
|
129
|
+
| `getChildren(folderId)` | Direct children (folders + files); `folderId === null` for root |
|
|
130
|
+
| `getTree(rootFolderId?)` | Full tree or subtree |
|
|
131
|
+
| `uploadAndCreateFile(folderId, fileName, body, options?)` | Upload blob and create file record in tree |
|
|
132
|
+
| `deleteFile(id)`, `deleteFolder(id)` | Delete file/folder and blob(s); uses `exists` + `versionId` for Backblaze |
|
|
100
133
|
|
|
101
|
-
|
|
134
|
+
### Provider contract (IFileSystemProvider)
|
|
102
135
|
|
|
103
|
-
|
|
136
|
+
Implement this interface to add a new storage backend:
|
|
104
137
|
|
|
105
|
-
|
|
138
|
+
| Method | Required | Description |
|
|
139
|
+
|--------|----------|-------------|
|
|
140
|
+
| `upload(key, body, options?)` | ✓ | Upload to key |
|
|
141
|
+
| `download(key)` | ✓ | Return `ArrayBuffer` |
|
|
142
|
+
| `delete(key, options?)` | ✓ | Delete object; `options.versionId` for permanent delete |
|
|
143
|
+
| `list(prefix, options?)` | ✓ | List with pagination |
|
|
144
|
+
| `exists(key)` | ✓ | Head; return metadata (e.g. `versionId`) |
|
|
145
|
+
| `deleteMany(keys?)` | optional | Bulk delete |
|
|
146
|
+
| `getSignedDownloadUrl(key, expiresInSeconds?)` | optional | Throw `FileSystemNotSupportedError` if unsupported |
|
|
147
|
+
| `getSignedUploadUrl(key, contentType?, expiresInSeconds?)` | optional | Same |
|
|
106
148
|
|
|
107
|
-
|
|
108
|
-
|-------------|-------------------------|-------------|
|
|
109
|
-
| `FILE_SYSTEM_SETTING_KEYS.GENERAL_PROVIDER` | FILE-SYSTEM / GENERAL / PROVIDER | Storage provider (e.g. `backblaze`) |
|
|
110
|
-
| `FILE_SYSTEM_SETTING_KEYS.BACKBLAZE_BUCKET_NAME` | FILE-SYSTEM / BACKBLAZE / BUCKET_NAME | B2 bucket name for file-system operations |
|
|
149
|
+
### File and folder model
|
|
111
150
|
|
|
112
|
-
|
|
151
|
+
- **Entities:** `FileSystemFile`, `FileSystemFolder` (TypeORM). Folders use a closure-table tree; files have optional `folderId`.
|
|
152
|
+
- **Tree:** Stored in your database; create/update/delete via the service keep it in sync.
|
|
153
|
+
- **Delete:** For Backblaze, `deleteFile` / `deleteFolder` call `exists` to get `versionId`, then `delete` with that id for permanent deletion.
|
|
113
154
|
|
|
114
|
-
|
|
155
|
+
---
|
|
115
156
|
|
|
116
|
-
|
|
117
|
-
- **Persistence**: Stored in your database; register entities with TypeORM as above. On create/update/delete via the API, the tree is kept in sync.
|
|
118
|
-
- **Tree API**: `getTree(rootFolderId?)`, `getChildren(folderId)`, `getFolder(id)`, `getFile(id)`, `createFolder`, `moveFile`, `moveFolder`, `deleteFile`, `deleteFolder`, `uploadAndCreateFile`.
|
|
157
|
+
## Adding a provider
|
|
119
158
|
|
|
120
|
-
|
|
159
|
+
1. Implement **`IFileSystemProvider`** in a new class (e.g. `S3FileSystemProvider`).
|
|
160
|
+
2. In **`FileSystemModule.forRoot()`**, support the new provider in config (e.g. Settings or options) and register the provider (factory + token).
|
|
161
|
+
3. No changes in code that uses **`FileSystemService`**; only configuration switches the provider.
|
|
121
162
|
|
|
122
|
-
|
|
123
|
-
- Others (GCS, Azure Blob) can be added by implementing the contract and registering in the module.
|
|
163
|
+
---
|
|
124
164
|
|
|
125
165
|
## License
|
|
126
166
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venturialstd/file-system",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Provider-agnostic file system module (Backblaze, extensible to AWS S3) with file/folder tree persistence",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
"@types/uuid": "^10.0.0",
|
|
33
33
|
"typescript": "^5.7.0"
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|