@arcote.tech/arc-files 0.8.2 → 0.8.3
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/package.json +4 -4
- package/src/s3/s3-client.ts +30 -13
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-files",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Generic file upload fragment for Arc framework — S3 presigned upload + provider file_id binding",
|
|
7
7
|
"main": "./src/index.ts",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"type-check": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@arcote.tech/arc": "^0.8.
|
|
14
|
-
"@arcote.tech/arc-ds": "^0.8.
|
|
15
|
-
"@arcote.tech/platform": "^0.8.
|
|
13
|
+
"@arcote.tech/arc": "^0.8.3",
|
|
14
|
+
"@arcote.tech/arc-ds": "^0.8.3",
|
|
15
|
+
"@arcote.tech/platform": "^0.8.3",
|
|
16
16
|
"@aws-sdk/client-s3": "^3.658.0",
|
|
17
17
|
"@aws-sdk/s3-request-presigner": "^3.658.0",
|
|
18
18
|
"lucide-react": ">=0.400.0",
|
package/src/s3/s3-client.ts
CHANGED
|
@@ -14,9 +14,13 @@ import type { S3Config } from "../types";
|
|
|
14
14
|
* parsing 10 MB SDK. Pierwsze użycie ma ~100-200 ms overhead lazy load
|
|
15
15
|
* (acceptable dla async S3 operation).
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* KAŻDY `import("@aws-sdk/...")` MUSI być owinięty w `ONLY_SERVER ? … : null`
|
|
18
|
+
* (helpery #s3 / #presigner niżej). Sam `if (!ONLY_SERVER) throw` NIE
|
|
19
|
+
* wystarcza — bundler nie robi analizy przepływu, więc gołe `import(...)` w
|
|
20
|
+
* ciele metody zostaje w grafie i (bez splittingu w buildContextPackages)
|
|
21
|
+
* ląduje INLINE w dist/browser konsumenta. W NDT dało to ~840 KB AWS SDK +
|
|
22
|
+
* ~600 KB polyfilli node:crypto/stream w KAŻDYM wejściu. Z guardem `define
|
|
23
|
+
* ONLY_SERVER=false` składa martwą gałąź do `null` → aws-sdk znika z klienta.
|
|
20
24
|
*/
|
|
21
25
|
export class S3Bridge {
|
|
22
26
|
readonly bucket: string;
|
|
@@ -28,17 +32,30 @@ export class S3Bridge {
|
|
|
28
32
|
this.#config = config;
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
/** Guarded loader — na przeglądarce (ONLY_SERVER=false) cała gałąź importu
|
|
36
|
+
* jest martwa i wypada z bundla; na serwerze ładuje aws-sdk lazy. */
|
|
37
|
+
async #s3() {
|
|
38
|
+
const mod = ONLY_SERVER ? await import("@aws-sdk/client-s3") : null;
|
|
39
|
+
if (!mod) throw new Error("S3Bridge not available in browser context");
|
|
40
|
+
return mod;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async #presigner() {
|
|
44
|
+
const mod = ONLY_SERVER
|
|
45
|
+
? await import("@aws-sdk/s3-request-presigner")
|
|
46
|
+
: null;
|
|
47
|
+
if (!mod) throw new Error("S3Bridge not available in browser context");
|
|
48
|
+
return mod;
|
|
49
|
+
}
|
|
50
|
+
|
|
31
51
|
/**
|
|
32
52
|
* Lazy client construction. Pierwszy call odpala dynamic import aws-sdk
|
|
33
53
|
* + `new S3Client(...)`; kolejne calle reużywają cached Promise.
|
|
34
54
|
*/
|
|
35
55
|
async #client(): Promise<S3ClientLike> {
|
|
36
|
-
if (!ONLY_SERVER) {
|
|
37
|
-
throw new Error("S3Bridge not available in browser context");
|
|
38
|
-
}
|
|
39
56
|
if (!this.#clientPromise) {
|
|
40
57
|
this.#clientPromise = (async () => {
|
|
41
|
-
const { S3Client } = await
|
|
58
|
+
const { S3Client } = await this.#s3();
|
|
42
59
|
return new S3Client({
|
|
43
60
|
region: this.#config.region,
|
|
44
61
|
endpoint: this.#config.endpoint,
|
|
@@ -57,8 +74,8 @@ export class S3Bridge {
|
|
|
57
74
|
async presignUpload(key: string, mime: string, expiresIn = 300) {
|
|
58
75
|
const [client, { PutObjectCommand }, { getSignedUrl }] = await Promise.all([
|
|
59
76
|
this.#client(),
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
this.#s3(),
|
|
78
|
+
this.#presigner(),
|
|
62
79
|
]);
|
|
63
80
|
return getSignedUrl(
|
|
64
81
|
client as any,
|
|
@@ -74,8 +91,8 @@ export class S3Bridge {
|
|
|
74
91
|
async presignDownload(key: string, expiresIn = 3600) {
|
|
75
92
|
const [client, { GetObjectCommand }, { getSignedUrl }] = await Promise.all([
|
|
76
93
|
this.#client(),
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
this.#s3(),
|
|
95
|
+
this.#presigner(),
|
|
79
96
|
]);
|
|
80
97
|
return getSignedUrl(
|
|
81
98
|
client as any,
|
|
@@ -87,7 +104,7 @@ export class S3Bridge {
|
|
|
87
104
|
async downloadObject(key: string): Promise<Buffer> {
|
|
88
105
|
const [client, { GetObjectCommand }] = await Promise.all([
|
|
89
106
|
this.#client(),
|
|
90
|
-
|
|
107
|
+
this.#s3(),
|
|
91
108
|
]);
|
|
92
109
|
const out = await client.send(
|
|
93
110
|
new GetObjectCommand({ Bucket: this.bucket, Key: key }),
|
|
@@ -101,7 +118,7 @@ export class S3Bridge {
|
|
|
101
118
|
async deleteObject(key: string): Promise<void> {
|
|
102
119
|
const [client, { DeleteObjectCommand }] = await Promise.all([
|
|
103
120
|
this.#client(),
|
|
104
|
-
|
|
121
|
+
this.#s3(),
|
|
105
122
|
]);
|
|
106
123
|
await client.send(
|
|
107
124
|
new DeleteObjectCommand({ Bucket: this.bucket, Key: key }),
|