@bejibun/storage 0.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/CHANGELOG.md +44 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/builders/StorageBuilder.d.ts +24 -0
- package/builders/StorageBuilder.js +131 -0
- package/builders/storage/StorageLocalBuilder.d.ts +18 -0
- package/builders/storage/StorageLocalBuilder.js +92 -0
- package/builders/storage/StorageS3Builder.d.ts +18 -0
- package/builders/storage/StorageS3Builder.js +103 -0
- package/config/storage.d.ts +2 -0
- package/config/storage.js +26 -0
- package/configure.d.ts +1 -0
- package/configure.js +14 -0
- package/enums/StorageDiskDriverEnum.d.ts +5 -0
- package/enums/StorageDiskDriverEnum.js +6 -0
- package/enums/index.d.ts +1 -0
- package/enums/index.js +1 -0
- package/exceptions/StorageException.d.ts +4 -0
- package/exceptions/StorageException.js +14 -0
- package/exceptions/index.d.ts +1 -0
- package/exceptions/index.js +1 -0
- package/facades/Storage.d.ts +18 -0
- package/facades/Storage.js +42 -0
- package/facades/index.d.ts +1 -0
- package/facades/index.js +1 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +43 -0
- package/tsconfig.json +18 -0
- package/types/index.d.ts +1 -0
- package/types/storage.d.ts +138 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## [v0.1.0](https://github.com/Bejibun-Framework/bejibun-storage/compare/v0.1.0...v0.1.0) - 2026-08-03
|
|
7
|
+
|
|
8
|
+
### 🩹 Fixes
|
|
9
|
+
|
|
10
|
+
### 📖 Changes
|
|
11
|
+
Initial release of `@bejibun/storage` -- a filesystem abstraction for the Bejibun Framework, providing a single API over local disk and S3-compatible storage.
|
|
12
|
+
|
|
13
|
+
**Disk drivers:**
|
|
14
|
+
- `local` -- reads/writes files on the local filesystem
|
|
15
|
+
- `s3` -- reads/writes files to an S3-compatible bucket (endpoint, region, bucket, credentials configurable)
|
|
16
|
+
**`Storage` facade / `StorageBuilder`:**
|
|
17
|
+
- `.disk(name)` -- select a configured disk by name
|
|
18
|
+
- `.build(disk)` -- use an ad-hoc disk config at runtime, without touching `config/storage.ts`
|
|
19
|
+
- `.exists(path)` / `.missing(path)` -- check file presence
|
|
20
|
+
- `.metadata(path)` -- get file `Stats` (local) or `S3Stats` (S3)
|
|
21
|
+
- `.size(path)` -- get file size in bytes
|
|
22
|
+
- `.mimeType(path)` -- detect file MIME type
|
|
23
|
+
- `.lastModified(path)` -- get last-modified date
|
|
24
|
+
- `.get(path)` -- retrieve a `Bun.BunFile` or `Bun.S3File`
|
|
25
|
+
- `.put(path, content, options?)` -- write content to a file
|
|
26
|
+
- `.copy(source, destination, options?)` -- copy a file
|
|
27
|
+
- `.move(source, destination, options?)` -- move a file
|
|
28
|
+
- `.delete(path)` -- delete a file
|
|
29
|
+
**Config:**
|
|
30
|
+
- `config/storage.ts` supports a `default` disk plus a `disks` map; ships with `local`, `public`, and `s3` examples
|
|
31
|
+
- Per-operation `StorageOptions` cover S3-specific concerns (`acl`, `storageClass`, `partSize`, `queueSize`, `retry`, `virtualHostedStyle`, etc.) as well as local options (`mode`, `createPath`)
|
|
32
|
+
- `StorageDiskDriverEnum` (`Local` | `S3`) used to identify the driver per disk
|
|
33
|
+
**Error handling:**
|
|
34
|
+
- `StorageException` -- thrown for missing/invalid config, unsupported drivers, and missing required arguments; logs via `@bejibun/logger` before throwing
|
|
35
|
+
|
|
36
|
+
**Dependencies:**
|
|
37
|
+
- `@bejibun/app ^0.1.24`
|
|
38
|
+
- `@bejibun/logger ^0.1.22`
|
|
39
|
+
- `@bejibun/utils ^0.1.28`
|
|
40
|
+
|
|
41
|
+
### ❤️Contributors
|
|
42
|
+
- Havea Crenata ([@crenata](https://github.com/crenata))
|
|
43
|
+
|
|
44
|
+
**Full Changelog**: https://github.com/Bejibun-Framework/bejibun-storage/blob/master/CHANGELOG.md
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bejibun Framework
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://github.com/Bejibun-Framework/bejibun/blob/master/public/images/bejibun.png?raw=true" width="150" alt="Bejibun" />
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
# Storage for Bejibun
|
|
14
|
+
Storage for Bejibun Framework.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
Install the package.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Using Bun
|
|
23
|
+
bun add @bejibun/storage
|
|
24
|
+
|
|
25
|
+
# Using Bejibun
|
|
26
|
+
bun ace install @bejibun/storage
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Configuration
|
|
30
|
+
The configuration file automatically executed if you are using `ace`.
|
|
31
|
+
|
|
32
|
+
Or
|
|
33
|
+
|
|
34
|
+
Add `storage.ts` inside config directory on your project if doesn't exist.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
config/storage.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import App from "@bejibun/app";
|
|
42
|
+
import StorageDiskDriverEnum from "@/enums/StorageDiskDriverEnum";
|
|
43
|
+
|
|
44
|
+
const config: Record<string, any> = {
|
|
45
|
+
default: "local",
|
|
46
|
+
|
|
47
|
+
disks: {
|
|
48
|
+
local: {
|
|
49
|
+
driver: StorageDiskDriverEnum.Local,
|
|
50
|
+
root: App.Path.storagePath("app")
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
public: {
|
|
54
|
+
driver: StorageDiskDriverEnum.Local,
|
|
55
|
+
root: App.Path.storagePath("app/public"),
|
|
56
|
+
url: `${Bun.env.APP_URL}/storage/public`
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
s3: {
|
|
60
|
+
driver: StorageDiskDriverEnum.S3,
|
|
61
|
+
endpoint: Bun.env.S3_ENDPOINT,
|
|
62
|
+
region: Bun.env.S3_REGION,
|
|
63
|
+
bucket: Bun.env.S3_BUCKET,
|
|
64
|
+
access_key_id: Bun.env.S3_ACCESS_KEY_ID,
|
|
65
|
+
secret_access_key: Bun.env.S3_SECRET_ACCESS_KEY,
|
|
66
|
+
url: ""
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default config;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can pass the value with environment variables.
|
|
75
|
+
|
|
76
|
+
### How to Use
|
|
77
|
+
How to use tha package.
|
|
78
|
+
|
|
79
|
+
#### Standard Use
|
|
80
|
+
```ts
|
|
81
|
+
import Storage from "@bejibun/core/facades/Storage";
|
|
82
|
+
|
|
83
|
+
await Storage.exists("path/to/your/file.ext"); // Check if the file exists
|
|
84
|
+
await Storage.missing("path/to/your/file.ext"); // Check if the file doesn't exists
|
|
85
|
+
await Storage.get("path/to/your/file.ext"); // Get data content
|
|
86
|
+
await Storage.put("path/to/your/file.ext", "content"); // Store content to file
|
|
87
|
+
await Storage.copy("source/file.ext", "destination/file.ext"); // Copy file
|
|
88
|
+
await Storage.move("source/file.ext", "destination/file.ext"); // Move file
|
|
89
|
+
await Storage.delete("path/to/your/file.ext"); // Delete file
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### With Specified Disk
|
|
93
|
+
```ts
|
|
94
|
+
import Storage from "@bejibun/core/facades/Storage";
|
|
95
|
+
|
|
96
|
+
await Storage.disk("public").exists("path/to/your/file.ext");
|
|
97
|
+
await Storage.disk("public").missing("path/to/your/file.ext");
|
|
98
|
+
await Storage.disk("public").get("path/to/your/file.ext");
|
|
99
|
+
await Storage.disk("public").put("path/to/your/file.ext", "content");
|
|
100
|
+
await Storage.disk("public").copy("source/file.ext", "destination/file.ext");
|
|
101
|
+
await Storage.disk("public").move("source/file.ext", "destination/file.ext");
|
|
102
|
+
await Storage.disk("public").delete("path/to/your/file.ext");
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### New Disk at Runtime
|
|
106
|
+
```ts
|
|
107
|
+
import Storage from "@bejibun/core/facades/Storage";
|
|
108
|
+
|
|
109
|
+
await Storage.build({
|
|
110
|
+
driver: "local", // "local" | StorageDiskDriverEnum.Local
|
|
111
|
+
root: App.Path.storagePath("custom")
|
|
112
|
+
}).exists("path/to/your/file.ext");
|
|
113
|
+
await Storage.build({
|
|
114
|
+
driver: "local",
|
|
115
|
+
root: App.Path.storagePath("custom")
|
|
116
|
+
}).missing("path/to/your/file.ext");
|
|
117
|
+
await Storage.build({
|
|
118
|
+
driver: "local",
|
|
119
|
+
root: App.Path.storagePath("custom")
|
|
120
|
+
}).get("path/to/your/file.ext");
|
|
121
|
+
await Storage.build({
|
|
122
|
+
driver: "local",
|
|
123
|
+
root: App.Path.storagePath("custom")
|
|
124
|
+
}).put("path/to/your/file.ext", "content");
|
|
125
|
+
await Storage.build({
|
|
126
|
+
driver: "local",
|
|
127
|
+
root: App.Path.storagePath("custom")
|
|
128
|
+
}).copy("source/file.ext", "destination/file.ext");
|
|
129
|
+
await Storage.build({
|
|
130
|
+
driver: "local",
|
|
131
|
+
root: App.Path.storagePath("custom")
|
|
132
|
+
}).move("source/file.ext", "destination/file.ext");
|
|
133
|
+
await Storage.build({
|
|
134
|
+
driver: "local",
|
|
135
|
+
root: App.Path.storagePath("custom")
|
|
136
|
+
}).delete("path/to/your/file.ext");
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## ☕ Support / Donate
|
|
140
|
+
|
|
141
|
+
If you find this project helpful and want to support it:
|
|
142
|
+
|
|
143
|
+
[](https://donate.bejibun.com)
|
|
144
|
+
|
|
145
|
+
Or you can buy this `$BJBN (Bejibun)` tokens [here](https://pump.fun/coin/CQhbNnCGKfDaKXt8uE61i5DrBYJV7NPsCDD9vQgypump).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Stats } from "fs";
|
|
2
|
+
import type { StorageDisk, StorageOptions } from "../types/storage";
|
|
3
|
+
export default class StorageBuilder {
|
|
4
|
+
protected conf: Record<string, any>;
|
|
5
|
+
protected overrideDisk?: StorageDisk;
|
|
6
|
+
protected drive?: string;
|
|
7
|
+
constructor();
|
|
8
|
+
private get config();
|
|
9
|
+
private get currentDisk();
|
|
10
|
+
private get driver();
|
|
11
|
+
build(overrideDisk: StorageDisk): StorageBuilder;
|
|
12
|
+
disk(drive: string): StorageBuilder;
|
|
13
|
+
exists(filepath: string): Promise<boolean>;
|
|
14
|
+
missing(filepath: string): Promise<boolean>;
|
|
15
|
+
metadata(filepath: string): Promise<Stats | Bun.S3Stats>;
|
|
16
|
+
size(filepath: string): Promise<number>;
|
|
17
|
+
mimeType(filepath: string): Promise<string>;
|
|
18
|
+
lastModified(filepath: string): Promise<Date>;
|
|
19
|
+
get(filepath: string): Promise<Bun.BunFile | Bun.S3File>;
|
|
20
|
+
put(filepath: string, content: any, options?: StorageOptions): Promise<void>;
|
|
21
|
+
copy(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
22
|
+
move(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
23
|
+
delete(filepath: string): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import App from "@bejibun/app";
|
|
2
|
+
import Logger from "@bejibun/logger";
|
|
3
|
+
import { defineValue, isEmpty } from "@bejibun/utils";
|
|
4
|
+
import Enum from "@bejibun/utils/facades/Enum";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import StorageLocalBuilder from "../builders/storage/StorageLocalBuilder";
|
|
7
|
+
import StorageS3Builder from "../builders/storage/StorageS3Builder";
|
|
8
|
+
import StorageConfig from "../config/storage";
|
|
9
|
+
import StorageDiskDriverEnum from "../enums/StorageDiskDriverEnum";
|
|
10
|
+
import StorageException from "../exceptions/StorageException";
|
|
11
|
+
export default class StorageBuilder {
|
|
12
|
+
conf;
|
|
13
|
+
overrideDisk;
|
|
14
|
+
drive;
|
|
15
|
+
constructor() {
|
|
16
|
+
const configPath = App.Path.configPath("storage.ts");
|
|
17
|
+
let config;
|
|
18
|
+
if (fs.existsSync(configPath))
|
|
19
|
+
config = require(configPath).default;
|
|
20
|
+
else
|
|
21
|
+
config = StorageConfig;
|
|
22
|
+
this.conf = config;
|
|
23
|
+
}
|
|
24
|
+
get config() {
|
|
25
|
+
if (isEmpty(this.conf))
|
|
26
|
+
throw new StorageException("There is no config provided.");
|
|
27
|
+
return this.conf;
|
|
28
|
+
}
|
|
29
|
+
get currentDisk() {
|
|
30
|
+
return defineValue(this.overrideDisk, this.config.disks[defineValue(this.drive, this.config.default)]);
|
|
31
|
+
}
|
|
32
|
+
get driver() {
|
|
33
|
+
const driver = defineValue(this.currentDisk?.driver);
|
|
34
|
+
if (isEmpty(driver))
|
|
35
|
+
throw new StorageException(`Missing "driver" on disk config.`);
|
|
36
|
+
if (!Enum.setEnums(StorageDiskDriverEnum).hasValue(driver))
|
|
37
|
+
throw new StorageException(`Not supported "driver" disk.`);
|
|
38
|
+
switch (driver) {
|
|
39
|
+
case StorageDiskDriverEnum.Local:
|
|
40
|
+
return new StorageLocalBuilder(this.currentDisk);
|
|
41
|
+
case StorageDiskDriverEnum.S3:
|
|
42
|
+
return new StorageS3Builder(this.currentDisk);
|
|
43
|
+
default:
|
|
44
|
+
throw new StorageException(`Not supported "driver" disk.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
build(overrideDisk) {
|
|
48
|
+
this.overrideDisk = overrideDisk;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
disk(drive) {
|
|
52
|
+
this.drive = drive;
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
async exists(filepath) {
|
|
56
|
+
if (isEmpty(filepath))
|
|
57
|
+
throw new StorageException("The file path is required.");
|
|
58
|
+
return await this.driver.exists(filepath);
|
|
59
|
+
}
|
|
60
|
+
async missing(filepath) {
|
|
61
|
+
if (isEmpty(filepath))
|
|
62
|
+
throw new StorageException("The file path is required.");
|
|
63
|
+
return !await this.driver.missing(filepath);
|
|
64
|
+
}
|
|
65
|
+
async metadata(filepath) {
|
|
66
|
+
if (isEmpty(filepath))
|
|
67
|
+
throw new StorageException("The file path is required.");
|
|
68
|
+
return await this.driver.metadata(filepath);
|
|
69
|
+
}
|
|
70
|
+
async size(filepath) {
|
|
71
|
+
if (isEmpty(filepath))
|
|
72
|
+
throw new StorageException("The file path is required.");
|
|
73
|
+
return await this.driver.size(filepath);
|
|
74
|
+
}
|
|
75
|
+
async mimeType(filepath) {
|
|
76
|
+
if (isEmpty(filepath))
|
|
77
|
+
throw new StorageException("The file path is required.");
|
|
78
|
+
return await this.driver.mimeType(filepath);
|
|
79
|
+
}
|
|
80
|
+
async lastModified(filepath) {
|
|
81
|
+
if (isEmpty(filepath))
|
|
82
|
+
throw new StorageException("The file path is required.");
|
|
83
|
+
return await this.driver.lastModified(filepath);
|
|
84
|
+
}
|
|
85
|
+
async get(filepath) {
|
|
86
|
+
if (isEmpty(filepath))
|
|
87
|
+
throw new StorageException("The file path is required.");
|
|
88
|
+
return await this.driver.get(filepath);
|
|
89
|
+
}
|
|
90
|
+
async put(filepath, content, options) {
|
|
91
|
+
if (isEmpty(filepath))
|
|
92
|
+
throw new StorageException("The file path is required.");
|
|
93
|
+
if (isEmpty(content))
|
|
94
|
+
throw new StorageException("The content is required.");
|
|
95
|
+
try {
|
|
96
|
+
await this.driver.put(filepath, content, options);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
Logger.setContext("Storage").error("Something went wrong when saving file.").trace(error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async copy(source, destination, options) {
|
|
103
|
+
if (isEmpty(source))
|
|
104
|
+
throw new StorageException("The source file path is required.");
|
|
105
|
+
if (isEmpty(destination))
|
|
106
|
+
throw new StorageException("The destination file path is required.");
|
|
107
|
+
try {
|
|
108
|
+
await this.driver.copy(source, destination, options);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
Logger.setContext("Storage").error("Something went wrong when copying file.").trace(error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async move(source, destination, options) {
|
|
115
|
+
if (isEmpty(source))
|
|
116
|
+
throw new StorageException("The source file path is required.");
|
|
117
|
+
if (isEmpty(destination))
|
|
118
|
+
throw new StorageException("The destination file path is required.");
|
|
119
|
+
try {
|
|
120
|
+
await this.driver.move(source, destination, options);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
Logger.setContext("Storage").error("Something went wrong when moving file.").trace(error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async delete(filepath) {
|
|
127
|
+
if (isEmpty(filepath))
|
|
128
|
+
throw new StorageException("The file path is required.");
|
|
129
|
+
await this.driver.delete(filepath);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Stats } from "fs";
|
|
2
|
+
import type { StorageDriver, StorageOptions } from "../../types/storage";
|
|
3
|
+
export default class StorageLocalBuilder implements StorageDriver {
|
|
4
|
+
protected _config: Record<string, any>;
|
|
5
|
+
constructor(config: Record<string, any>);
|
|
6
|
+
private get config();
|
|
7
|
+
exists(filepath: string): Promise<boolean>;
|
|
8
|
+
missing(filepath: string): Promise<boolean>;
|
|
9
|
+
metadata(filepath: string): Promise<Stats>;
|
|
10
|
+
size(filepath: string): Promise<number>;
|
|
11
|
+
mimeType(filepath: string): Promise<string>;
|
|
12
|
+
lastModified(filepath: string): Promise<Date>;
|
|
13
|
+
get(filepath: string): Promise<Bun.BunFile>;
|
|
14
|
+
put(filepath: string, content: any, options?: StorageOptions): Promise<void>;
|
|
15
|
+
copy(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
16
|
+
move(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
17
|
+
delete(filepath: string): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import Logger from "@bejibun/logger";
|
|
2
|
+
import { isEmpty } from "@bejibun/utils";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import StorageException from "../../exceptions/StorageException";
|
|
5
|
+
export default class StorageLocalBuilder {
|
|
6
|
+
_config;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this._config = config;
|
|
9
|
+
}
|
|
10
|
+
get config() {
|
|
11
|
+
if (isEmpty(this._config.root))
|
|
12
|
+
throw new StorageException(`Missing "root" for "local" disk configuration.`);
|
|
13
|
+
return this._config;
|
|
14
|
+
}
|
|
15
|
+
async exists(filepath) {
|
|
16
|
+
if (isEmpty(filepath))
|
|
17
|
+
throw new StorageException("The file path is required.");
|
|
18
|
+
return await Bun.file(path.resolve(this.config.root, filepath)).exists();
|
|
19
|
+
}
|
|
20
|
+
async missing(filepath) {
|
|
21
|
+
if (isEmpty(filepath))
|
|
22
|
+
throw new StorageException("The file path is required.");
|
|
23
|
+
return !await this.exists(filepath);
|
|
24
|
+
}
|
|
25
|
+
async metadata(filepath) {
|
|
26
|
+
if (isEmpty(filepath))
|
|
27
|
+
throw new StorageException("The file path is required.");
|
|
28
|
+
return await (await this.get(filepath)).stat();
|
|
29
|
+
}
|
|
30
|
+
async size(filepath) {
|
|
31
|
+
if (isEmpty(filepath))
|
|
32
|
+
throw new StorageException("The file path is required.");
|
|
33
|
+
return (await this.metadata(filepath)).size;
|
|
34
|
+
}
|
|
35
|
+
async mimeType(filepath) {
|
|
36
|
+
if (isEmpty(filepath))
|
|
37
|
+
throw new StorageException("The file path is required.");
|
|
38
|
+
return (await this.get(filepath)).type;
|
|
39
|
+
}
|
|
40
|
+
async lastModified(filepath) {
|
|
41
|
+
if (isEmpty(filepath))
|
|
42
|
+
throw new StorageException("The file path is required.");
|
|
43
|
+
return (await this.metadata(filepath)).mtime;
|
|
44
|
+
}
|
|
45
|
+
async get(filepath) {
|
|
46
|
+
if (isEmpty(filepath))
|
|
47
|
+
throw new StorageException("The file path is required.");
|
|
48
|
+
return Bun.file(path.resolve(this.config.root, filepath));
|
|
49
|
+
}
|
|
50
|
+
async put(filepath, content, options) {
|
|
51
|
+
if (isEmpty(filepath))
|
|
52
|
+
throw new StorageException("The file path is required.");
|
|
53
|
+
if (isEmpty(content))
|
|
54
|
+
throw new StorageException("The content is required.");
|
|
55
|
+
try {
|
|
56
|
+
await Bun.write(path.resolve(this.config.root, filepath), content, options);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
Logger.setContext("Storage").error("Something went wrong when saving file.").trace(error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async copy(source, destination, options) {
|
|
63
|
+
if (isEmpty(source))
|
|
64
|
+
throw new StorageException("The source file path is required.");
|
|
65
|
+
if (isEmpty(destination))
|
|
66
|
+
throw new StorageException("The destination file path is required.");
|
|
67
|
+
try {
|
|
68
|
+
await this.put(destination, await this.get(source), options);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
Logger.setContext("Storage").error("Something went wrong when copying file.").trace(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async move(source, destination, options) {
|
|
75
|
+
if (isEmpty(source))
|
|
76
|
+
throw new StorageException("The source file path is required.");
|
|
77
|
+
if (isEmpty(destination))
|
|
78
|
+
throw new StorageException("The destination file path is required.");
|
|
79
|
+
try {
|
|
80
|
+
await this.copy(source, destination, options);
|
|
81
|
+
await this.delete(source);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
Logger.setContext("Storage").error("Something went wrong when moving file.").trace(error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async delete(filepath) {
|
|
88
|
+
if (isEmpty(filepath))
|
|
89
|
+
throw new StorageException("The file path is required.");
|
|
90
|
+
await Bun.file(path.resolve(this.config.root, filepath)).delete();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StorageDriver, StorageOptions } from "../../types/storage";
|
|
2
|
+
export default class StorageS3Builder implements StorageDriver {
|
|
3
|
+
protected _config: Record<string, any>;
|
|
4
|
+
protected client: Bun.S3Client;
|
|
5
|
+
constructor(config: Record<string, any>);
|
|
6
|
+
private get config();
|
|
7
|
+
exists(filepath: string): Promise<boolean>;
|
|
8
|
+
missing(filepath: string): Promise<boolean>;
|
|
9
|
+
metadata(filepath: string): Promise<Bun.S3Stats>;
|
|
10
|
+
size(filepath: string): Promise<number>;
|
|
11
|
+
mimeType(filepath: string): Promise<string>;
|
|
12
|
+
lastModified(filepath: string): Promise<Date>;
|
|
13
|
+
get(filepath: string): Promise<Bun.S3File>;
|
|
14
|
+
put(filepath: string, content: any, options?: StorageOptions): Promise<void>;
|
|
15
|
+
copy(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
16
|
+
move(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
17
|
+
delete(filepath: string): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import Logger from "@bejibun/logger";
|
|
2
|
+
import { isEmpty } from "@bejibun/utils";
|
|
3
|
+
import StorageException from "../../exceptions/StorageException";
|
|
4
|
+
export default class StorageS3Builder {
|
|
5
|
+
_config;
|
|
6
|
+
client;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this._config = config;
|
|
9
|
+
this.client = new Bun.S3Client({
|
|
10
|
+
endpoint: this.config.endpoint,
|
|
11
|
+
region: this.config.region,
|
|
12
|
+
bucket: this.config.bucket,
|
|
13
|
+
accessKeyId: this.config.access_key_id,
|
|
14
|
+
secretAccessKey: this.config.secret_access_key
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
get config() {
|
|
18
|
+
if (isEmpty(this._config.endpoint))
|
|
19
|
+
throw new StorageException(`Missing "endpoint" for "s3" disk configuration.`);
|
|
20
|
+
if (isEmpty(this._config.access_key_id))
|
|
21
|
+
throw new StorageException(`Missing "access_key_id" for "s3" disk configuration.`);
|
|
22
|
+
if (isEmpty(this._config.secret_access_key))
|
|
23
|
+
throw new StorageException(`Missing "secret_access_key" for "s3" disk configuration.`);
|
|
24
|
+
return this._config;
|
|
25
|
+
}
|
|
26
|
+
async exists(filepath) {
|
|
27
|
+
if (isEmpty(filepath))
|
|
28
|
+
throw new StorageException("The file path is required.");
|
|
29
|
+
return await this.client.file(filepath).exists();
|
|
30
|
+
}
|
|
31
|
+
async missing(filepath) {
|
|
32
|
+
if (isEmpty(filepath))
|
|
33
|
+
throw new StorageException("The file path is required.");
|
|
34
|
+
return !await this.exists(filepath);
|
|
35
|
+
}
|
|
36
|
+
async metadata(filepath) {
|
|
37
|
+
if (isEmpty(filepath))
|
|
38
|
+
throw new StorageException("The file path is required.");
|
|
39
|
+
return await (await this.get(filepath)).stat();
|
|
40
|
+
}
|
|
41
|
+
async size(filepath) {
|
|
42
|
+
if (isEmpty(filepath))
|
|
43
|
+
throw new StorageException("The file path is required.");
|
|
44
|
+
return (await this.metadata(filepath)).size;
|
|
45
|
+
}
|
|
46
|
+
async mimeType(filepath) {
|
|
47
|
+
if (isEmpty(filepath))
|
|
48
|
+
throw new StorageException("The file path is required.");
|
|
49
|
+
return (await this.metadata(filepath)).type;
|
|
50
|
+
}
|
|
51
|
+
async lastModified(filepath) {
|
|
52
|
+
if (isEmpty(filepath))
|
|
53
|
+
throw new StorageException("The file path is required.");
|
|
54
|
+
return (await this.metadata(filepath)).lastModified;
|
|
55
|
+
}
|
|
56
|
+
async get(filepath) {
|
|
57
|
+
if (isEmpty(filepath))
|
|
58
|
+
throw new StorageException("The file path is required.");
|
|
59
|
+
return this.client.file(filepath);
|
|
60
|
+
}
|
|
61
|
+
async put(filepath, content, options) {
|
|
62
|
+
if (isEmpty(filepath))
|
|
63
|
+
throw new StorageException("The file path is required.");
|
|
64
|
+
if (isEmpty(content))
|
|
65
|
+
throw new StorageException("The content is required.");
|
|
66
|
+
try {
|
|
67
|
+
await this.client.write(filepath, content, options);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
Logger.setContext("Storage").error("Something went wrong when saving file.").trace(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async copy(source, destination, options) {
|
|
74
|
+
if (isEmpty(source))
|
|
75
|
+
throw new StorageException("The source file path is required.");
|
|
76
|
+
if (isEmpty(destination))
|
|
77
|
+
throw new StorageException("The destination file path is required.");
|
|
78
|
+
try {
|
|
79
|
+
await this.put(destination, await this.get(source), options);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
Logger.setContext("Storage").error("Something went wrong when copying file.").trace(error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async move(source, destination, options) {
|
|
86
|
+
if (isEmpty(source))
|
|
87
|
+
throw new StorageException("The source file path is required.");
|
|
88
|
+
if (isEmpty(destination))
|
|
89
|
+
throw new StorageException("The destination file path is required.");
|
|
90
|
+
try {
|
|
91
|
+
await this.copy(source, destination, options);
|
|
92
|
+
await this.delete(source);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
Logger.setContext("Storage").error("Something went wrong when moving file.").trace(error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async delete(filepath) {
|
|
99
|
+
if (isEmpty(filepath))
|
|
100
|
+
throw new StorageException("The file path is required.");
|
|
101
|
+
await this.client.file(filepath).delete();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import App from "@bejibun/app";
|
|
2
|
+
import StorageDiskDriverEnum from "../enums/StorageDiskDriverEnum";
|
|
3
|
+
const config = {
|
|
4
|
+
default: "local",
|
|
5
|
+
disks: {
|
|
6
|
+
local: {
|
|
7
|
+
driver: StorageDiskDriverEnum.Local,
|
|
8
|
+
root: App.Path.storagePath("app")
|
|
9
|
+
},
|
|
10
|
+
public: {
|
|
11
|
+
driver: StorageDiskDriverEnum.Local,
|
|
12
|
+
root: App.Path.storagePath("app/public"),
|
|
13
|
+
url: `${Bun.env.APP_URL}/storage/public`
|
|
14
|
+
},
|
|
15
|
+
s3: {
|
|
16
|
+
driver: StorageDiskDriverEnum.S3,
|
|
17
|
+
endpoint: Bun.env.S3_ENDPOINT,
|
|
18
|
+
region: Bun.env.S3_REGION,
|
|
19
|
+
bucket: Bun.env.S3_BUCKET,
|
|
20
|
+
access_key_id: Bun.env.S3_ACCESS_KEY_ID,
|
|
21
|
+
secret_access_key: Bun.env.S3_SECRET_ACCESS_KEY,
|
|
22
|
+
url: ""
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export default config;
|
package/configure.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/configure.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import App from "@bejibun/app";
|
|
2
|
+
import Logger from "@bejibun/logger";
|
|
3
|
+
import path from "path";
|
|
4
|
+
const configPath = path.resolve(__dirname, "config");
|
|
5
|
+
const regex = /\.(m?js|ts)$/;
|
|
6
|
+
const configs = Array.from(new Bun.Glob("**/*").scanSync({
|
|
7
|
+
cwd: configPath
|
|
8
|
+
})).filter(value => (regex.test(value) &&
|
|
9
|
+
!value.endsWith(".d.ts")));
|
|
10
|
+
for (const config of configs) {
|
|
11
|
+
const destination = config.replace(regex, ".ts");
|
|
12
|
+
await Bun.write(App.Path.configPath(destination), await Bun.file(path.resolve(configPath, config)).text());
|
|
13
|
+
Logger.setContext("CONFIGURE").info(`Copying ${config} into config/${destination}`);
|
|
14
|
+
}
|
package/enums/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../enums/StorageDiskDriverEnum";
|
package/enums/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../enums/StorageDiskDriverEnum";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Logger from "@bejibun/logger";
|
|
2
|
+
import { defineValue } from "@bejibun/utils";
|
|
3
|
+
export default class StorageException extends Error {
|
|
4
|
+
code;
|
|
5
|
+
constructor(message, code) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "StorageException";
|
|
8
|
+
this.code = defineValue(code, 503);
|
|
9
|
+
Logger.setContext(this.name).error(this.message).trace(this.stack);
|
|
10
|
+
if (Error.captureStackTrace) {
|
|
11
|
+
Error.captureStackTrace(this, StorageException);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../exceptions/StorageException";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../exceptions/StorageException";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Stats } from "fs";
|
|
2
|
+
import type { StorageDisk, StorageOptions } from "../types/storage";
|
|
3
|
+
import StorageBuilder from "../builders/StorageBuilder";
|
|
4
|
+
export default class Storage {
|
|
5
|
+
static build(disk: StorageDisk): StorageBuilder;
|
|
6
|
+
static disk(disk: string): StorageBuilder;
|
|
7
|
+
static exists(path: string): Promise<boolean>;
|
|
8
|
+
static missing(path: string): Promise<boolean>;
|
|
9
|
+
static metadata(path: string): Promise<Stats | Bun.S3Stats>;
|
|
10
|
+
static size(path: string): Promise<number>;
|
|
11
|
+
static mimeType(path: string): Promise<string>;
|
|
12
|
+
static lastModified(path: string): Promise<Date>;
|
|
13
|
+
static get(path: string): Promise<Bun.BunFile | Bun.S3File>;
|
|
14
|
+
static put(path: string, content: any, options?: StorageOptions): Promise<void>;
|
|
15
|
+
static copy(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
16
|
+
static move(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
17
|
+
static delete(path: string): Promise<any>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import StorageBuilder from "../builders/StorageBuilder";
|
|
2
|
+
export default class Storage {
|
|
3
|
+
static build(disk) {
|
|
4
|
+
return new StorageBuilder().build(disk);
|
|
5
|
+
}
|
|
6
|
+
static disk(disk) {
|
|
7
|
+
return new StorageBuilder().disk(disk);
|
|
8
|
+
}
|
|
9
|
+
static async exists(path) {
|
|
10
|
+
return await new StorageBuilder().exists(path);
|
|
11
|
+
}
|
|
12
|
+
static async missing(path) {
|
|
13
|
+
return await new StorageBuilder().missing(path);
|
|
14
|
+
}
|
|
15
|
+
static async metadata(path) {
|
|
16
|
+
return await new StorageBuilder().metadata(path);
|
|
17
|
+
}
|
|
18
|
+
static async size(path) {
|
|
19
|
+
return await new StorageBuilder().size(path);
|
|
20
|
+
}
|
|
21
|
+
static async mimeType(path) {
|
|
22
|
+
return await new StorageBuilder().mimeType(path);
|
|
23
|
+
}
|
|
24
|
+
static async lastModified(path) {
|
|
25
|
+
return await new StorageBuilder().lastModified(path);
|
|
26
|
+
}
|
|
27
|
+
static async get(path) {
|
|
28
|
+
return await new StorageBuilder().get(path);
|
|
29
|
+
}
|
|
30
|
+
static async put(path, content, options) {
|
|
31
|
+
return await new StorageBuilder().put(path, content);
|
|
32
|
+
}
|
|
33
|
+
static async copy(source, destination, options) {
|
|
34
|
+
return await new StorageBuilder().copy(source, destination, options);
|
|
35
|
+
}
|
|
36
|
+
static async move(source, destination, options) {
|
|
37
|
+
return await new StorageBuilder().move(source, destination, options);
|
|
38
|
+
}
|
|
39
|
+
static async delete(path) {
|
|
40
|
+
return await new StorageBuilder().delete(path);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../facades/Storage";
|
package/facades/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../facades/Storage";
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bejibun/storage",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "Havea Crenata <havea.crenata@gmail.com>",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Bejibun-Framework/bejibun-storage.git"
|
|
8
|
+
},
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"module": "index.js",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@bejibun/app": "^0.1.24",
|
|
13
|
+
"@bejibun/logger": "^0.1.22",
|
|
14
|
+
"@bejibun/utils": "^0.1.28"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/bun": "latest",
|
|
18
|
+
"tsc-alias": "^1.9.1"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Bejibun-Framework/bejibun-storage/issues"
|
|
22
|
+
},
|
|
23
|
+
"description": "Storage for Bejibun Framework",
|
|
24
|
+
"homepage": "https://github.com/Bejibun-Framework/bejibun-storage#readme",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"bun",
|
|
27
|
+
"bun framework",
|
|
28
|
+
"storage",
|
|
29
|
+
"bejibun",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"alias": "bunx tsc-alias -p tsconfig.json",
|
|
35
|
+
"types": "cp -rf src/types dist",
|
|
36
|
+
"rsync": "rsync -a dist/ ./",
|
|
37
|
+
"clean": "rm -rf dist",
|
|
38
|
+
"build": "bunx tsc -p tsconfig.json && bun run types && bun run alias && bun run rsync && bun run clean",
|
|
39
|
+
"deploy": "bun run build && bun publish --access public"
|
|
40
|
+
},
|
|
41
|
+
"type": "module",
|
|
42
|
+
"types": "index.d.ts"
|
|
43
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
"@/*": ["./src/*"]
|
|
14
|
+
},
|
|
15
|
+
"ignoreDeprecations": "6.0",
|
|
16
|
+
"types": ["bun-types"]
|
|
17
|
+
}
|
|
18
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../types/storage";
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type {Stats} from "fs";
|
|
2
|
+
|
|
3
|
+
export type StorageDisk = {
|
|
4
|
+
driver: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type StorageOptions = {
|
|
9
|
+
mode?: number;
|
|
10
|
+
createPath?: boolean;
|
|
11
|
+
acl?:
|
|
12
|
+
| "private"
|
|
13
|
+
| "public-read"
|
|
14
|
+
| "public-read-write"
|
|
15
|
+
| "aws-exec-read"
|
|
16
|
+
| "authenticated-read"
|
|
17
|
+
| "bucket-owner-read"
|
|
18
|
+
| "bucket-owner-full-control"
|
|
19
|
+
| "log-delivery-write";
|
|
20
|
+
bucket?: string;
|
|
21
|
+
region?: string;
|
|
22
|
+
accessKeyId?: string;
|
|
23
|
+
secretAccessKey?: string;
|
|
24
|
+
sessionToken?: string;
|
|
25
|
+
endpoint?: string;
|
|
26
|
+
virtualHostedStyle?: boolean;
|
|
27
|
+
partSize?: number;
|
|
28
|
+
queueSize?: number;
|
|
29
|
+
retry?: number;
|
|
30
|
+
type?: string;
|
|
31
|
+
contentDisposition?: string | undefined;
|
|
32
|
+
storageClass?:
|
|
33
|
+
| "STANDARD"
|
|
34
|
+
| "DEEP_ARCHIVE"
|
|
35
|
+
| "EXPRESS_ONEZONE"
|
|
36
|
+
| "GLACIER"
|
|
37
|
+
| "GLACIER_IR"
|
|
38
|
+
| "INTELLIGENT_TIERING"
|
|
39
|
+
| "ONEZONE_IA"
|
|
40
|
+
| "OUTPOSTS"
|
|
41
|
+
| "REDUCED_REDUNDANCY"
|
|
42
|
+
| "SNOW"
|
|
43
|
+
| "STANDARD_IA";
|
|
44
|
+
requestPayer?: boolean;
|
|
45
|
+
highWaterMark?: number;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface StorageDriver {
|
|
49
|
+
/**
|
|
50
|
+
* Determine whether a file exists.
|
|
51
|
+
*
|
|
52
|
+
* @param filepath The path to the file.
|
|
53
|
+
* @returns True if the file exists; otherwise false.
|
|
54
|
+
*/
|
|
55
|
+
exists(filepath: string): Promise<boolean>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Determine whether a file is missing.
|
|
59
|
+
*
|
|
60
|
+
* @param filepath The path to the file.
|
|
61
|
+
* @returns True if the file does not exist; otherwise false.
|
|
62
|
+
*/
|
|
63
|
+
missing(filepath: string): Promise<boolean>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Retrieve metadata for a file.
|
|
67
|
+
*
|
|
68
|
+
* @param filepath The path to the file.
|
|
69
|
+
* @returns File metadata and statistics.
|
|
70
|
+
*/
|
|
71
|
+
metadata(filepath: string): Promise<Stats | Bun.S3Stats>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get the file size in bytes.
|
|
75
|
+
*
|
|
76
|
+
* @param filepath The path to the file.
|
|
77
|
+
* @returns The file size in bytes.
|
|
78
|
+
*/
|
|
79
|
+
size(filepath: string): Promise<number>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the file MIME type.
|
|
83
|
+
*
|
|
84
|
+
* @param filepath The path to the file.
|
|
85
|
+
* @returns The detected MIME type.
|
|
86
|
+
*/
|
|
87
|
+
mimeType(filepath: string): Promise<string>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get the file's last modification date.
|
|
91
|
+
*
|
|
92
|
+
* @param filepath The path to the file.
|
|
93
|
+
* @returns The last modified timestamp.
|
|
94
|
+
*/
|
|
95
|
+
lastModified(filepath: string): Promise<Date>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Retrieve a file from storage.
|
|
99
|
+
*
|
|
100
|
+
* @param filepath The path to the file.
|
|
101
|
+
* @returns The storage file instance.
|
|
102
|
+
*/
|
|
103
|
+
get(filepath: string): Promise<Bun.BunFile | Bun.S3File>;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Store content at the given path.
|
|
107
|
+
*
|
|
108
|
+
* @param filepath The destination file path.
|
|
109
|
+
* @param content The content to store.
|
|
110
|
+
* @param options Additional storage options.
|
|
111
|
+
*/
|
|
112
|
+
put(filepath: string, content: any, options?: StorageOptions): Promise<void>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Copy a file to a new location.
|
|
116
|
+
*
|
|
117
|
+
* @param source The source file path.
|
|
118
|
+
* @param destination The destination file path.
|
|
119
|
+
* @param options Additional storage options.
|
|
120
|
+
*/
|
|
121
|
+
copy(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Move a file to a new location.
|
|
125
|
+
*
|
|
126
|
+
* @param source The source file path.
|
|
127
|
+
* @param destination The destination file path.
|
|
128
|
+
* @param options Additional storage options.
|
|
129
|
+
*/
|
|
130
|
+
move(source: string, destination: string, options?: StorageOptions): Promise<void>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Delete a file from storage.
|
|
134
|
+
*
|
|
135
|
+
* @param filepath The path to the file.
|
|
136
|
+
*/
|
|
137
|
+
delete(filepath: string): Promise<void>;
|
|
138
|
+
}
|