@wild-framework/storage-s3 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +41 -2
- package/dist/driver.d.ts +50 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +109 -0
- package/dist/driver.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +39 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +63 -0
- package/dist/provider.js.map +1 -0
- package/package.json +44 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wild Framework contributors
|
|
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
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @wild-framework/storage-s3
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
S3 (AWS) storage driver for [Wild Framework](https://github.com/KhandaSoftware/wild-framework)'s storage package. Works with AWS S3 and any S3-compatible store (MinIO, Cloudflare R2, DigitalOcean Spaces, …).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @wild-framework/storage-s3
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { S3StorageProvider } from "@wild-framework/storage-s3";
|
|
15
|
+
|
|
16
|
+
S3StorageProvider.bucket = process.env.AWS_BUCKET;
|
|
17
|
+
S3StorageProvider.region = process.env.AWS_REGION;
|
|
18
|
+
S3StorageProvider.accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
19
|
+
S3StorageProvider.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
20
|
+
|
|
21
|
+
app.register(S3StorageProvider);
|
|
22
|
+
// … storage is now S3-backed, resolved via app.resolve(Storage)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- Omit `accessKeyId`/`secretAccessKey` to use the default AWS credential chain (env vars, IAM role, EC2 metadata).
|
|
26
|
+
- Set `publicUrl` to serve public objects directly; otherwise `storage.url(key, { expiresIn })` returns a **presigned** URL.
|
|
27
|
+
- Point `endpoint` + `forcePathStyle` at MinIO/R2 for self-hosted or S3-compatible storage.
|
|
28
|
+
|
|
29
|
+
## Integration test
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
AWS_BUCKET=test AWS_REGION=us-east-1 \
|
|
33
|
+
AWS_ENDPOINT=http://localhost:9000 \
|
|
34
|
+
AWS_ACCESS_KEY_ID=wild AWS_SECRET_ACCESS_KEY=wildsecret \
|
|
35
|
+
pnpm --filter @wild-framework/storage-s3 test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Skips automatically when the env vars are not set.
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
MIT
|
package/dist/driver.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { StorageDriver, PutOptions, UrlOptions } from "@wild-framework/storage";
|
|
2
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for the S3 storage driver.
|
|
5
|
+
*/
|
|
6
|
+
export interface S3StorageConfig {
|
|
7
|
+
/** S3 bucket name. */
|
|
8
|
+
bucket: string;
|
|
9
|
+
/** AWS region, e.g. `us-east-1`. */
|
|
10
|
+
region: string;
|
|
11
|
+
/** Static credentials. Omit to use the default AWS credential chain (env, IAM role, etc.). */
|
|
12
|
+
credentials?: {
|
|
13
|
+
accessKeyId: string;
|
|
14
|
+
secretAccessKey: string;
|
|
15
|
+
};
|
|
16
|
+
/** Custom endpoint — for S3-compatible stores like MinIO. */
|
|
17
|
+
endpoint?: string;
|
|
18
|
+
/** Use path-style addressing (required for MinIO and many custom endpoints). */
|
|
19
|
+
forcePathStyle?: boolean;
|
|
20
|
+
/** Base URL for public objects. When set, `url()` returns `${publicUrl}/${key}`. */
|
|
21
|
+
publicUrl?: string;
|
|
22
|
+
/** Default expiry (seconds) for signed URLs when `url()` is called with no `expiresIn`. */
|
|
23
|
+
signedUrlExpiresIn?: number;
|
|
24
|
+
/** A pre-built client — for advanced use or tests. */
|
|
25
|
+
client?: S3Client;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* S3-backed storage driver implementing `StorageDriver`.
|
|
29
|
+
*
|
|
30
|
+
* Backed by `@aws-sdk/client-s3` (v3). Works with AWS S3 and any
|
|
31
|
+
* S3-compatible store (MinIO, R2, DigitalOcean Spaces, …). Call `connect()`
|
|
32
|
+
* to materialise the client (so bad config fails early) — `S3StorageProvider`
|
|
33
|
+
* does this on boot.
|
|
34
|
+
*/
|
|
35
|
+
export declare class S3StorageDriver implements StorageDriver {
|
|
36
|
+
private config;
|
|
37
|
+
private client;
|
|
38
|
+
constructor(config: S3StorageConfig);
|
|
39
|
+
connect(): Promise<void>;
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
put(path: string, contents: Buffer | string, options?: PutOptions): Promise<string>;
|
|
42
|
+
get(path: string): Promise<Buffer>;
|
|
43
|
+
delete(path: string): Promise<void>;
|
|
44
|
+
exists(path: string): Promise<boolean>;
|
|
45
|
+
url(path: string, options?: UrlOptions): Promise<string>;
|
|
46
|
+
private defaultPublicUrl;
|
|
47
|
+
private normalizeKey;
|
|
48
|
+
private requireClient;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EACH,QAAQ,EAKX,MAAM,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,WAAW,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,MAAM,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,qBAAa,eAAgB,YAAW,aAAa;IAGrC,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAyB;gBAEnB,MAAM,EAAE,eAAe;IASrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAanF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWlC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB9D,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;CAaxB"}
|
package/dist/driver.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, HeadObjectCommand, } from "@aws-sdk/client-s3";
|
|
2
|
+
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
3
|
+
/**
|
|
4
|
+
* S3-backed storage driver implementing `StorageDriver`.
|
|
5
|
+
*
|
|
6
|
+
* Backed by `@aws-sdk/client-s3` (v3). Works with AWS S3 and any
|
|
7
|
+
* S3-compatible store (MinIO, R2, DigitalOcean Spaces, …). Call `connect()`
|
|
8
|
+
* to materialise the client (so bad config fails early) — `S3StorageProvider`
|
|
9
|
+
* does this on boot.
|
|
10
|
+
*/
|
|
11
|
+
export class S3StorageDriver {
|
|
12
|
+
config;
|
|
13
|
+
client = null;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
if (!config.bucket) {
|
|
17
|
+
throw new Error("S3StorageDriver requires a bucket.");
|
|
18
|
+
}
|
|
19
|
+
if (!config.client && !config.region) {
|
|
20
|
+
throw new Error("S3StorageDriver requires a region (or an injected client).");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async connect() {
|
|
24
|
+
this.requireClient(); // materialise so config errors surface at boot
|
|
25
|
+
}
|
|
26
|
+
async close() {
|
|
27
|
+
// Only destroy clients we created — an injected client is the caller's.
|
|
28
|
+
if (this.client && !this.config.client) {
|
|
29
|
+
this.client.destroy();
|
|
30
|
+
}
|
|
31
|
+
this.client = null;
|
|
32
|
+
}
|
|
33
|
+
async put(path, contents, options) {
|
|
34
|
+
await this.requireClient().send(new PutObjectCommand({
|
|
35
|
+
Bucket: this.config.bucket,
|
|
36
|
+
Key: this.normalizeKey(path),
|
|
37
|
+
Body: contents,
|
|
38
|
+
ContentType: options?.contentType,
|
|
39
|
+
Metadata: options?.metadata,
|
|
40
|
+
}));
|
|
41
|
+
return path;
|
|
42
|
+
}
|
|
43
|
+
async get(path) {
|
|
44
|
+
const response = await this.requireClient().send(new GetObjectCommand({ Bucket: this.config.bucket, Key: this.normalizeKey(path) }));
|
|
45
|
+
if (!response.Body) {
|
|
46
|
+
throw new Error(`Object "${path}" has no body.`);
|
|
47
|
+
}
|
|
48
|
+
const bytes = await response.Body.transformToByteArray();
|
|
49
|
+
return Buffer.from(bytes);
|
|
50
|
+
}
|
|
51
|
+
async delete(path) {
|
|
52
|
+
await this.requireClient().send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: this.normalizeKey(path) }));
|
|
53
|
+
}
|
|
54
|
+
async exists(path) {
|
|
55
|
+
try {
|
|
56
|
+
await this.requireClient().send(new HeadObjectCommand({ Bucket: this.config.bucket, Key: this.normalizeKey(path) }));
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const status = error
|
|
61
|
+
?.$metadata?.httpStatusCode;
|
|
62
|
+
// 404 = missing; 403 = missing in a private bucket.
|
|
63
|
+
if (status === 404 || status === 403)
|
|
64
|
+
return false;
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async url(path, options) {
|
|
69
|
+
const key = this.normalizeKey(path);
|
|
70
|
+
if (this.config.publicUrl) {
|
|
71
|
+
return joinUrl(this.config.publicUrl, key);
|
|
72
|
+
}
|
|
73
|
+
if (options?.expiresIn !== undefined || this.config.signedUrlExpiresIn !== undefined) {
|
|
74
|
+
const expiresIn = options?.expiresIn ?? this.config.signedUrlExpiresIn ?? 3600;
|
|
75
|
+
return getSignedUrl(this.requireClient(), new GetObjectCommand({ Bucket: this.config.bucket, Key: key }), { expiresIn });
|
|
76
|
+
}
|
|
77
|
+
return this.defaultPublicUrl(key);
|
|
78
|
+
}
|
|
79
|
+
defaultPublicUrl(key) {
|
|
80
|
+
if (this.config.endpoint) {
|
|
81
|
+
return joinUrl(this.config.endpoint, `${this.config.bucket}/${key}`);
|
|
82
|
+
}
|
|
83
|
+
const host = this.config.region === "us-east-1"
|
|
84
|
+
? `${this.config.bucket}.s3.amazonaws.com`
|
|
85
|
+
: `${this.config.bucket}.s3.${this.config.region}.amazonaws.com`;
|
|
86
|
+
return `https://${host}/${key}`;
|
|
87
|
+
}
|
|
88
|
+
normalizeKey(path) {
|
|
89
|
+
return path.replace(/^\/+/, "");
|
|
90
|
+
}
|
|
91
|
+
requireClient() {
|
|
92
|
+
if (!this.client) {
|
|
93
|
+
this.client =
|
|
94
|
+
this.config.client ??
|
|
95
|
+
new S3Client({
|
|
96
|
+
region: this.config.region,
|
|
97
|
+
credentials: this.config.credentials,
|
|
98
|
+
endpoint: this.config.endpoint,
|
|
99
|
+
forcePathStyle: this.config.forcePathStyle,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return this.client;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Join a base URL and a key without producing double slashes. */
|
|
106
|
+
function joinUrl(base, key) {
|
|
107
|
+
return `${base.replace(/\/+$/, "")}/${key.replace(/^\/+/, "")}`;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Provider, Application } from "@wild-framework/core";
|
|
2
|
+
/**
|
|
3
|
+
* Registers an S3-backed storage with the application.
|
|
4
|
+
*
|
|
5
|
+
* Static configuration (no-arg constructor requirement):
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* S3StorageProvider.bucket = "my-bucket";
|
|
9
|
+
* S3StorageProvider.region = "us-east-1";
|
|
10
|
+
* S3StorageProvider.accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
11
|
+
* S3StorageProvider.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Materialises the client on boot (fail-fast on bad config) and destroys it
|
|
15
|
+
* on shutdown.
|
|
16
|
+
*/
|
|
17
|
+
export declare class S3StorageProvider implements Provider {
|
|
18
|
+
/** S3 bucket name. */
|
|
19
|
+
static bucket: string | undefined;
|
|
20
|
+
/** AWS region. */
|
|
21
|
+
static region: string | undefined;
|
|
22
|
+
/** Access key id. Omit to use the default AWS credential chain. */
|
|
23
|
+
static accessKeyId: string | undefined;
|
|
24
|
+
/** Secret access key. */
|
|
25
|
+
static secretAccessKey: string | undefined;
|
|
26
|
+
/** Custom endpoint (MinIO, R2, …). */
|
|
27
|
+
static endpoint: string | undefined;
|
|
28
|
+
/** Path-style addressing for custom endpoints. */
|
|
29
|
+
static forcePathStyle: boolean;
|
|
30
|
+
/** Base URL for public objects. */
|
|
31
|
+
static publicUrl: string | undefined;
|
|
32
|
+
/** Default expiry (seconds) for signed URLs. */
|
|
33
|
+
static signedUrlExpiresIn: number | undefined;
|
|
34
|
+
private driver;
|
|
35
|
+
register(app: Application): void;
|
|
36
|
+
boot(): Promise<void>;
|
|
37
|
+
shutdown(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKlE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAkB,YAAW,QAAQ;IAC9C,sBAAsB;IACtB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,kBAAkB;IAClB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,mEAAmE;IACnE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,yBAAyB;IACzB,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,sCAAsC;IACtC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,kDAAkD;IAClD,MAAM,CAAC,cAAc,UAAS;IAC9B,mCAAmC;IACnC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,gDAAgD;IAChD,MAAM,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IAE9C,OAAO,CAAC,MAAM,CAA8B;IAE5C,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAsB1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Container } from "@wild-framework/container";
|
|
2
|
+
import { Storage } from "@wild-framework/storage";
|
|
3
|
+
import { S3StorageDriver } from "./driver.js";
|
|
4
|
+
/**
|
|
5
|
+
* Registers an S3-backed storage with the application.
|
|
6
|
+
*
|
|
7
|
+
* Static configuration (no-arg constructor requirement):
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* S3StorageProvider.bucket = "my-bucket";
|
|
11
|
+
* S3StorageProvider.region = "us-east-1";
|
|
12
|
+
* S3StorageProvider.accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
13
|
+
* S3StorageProvider.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Materialises the client on boot (fail-fast on bad config) and destroys it
|
|
17
|
+
* on shutdown.
|
|
18
|
+
*/
|
|
19
|
+
export class S3StorageProvider {
|
|
20
|
+
/** S3 bucket name. */
|
|
21
|
+
static bucket;
|
|
22
|
+
/** AWS region. */
|
|
23
|
+
static region;
|
|
24
|
+
/** Access key id. Omit to use the default AWS credential chain. */
|
|
25
|
+
static accessKeyId;
|
|
26
|
+
/** Secret access key. */
|
|
27
|
+
static secretAccessKey;
|
|
28
|
+
/** Custom endpoint (MinIO, R2, …). */
|
|
29
|
+
static endpoint;
|
|
30
|
+
/** Path-style addressing for custom endpoints. */
|
|
31
|
+
static forcePathStyle = false;
|
|
32
|
+
/** Base URL for public objects. */
|
|
33
|
+
static publicUrl;
|
|
34
|
+
/** Default expiry (seconds) for signed URLs. */
|
|
35
|
+
static signedUrlExpiresIn;
|
|
36
|
+
driver;
|
|
37
|
+
register(app) {
|
|
38
|
+
const container = app.resolve(Container);
|
|
39
|
+
const driver = new S3StorageDriver({
|
|
40
|
+
bucket: S3StorageProvider.bucket ?? "",
|
|
41
|
+
region: S3StorageProvider.region ?? "",
|
|
42
|
+
credentials: S3StorageProvider.accessKeyId
|
|
43
|
+
? {
|
|
44
|
+
accessKeyId: S3StorageProvider.accessKeyId,
|
|
45
|
+
secretAccessKey: S3StorageProvider.secretAccessKey ?? "",
|
|
46
|
+
}
|
|
47
|
+
: undefined,
|
|
48
|
+
endpoint: S3StorageProvider.endpoint,
|
|
49
|
+
forcePathStyle: S3StorageProvider.forcePathStyle,
|
|
50
|
+
publicUrl: S3StorageProvider.publicUrl,
|
|
51
|
+
signedUrlExpiresIn: S3StorageProvider.signedUrlExpiresIn,
|
|
52
|
+
});
|
|
53
|
+
this.driver = driver;
|
|
54
|
+
container.singleton(Storage, () => new Storage(driver));
|
|
55
|
+
}
|
|
56
|
+
async boot() {
|
|
57
|
+
await this.driver?.connect();
|
|
58
|
+
}
|
|
59
|
+
async shutdown() {
|
|
60
|
+
await this.driver?.close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,iBAAiB;IAC1B,sBAAsB;IACtB,MAAM,CAAC,MAAM,CAAqB;IAClC,kBAAkB;IAClB,MAAM,CAAC,MAAM,CAAqB;IAClC,mEAAmE;IACnE,MAAM,CAAC,WAAW,CAAqB;IACvC,yBAAyB;IACzB,MAAM,CAAC,eAAe,CAAqB;IAC3C,sCAAsC;IACtC,MAAM,CAAC,QAAQ,CAAqB;IACpC,kDAAkD;IAClD,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC;IAC9B,mCAAmC;IACnC,MAAM,CAAC,SAAS,CAAqB;IACrC,gDAAgD;IAChD,MAAM,CAAC,kBAAkB,CAAqB;IAEtC,MAAM,CAA8B;IAE5C,QAAQ,CAAC,GAAgB;QACrB,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEzC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YAC/B,MAAM,EAAE,iBAAiB,CAAC,MAAM,IAAI,EAAE;YACtC,MAAM,EAAE,iBAAiB,CAAC,MAAM,IAAI,EAAE;YACtC,WAAW,EAAE,iBAAiB,CAAC,WAAW;gBACtC,CAAC,CAAC;oBACI,WAAW,EAAE,iBAAiB,CAAC,WAAW;oBAC1C,eAAe,EAAE,iBAAiB,CAAC,eAAe,IAAI,EAAE;iBAC3D;gBACH,CAAC,CAAC,SAAS;YACf,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;YACpC,cAAc,EAAE,iBAAiB,CAAC,cAAc;YAChD,SAAS,EAAE,iBAAiB,CAAC,SAAS;YACtC,kBAAkB,EAAE,iBAAiB,CAAC,kBAAkB;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wild-framework/storage-s3",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": "Sphah",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/KhandaSoftware/wild-framework.git"
|
|
24
|
+
},
|
|
25
|
+
"description": "S3 (AWS) storage driver for Wild Framework's storage package.",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"wild",
|
|
28
|
+
"framework",
|
|
29
|
+
"storage",
|
|
30
|
+
"files",
|
|
31
|
+
"s3",
|
|
32
|
+
"aws",
|
|
33
|
+
"minio"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@aws-sdk/client-s3": "^3.700.0",
|
|
37
|
+
"@aws-sdk/s3-request-presigner": "^3.700.0",
|
|
38
|
+
"@wild-framework/container": "0.2.0",
|
|
39
|
+
"@wild-framework/storage": "0.2.0",
|
|
40
|
+
"@wild-framework/core": "0.2.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc",
|
|
44
|
+
"clean": "rm -rf dist",
|
|
45
|
+
"test": "vitest run"
|
|
46
|
+
}
|
|
6
47
|
}
|