stratal 0.0.18 → 0.0.20
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 +8 -8
- package/dist/{base-email.provider-Cuw4OAB0.mjs → base-email.provider-CfQCA08m.mjs} +1 -1
- package/dist/{base-email.provider-Cuw4OAB0.mjs.map → base-email.provider-CfQCA08m.mjs.map} +1 -1
- package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
- package/dist/bin/quarry.mjs +26 -35
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +2 -153
- package/dist/cache/index.d.mts.map +1 -1
- package/dist/cache/index.mjs +4 -6
- package/dist/cache/index.mjs.map +1 -1
- package/dist/cache.service-DsnKuNyO.d.mts +156 -0
- package/dist/cache.service-DsnKuNyO.d.mts.map +1 -0
- package/dist/cache.tokens-B7Rw1C9Q.mjs +6 -0
- package/dist/cache.tokens-B7Rw1C9Q.mjs.map +1 -0
- package/dist/{colors-BTAnQRGU.mjs → colors-DJaRDXoS.mjs} +1 -1
- package/dist/{colors-BTAnQRGU.mjs.map → colors-DJaRDXoS.mjs.map} +1 -1
- package/dist/{command-DjGqCYHv.mjs → command-BgSlsS4M.mjs} +2 -2
- package/dist/{command-DjGqCYHv.mjs.map → command-BgSlsS4M.mjs.map} +1 -1
- package/dist/{command-B1YuV-UZ.d.mts → command-Bu-PjJrX.d.mts} +2 -2
- package/dist/{command-B1YuV-UZ.d.mts.map → command-Bu-PjJrX.d.mts.map} +1 -1
- package/dist/config/index.d.mts +81 -37
- package/dist/config/index.d.mts.map +1 -1
- package/dist/config/index.mjs +126 -45
- package/dist/config/index.mjs.map +1 -1
- package/dist/{consumer-registry-BkuHXR_u.d.mts → consumer-registry-B7yUNh0q.d.mts} +1 -1
- package/dist/{consumer-registry-BkuHXR_u.d.mts.map → consumer-registry-B7yUNh0q.d.mts.map} +1 -1
- package/dist/controller.decorator-DQzenvSN.mjs +66 -0
- package/dist/controller.decorator-DQzenvSN.mjs.map +1 -0
- package/dist/cron/index.d.mts +4 -3
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +1 -1
- package/dist/{cron-manager-1KnZvojs.mjs → cron-manager-7Symz_TE.mjs} +29 -19
- package/dist/cron-manager-7Symz_TE.mjs.map +1 -0
- package/dist/{cron-manager-BnEZquBL.d.mts → cron-manager-BEsH1mjW.d.mts} +27 -13
- package/dist/cron-manager-BEsH1mjW.d.mts.map +1 -0
- package/dist/di/index.d.mts +1 -1
- package/dist/di/index.mjs +2 -2
- package/dist/email/index.d.mts +3 -3
- package/dist/email/index.mjs +87 -10
- package/dist/email/index.mjs.map +1 -1
- package/dist/{en-3QnZwP-u.mjs → en-DSH_bhh6.mjs} +10 -30
- package/dist/en-DSH_bhh6.mjs.map +1 -0
- package/dist/env-D1rcZ8_r.d.mts +25 -0
- package/dist/env-D1rcZ8_r.d.mts.map +1 -0
- package/dist/errors/index.d.mts +1 -1
- package/dist/errors/index.mjs +1 -1
- package/dist/{errors--RBIvDXr.mjs → errors-BdyV5PnY.mjs} +180 -15
- package/dist/errors-BdyV5PnY.mjs.map +1 -0
- package/dist/{errors-B7hCnXgB.mjs → errors-Da3Pz2X7.mjs} +14 -7
- package/dist/errors-Da3Pz2X7.mjs.map +1 -0
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +1 -1
- package/dist/{events-UTJliZhl.mjs → events-COKixqnG.mjs} +2 -2
- package/dist/{events-UTJliZhl.mjs.map → events-COKixqnG.mjs.map} +1 -1
- package/dist/{gateway-context-BdBFoQd8.mjs → gateway-context-CdJjpUCW.mjs} +5 -70
- package/dist/gateway-context-CdJjpUCW.mjs.map +1 -0
- package/dist/guards/index.d.mts +14 -5
- package/dist/guards/index.d.mts.map +1 -1
- package/dist/guards/index.mjs +1 -1
- package/dist/{guards-MtDgcHnF.mjs → guards-DUk_Kzst.mjs} +1 -1
- package/dist/guards-DUk_Kzst.mjs.map +1 -0
- package/dist/http-method.decorator-DXwxAfb_.mjs +96 -0
- package/dist/http-method.decorator-DXwxAfb_.mjs.map +1 -0
- package/dist/i18n/index.d.mts +3 -3
- package/dist/i18n/index.mjs +2 -2
- package/dist/i18n/messages/en/index.d.mts +1 -1
- package/dist/i18n/messages/en/index.mjs +1 -1
- package/dist/i18n/utils/index.mjs +1 -1
- package/dist/i18n/validation/index.d.mts +2 -2
- package/dist/i18n/validation/index.mjs +2 -2
- package/dist/{i18n.module-BpLLLCTg.mjs → i18n.module-BBlNNlcG.mjs} +234 -204
- package/dist/i18n.module-BBlNNlcG.mjs.map +1 -0
- package/dist/index-7-hU3GTV.d.mts +101 -0
- package/dist/index-7-hU3GTV.d.mts.map +1 -0
- package/dist/{index-Dfpd_ypO.d.mts → index-Bnpfq6uk.d.mts} +81 -19
- package/dist/index-Bnpfq6uk.d.mts.map +1 -0
- package/dist/{index-BDh9J2KD.d.mts → index-C1KvMncZ.d.mts} +9 -29
- package/dist/{index-BDh9J2KD.d.mts.map → index-C1KvMncZ.d.mts.map} +1 -1
- package/dist/{index-DPxmo6AY.d.mts → index-CjaQ6_tZ.d.mts} +5 -4
- package/dist/index-CjaQ6_tZ.d.mts.map +1 -0
- package/dist/{index-BrmS34sa.d.mts → index-D0US0X14.d.mts} +375 -235
- package/dist/index-D0US0X14.d.mts.map +1 -0
- package/dist/{index-BR23zDMy.d.mts → index-DBd_2wv8.d.mts} +1 -1
- package/dist/{index-BR23zDMy.d.mts.map → index-DBd_2wv8.d.mts.map} +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{is-command-PvULqiTa.mjs → is-command-C6a7WTPw.mjs} +2 -2
- package/dist/{is-command-PvULqiTa.mjs.map → is-command-C6a7WTPw.mjs.map} +1 -1
- package/dist/{is-seeder-BN9Ej1r7.mjs → is-seeder-CebjZCDn.mjs} +1 -1
- package/dist/{is-seeder-BN9Ej1r7.mjs.map → is-seeder-CebjZCDn.mjs.map} +1 -1
- package/dist/logger/index.d.mts +1 -1
- package/dist/logger/index.mjs +1 -1
- package/dist/{logger-c0ftIK4G.mjs → logger-V6Ms3QnQ.mjs} +38 -20
- package/dist/{logger-c0ftIK4G.mjs.map → logger-V6Ms3QnQ.mjs.map} +1 -1
- package/dist/macroable/index.d.mts +2 -0
- package/dist/macroable/index.mjs +2 -0
- package/dist/macroable-BmufBshB.mjs +122 -0
- package/dist/macroable-BmufBshB.mjs.map +1 -0
- package/dist/module/index.d.mts +2 -2
- package/dist/module/index.mjs +1 -1
- package/dist/{module-C3YZ-kZN.mjs → module-Dk2qTa77.mjs} +160 -19
- package/dist/module-Dk2qTa77.mjs.map +1 -0
- package/dist/openapi/index.d.mts +3 -3
- package/dist/openapi/index.mjs +2 -2
- package/dist/{openapi-tools.service-B77QXD56.mjs → openapi-tools.service-Zs-Ewv7F.mjs} +4 -1
- package/dist/{openapi-tools.service-B77QXD56.mjs.map → openapi-tools.service-Zs-Ewv7F.mjs.map} +1 -1
- package/dist/{openapi.service-6yj0BUY4.d.mts → openapi.service-BLgvn3hJ.d.mts} +3 -3
- package/dist/{openapi.service-6yj0BUY4.d.mts.map → openapi.service-BLgvn3hJ.d.mts.map} +1 -1
- package/dist/quarry/index.d.mts +7 -7
- package/dist/quarry/index.d.mts.map +1 -1
- package/dist/quarry/index.mjs +4 -4
- package/dist/{quarry-registry-CQCIlYTO.mjs → quarry-registry-DNEej-Db.mjs} +17 -15
- package/dist/quarry-registry-DNEej-Db.mjs.map +1 -0
- package/dist/queue/index.d.mts +2 -2
- package/dist/queue/index.mjs +2 -2
- package/dist/{queue.module-DIjD6nr-.mjs → queue.module-BCdCiySt.mjs} +4 -4
- package/dist/{queue.module-DIjD6nr-.mjs.map → queue.module-BCdCiySt.mjs.map} +1 -1
- package/dist/r2-storage.provider-Co6F0ZYV.mjs +244 -0
- package/dist/r2-storage.provider-Co6F0ZYV.mjs.map +1 -0
- package/dist/rate-limit.decorator--o6Q6p9w.mjs +55 -0
- package/dist/rate-limit.decorator--o6Q6p9w.mjs.map +1 -0
- package/dist/rate-limiter/index.d.mts +420 -0
- package/dist/rate-limiter/index.d.mts.map +1 -0
- package/dist/rate-limiter/index.mjs +365 -0
- package/dist/rate-limiter/index.mjs.map +1 -0
- package/dist/{resend.provider-Bvw36rQy.mjs → resend.provider-M6qRLrcy.mjs} +2 -2
- package/dist/{resend.provider-Bvw36rQy.mjs.map → resend.provider-M6qRLrcy.mjs.map} +1 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +7 -5
- package/dist/seeder/index.d.mts +3 -3
- package/dist/seeder/index.mjs +2 -2
- package/dist/{seeder-D7VXULXB.mjs → seeder-CJAOHEIo.mjs} +5 -5
- package/dist/{seeder-D7VXULXB.mjs.map → seeder-CJAOHEIo.mjs.map} +1 -1
- package/dist/{setup-BRIN-iYT.mjs → setup-CefZKV_e.mjs} +1 -1
- package/dist/{setup-BRIN-iYT.mjs.map → setup-CefZKV_e.mjs.map} +1 -1
- package/dist/signed-url-BQPbv2In.mjs +74 -0
- package/dist/signed-url-BQPbv2In.mjs.map +1 -0
- package/dist/{smtp.provider-CAwpvzvD.mjs → smtp.provider-w0Ve52Xg.mjs} +2 -2
- package/dist/{smtp.provider-CAwpvzvD.mjs.map → smtp.provider-w0Ve52Xg.mjs.map} +1 -1
- package/dist/storage/index.d.mts +39 -17
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +3 -3
- package/dist/storage/providers/index.d.mts +30 -70
- package/dist/storage/providers/index.d.mts.map +1 -1
- package/dist/storage/providers/index.mjs +2 -2
- package/dist/{storage-CJ-QOwNv.mjs → storage-1zw-6Yiz.mjs} +101 -27
- package/dist/storage-1zw-6Yiz.mjs.map +1 -0
- package/dist/{storage-provider.interface-YRtyYBxV.d.mts → storage-provider.interface-Bd6vA4ak.d.mts} +20 -21
- package/dist/storage-provider.interface-Bd6vA4ak.d.mts.map +1 -0
- package/dist/{stratal-B7G4i9-N.mjs → stratal-DeEcGgdq.mjs} +57 -26
- package/dist/stratal-DeEcGgdq.mjs.map +1 -0
- package/dist/{types-CN0zONAZ.d.mts → types-cySNS_lp.d.mts} +1 -1
- package/dist/types-cySNS_lp.d.mts.map +1 -0
- package/dist/{usage-generator-Cl1HPlUp.mjs → usage-generator-BUdlhnCK.mjs} +2 -2
- package/dist/{usage-generator-Cl1HPlUp.mjs.map → usage-generator-BUdlhnCK.mjs.map} +1 -1
- package/dist/{validation-B4bePOa_.mjs → validation-DtJwAv7O.mjs} +62 -8
- package/dist/validation-DtJwAv7O.mjs.map +1 -0
- package/dist/websocket/index.d.mts +9 -4
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +1 -1
- package/dist/workers/index.d.mts +2 -1
- package/dist/workers/index.d.mts.map +1 -1
- package/dist/workers/index.mjs +2 -2
- package/package.json +32 -40
- package/dist/cron-manager-1KnZvojs.mjs.map +0 -1
- package/dist/cron-manager-BnEZquBL.d.mts.map +0 -1
- package/dist/en-3QnZwP-u.mjs.map +0 -1
- package/dist/errors--RBIvDXr.mjs.map +0 -1
- package/dist/errors-B7hCnXgB.mjs.map +0 -1
- package/dist/gateway-context-BdBFoQd8.mjs.map +0 -1
- package/dist/guards-MtDgcHnF.mjs.map +0 -1
- package/dist/i18n.module-BpLLLCTg.mjs.map +0 -1
- package/dist/index-BrmS34sa.d.mts.map +0 -1
- package/dist/index-DPxmo6AY.d.mts.map +0 -1
- package/dist/index-Dfpd_ypO.d.mts.map +0 -1
- package/dist/module-C3YZ-kZN.mjs.map +0 -1
- package/dist/quarry-registry-CQCIlYTO.mjs.map +0 -1
- package/dist/s3-storage.provider-BAhHDMI3.mjs +0 -343
- package/dist/s3-storage.provider-BAhHDMI3.mjs.map +0 -1
- package/dist/storage-CJ-QOwNv.mjs.map +0 -1
- package/dist/storage-provider.interface-YRtyYBxV.d.mts.map +0 -1
- package/dist/stratal-B7G4i9-N.mjs.map +0 -1
- package/dist/types-CN0zONAZ.d.mts.map +0 -1
- package/dist/validation-B4bePOa_.mjs.map +0 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//#region src/router/signed-url.ts
|
|
2
|
+
/**
|
|
3
|
+
* Import a signing key for HMAC-SHA256.
|
|
4
|
+
*/
|
|
5
|
+
async function importKey(secret) {
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
return crypto.subtle.importKey("raw", encoder.encode(secret), {
|
|
8
|
+
name: "HMAC",
|
|
9
|
+
hash: "SHA-256"
|
|
10
|
+
}, false, ["sign", "verify"]);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Encode an ArrayBuffer as base64url (URL-safe base64).
|
|
14
|
+
*/
|
|
15
|
+
function toBase64Url(buffer) {
|
|
16
|
+
const bytes = new Uint8Array(buffer);
|
|
17
|
+
let binary = "";
|
|
18
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
19
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Sign a URL with HMAC-SHA256.
|
|
23
|
+
*
|
|
24
|
+
* Appends `signature` and optionally `expires` query parameters.
|
|
25
|
+
* The signature covers the pathname + search (excluding the signature params themselves).
|
|
26
|
+
*
|
|
27
|
+
* @param url - Full URL or path to sign
|
|
28
|
+
* @param secret - HMAC secret key (e.g., from env.APP_SECRET)
|
|
29
|
+
* @param options - Optional expiration
|
|
30
|
+
* @returns URL string with `signature` (and `expires`) query params appended
|
|
31
|
+
*/
|
|
32
|
+
async function signUrl(url, secret, options) {
|
|
33
|
+
const parsedUrl = new URL(url, "https://placeholder.local");
|
|
34
|
+
const key = await importKey(secret);
|
|
35
|
+
if (options?.expiresIn) {
|
|
36
|
+
const expires = Math.floor(Date.now() / 1e3) + options.expiresIn;
|
|
37
|
+
parsedUrl.searchParams.set("expires", String(expires));
|
|
38
|
+
}
|
|
39
|
+
const dataToSign = `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`;
|
|
40
|
+
const encoder = new TextEncoder();
|
|
41
|
+
const signature = toBase64Url(await crypto.subtle.sign("HMAC", key, encoder.encode(dataToSign)));
|
|
42
|
+
parsedUrl.searchParams.set("signature", signature);
|
|
43
|
+
return url.startsWith("http") ? parsedUrl.toString() : `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Verify a signed URL using `crypto.subtle.verify()` (timing-attack-safe).
|
|
47
|
+
*
|
|
48
|
+
* @param url - Full URL or path with signature query param
|
|
49
|
+
* @param secret - HMAC secret key (same key used for signing)
|
|
50
|
+
* @returns true if signature is valid and not expired
|
|
51
|
+
*/
|
|
52
|
+
async function verifySignedUrl(url, secret) {
|
|
53
|
+
const parsedUrl = new URL(url, "https://placeholder.local");
|
|
54
|
+
const signature = parsedUrl.searchParams.get("signature");
|
|
55
|
+
if (!signature) return false;
|
|
56
|
+
const expires = parsedUrl.searchParams.get("expires");
|
|
57
|
+
if (expires) {
|
|
58
|
+
const expiryTime = parseInt(expires, 10);
|
|
59
|
+
if (isNaN(expiryTime) || Math.floor(Date.now() / 1e3) > expiryTime) return false;
|
|
60
|
+
}
|
|
61
|
+
parsedUrl.searchParams.delete("signature");
|
|
62
|
+
const dataToVerify = `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`;
|
|
63
|
+
const base64 = signature.replace(/-/g, "+").replace(/_/g, "/");
|
|
64
|
+
const binaryStr = atob(base64);
|
|
65
|
+
const signatureBytes = new Uint8Array(binaryStr.length);
|
|
66
|
+
for (let i = 0; i < binaryStr.length; i++) signatureBytes[i] = binaryStr.charCodeAt(i);
|
|
67
|
+
const key = await importKey(secret);
|
|
68
|
+
const encoder = new TextEncoder();
|
|
69
|
+
return crypto.subtle.verify("HMAC", key, signatureBytes, encoder.encode(dataToVerify));
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { verifySignedUrl as n, signUrl as t };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=signed-url-BQPbv2In.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-url-BQPbv2In.mjs","names":[],"sources":["../src/router/signed-url.ts"],"sourcesContent":["/**\n * Signed URL utilities using HMAC-SHA256 via Web Crypto API.\n *\n * Follows the Cloudflare Workers signing pattern:\n * https://developers.cloudflare.com/workers/examples/signing-requests/\n *\n * Uses `crypto.subtle.verify()` for timing-attack-safe comparison.\n */\n\n/**\n * Options for signing a URL.\n */\nexport interface SignedUrlOptions {\n /** Time-to-live in seconds. URL expires after this duration. */\n expiresIn?: number\n}\n\n/**\n * Import a signing key for HMAC-SHA256.\n */\nasync function importKey(secret: string): Promise<CryptoKey> {\n const encoder = new TextEncoder()\n return crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify']\n )\n}\n\n/**\n * Encode an ArrayBuffer as base64url (URL-safe base64).\n */\nfunction toBase64Url(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = ''\n for (const byte of bytes) {\n binary += String.fromCharCode(byte)\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * Sign a URL with HMAC-SHA256.\n *\n * Appends `signature` and optionally `expires` query parameters.\n * The signature covers the pathname + search (excluding the signature params themselves).\n *\n * @param url - Full URL or path to sign\n * @param secret - HMAC secret key (e.g., from env.APP_SECRET)\n * @param options - Optional expiration\n * @returns URL string with `signature` (and `expires`) query params appended\n */\nexport async function signUrl(url: string, secret: string, options?: SignedUrlOptions): Promise<string> {\n const parsedUrl = new URL(url, 'https://placeholder.local')\n const key = await importKey(secret)\n\n // Add expiry if specified\n if (options?.expiresIn) {\n const expires = Math.floor(Date.now() / 1000) + options.expiresIn\n parsedUrl.searchParams.set('expires', String(expires))\n }\n\n // Sign: pathname + sorted search params (without signature)\n const dataToSign = `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`\n const encoder = new TextEncoder()\n const signatureBuffer = await crypto.subtle.sign('HMAC', key, encoder.encode(dataToSign))\n const signature = toBase64Url(signatureBuffer)\n\n parsedUrl.searchParams.set('signature', signature)\n // Return just the path + query for relative URLs, full URL for absolute\n return url.startsWith('http') ? parsedUrl.toString() : `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`\n}\n\n/**\n * Verify a signed URL using `crypto.subtle.verify()` (timing-attack-safe).\n *\n * @param url - Full URL or path with signature query param\n * @param secret - HMAC secret key (same key used for signing)\n * @returns true if signature is valid and not expired\n */\nexport async function verifySignedUrl(url: string, secret: string): Promise<boolean> {\n const parsedUrl = new URL(url, 'https://placeholder.local')\n const signature = parsedUrl.searchParams.get('signature')\n if (!signature) return false\n\n // Check expiry\n const expires = parsedUrl.searchParams.get('expires')\n if (expires) {\n const expiryTime = parseInt(expires, 10)\n if (isNaN(expiryTime) || Math.floor(Date.now() / 1000) > expiryTime) {\n return false\n }\n }\n\n // Reconstruct the data that was signed (without signature param)\n parsedUrl.searchParams.delete('signature')\n const dataToVerify = `${parsedUrl.pathname}?${parsedUrl.searchParams.toString()}`\n\n // Decode base64url signature\n const base64 = signature.replace(/-/g, '+').replace(/_/g, '/')\n const binaryStr = atob(base64)\n const signatureBytes = new Uint8Array(binaryStr.length)\n for (let i = 0; i < binaryStr.length; i++) {\n signatureBytes[i] = binaryStr.charCodeAt(i)\n }\n\n const key = await importKey(secret)\n const encoder = new TextEncoder()\n\n // Use crypto.subtle.verify() for timing-attack-safe comparison\n return crypto.subtle.verify('HMAC', key, signatureBytes, encoder.encode(dataToVerify))\n}\n"],"mappings":";;;;AAoBA,eAAe,UAAU,QAAoC;CAC3D,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,OAAO,OAAO,UACnB,OACA,QAAQ,OAAO,OAAO,EACtB;EAAE,MAAM;EAAQ,MAAM;EAAW,EACjC,OACA,CAAC,QAAQ,SAAS,CACnB;;;;;AAMH,SAAS,YAAY,QAA6B;CAChD,MAAM,QAAQ,IAAI,WAAW,OAAO;CACpC,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,MACjB,WAAU,OAAO,aAAa,KAAK;AAErC,QAAO,KAAK,OAAO,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG;;;;;;;;;;;;;AAchF,eAAsB,QAAQ,KAAa,QAAgB,SAA6C;CACtG,MAAM,YAAY,IAAI,IAAI,KAAK,4BAA4B;CAC3D,MAAM,MAAM,MAAM,UAAU,OAAO;AAGnC,KAAI,SAAS,WAAW;EACtB,MAAM,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG,QAAQ;AACxD,YAAU,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC;;CAIxD,MAAM,aAAa,GAAG,UAAU,SAAS,GAAG,UAAU,aAAa,UAAU;CAC7E,MAAM,UAAU,IAAI,aAAa;CAEjC,MAAM,YAAY,YAAY,MADA,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,WAAW,CAAC,CAC3C;AAE9C,WAAU,aAAa,IAAI,aAAa,UAAU;AAElD,QAAO,IAAI,WAAW,OAAO,GAAG,UAAU,UAAU,GAAG,GAAG,UAAU,SAAS,GAAG,UAAU,aAAa,UAAU;;;;;;;;;AAUnH,eAAsB,gBAAgB,KAAa,QAAkC;CACnF,MAAM,YAAY,IAAI,IAAI,KAAK,4BAA4B;CAC3D,MAAM,YAAY,UAAU,aAAa,IAAI,YAAY;AACzD,KAAI,CAAC,UAAW,QAAO;CAGvB,MAAM,UAAU,UAAU,aAAa,IAAI,UAAU;AACrD,KAAI,SAAS;EACX,MAAM,aAAa,SAAS,SAAS,GAAG;AACxC,MAAI,MAAM,WAAW,IAAI,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG,WACvD,QAAO;;AAKX,WAAU,aAAa,OAAO,YAAY;CAC1C,MAAM,eAAe,GAAG,UAAU,SAAS,GAAG,UAAU,aAAa,UAAU;CAG/E,MAAM,SAAS,UAAU,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;CAC9D,MAAM,YAAY,KAAK,OAAO;CAC9B,MAAM,iBAAiB,IAAI,WAAW,UAAU,OAAO;AACvD,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,IACpC,gBAAe,KAAK,UAAU,WAAW,EAAE;CAG7C,MAAM,MAAM,MAAM,UAAU,OAAO;CACnC,MAAM,UAAU,IAAI,aAAa;AAGjC,QAAO,OAAO,OAAO,OAAO,QAAQ,KAAK,gBAAgB,QAAQ,OAAO,aAAa,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EmailSmtpConnectionFailedError, SmtpConfigurationMissingError, SmtpHostMissingError } from "./email/index.mjs";
|
|
2
|
-
import { t as BaseEmailProvider } from "./base-email.provider-
|
|
2
|
+
import { t as BaseEmailProvider } from "./base-email.provider-CfQCA08m.mjs";
|
|
3
3
|
import * as nodemailer from "nodemailer";
|
|
4
4
|
import { Readable } from "stream";
|
|
5
5
|
//#region src/email/providers/smtp.provider.ts
|
|
@@ -72,4 +72,4 @@ var SmtpProvider = class extends BaseEmailProvider {
|
|
|
72
72
|
//#endregion
|
|
73
73
|
export { SmtpProvider };
|
|
74
74
|
|
|
75
|
-
//# sourceMappingURL=smtp.provider-
|
|
75
|
+
//# sourceMappingURL=smtp.provider-w0Ve52Xg.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smtp.provider-
|
|
1
|
+
{"version":3,"file":"smtp.provider-w0Ve52Xg.mjs","names":[],"sources":["../src/email/providers/smtp.provider.ts"],"sourcesContent":["import type { Transporter } from 'nodemailer'\nimport * as nodemailer from 'nodemailer'\nimport type SMTPTransport from 'nodemailer/lib/smtp-transport'\nimport { Readable } from 'stream'\nimport type { ResolvedEmailAttachment, ResolvedEmailMessage } from '../contracts'\nimport type { EmailModuleOptions } from '../email.module'\nimport { EmailSmtpConnectionFailedError, SmtpConfigurationMissingError, SmtpHostMissingError } from '../errors'\nimport { BaseEmailProvider } from './base-email.provider'\nimport type { EmailSendResult } from './email-provider.interface'\n\n/**\n * SMTP Email Provider\n *\n * Implementation of IEmailProvider using SMTP/nodemailer\n * Supports any SMTP server configured via SMTP_URL\n */\nexport class SmtpProvider extends BaseEmailProvider {\n private readonly transporter: Transporter<SMTPTransport.SentMessageInfo>\n private readonly defaultFrom: { name: string; email: string }\n\n constructor(\n private readonly options: EmailModuleOptions\n ) {\n super()\n\n // Validate SMTP configuration\n if (!this.options.smtp) {\n throw new SmtpConfigurationMissingError()\n }\n\n if (!this.options.smtp.host) {\n throw new SmtpHostMissingError()\n }\n\n // Create nodemailer transporter\n this.transporter = nodemailer.createTransport({\n host: this.options.smtp.host,\n port: this.options.smtp.port,\n secure: this.options.smtp.secure,\n auth: this.options.smtp.username && this.options.smtp.password\n ? {\n user: this.options.smtp.username,\n pass: this.options.smtp.password,\n }\n : undefined,\n })\n\n this.defaultFrom = this.options.from\n }\n\n async send(message: ResolvedEmailMessage): Promise<EmailSendResult> {\n try {\n const from = message.from\n ? `${message.from.name} <${message.from.email}>`\n : `${this.defaultFrom.name} <${this.defaultFrom.email}>`\n\n const info = await this.transporter.sendMail({\n from,\n to: Array.isArray(message.to) ? message.to.join(', ') : message.to,\n subject: message.subject,\n html: message.html,\n text: message.text,\n replyTo: message.replyTo,\n cc: message.cc?.join(', '),\n bcc: message.bcc?.join(', '),\n attachments: message.attachments?.map(attachment => ({\n filename: attachment.filename,\n content: this.toNodeStream(attachment.content),\n contentType: attachment.contentType,\n })),\n })\n\n return {\n messageId: info.messageId,\n accepted: true,\n metadata: {\n provider: 'smtp',\n response: info.response,\n },\n }\n } catch {\n throw new EmailSmtpConnectionFailedError(\n this.options.smtp?.host ?? '',\n this.options.smtp?.port ?? 587\n )\n }\n }\n\n /**\n * Convert attachment content to Node.js stream format\n *\n * Nodemailer expects Node.js Readable streams, not web ReadableStream.\n * Buffer is passed through as-is since nodemailer supports it directly.\n */\n private toNodeStream(content: ResolvedEmailAttachment['content']): Buffer | Readable {\n if (Buffer.isBuffer(content)) {\n return content\n }\n // Convert web ReadableStream to Node.js Readable\n return Readable.fromWeb(content as unknown as Parameters<typeof Readable.fromWeb>[0])\n }\n}\n"],"mappings":";;;;;;;;;;;AAgBA,IAAa,eAAb,cAAkC,kBAAkB;CAClD;CACA;CAEA,YACE,SACA;AACA,SAAO;AAFU,OAAA,UAAA;AAKjB,MAAI,CAAC,KAAK,QAAQ,KAChB,OAAM,IAAI,+BAA+B;AAG3C,MAAI,CAAC,KAAK,QAAQ,KAAK,KACrB,OAAM,IAAI,sBAAsB;AAIlC,OAAK,cAAc,WAAW,gBAAgB;GAC5C,MAAM,KAAK,QAAQ,KAAK;GACxB,MAAM,KAAK,QAAQ,KAAK;GACxB,QAAQ,KAAK,QAAQ,KAAK;GAC1B,MAAM,KAAK,QAAQ,KAAK,YAAY,KAAK,QAAQ,KAAK,WAClD;IACA,MAAM,KAAK,QAAQ,KAAK;IACxB,MAAM,KAAK,QAAQ,KAAK;IACzB,GACC,KAAA;GACL,CAAC;AAEF,OAAK,cAAc,KAAK,QAAQ;;CAGlC,MAAM,KAAK,SAAyD;AAClE,MAAI;GACF,MAAM,OAAO,QAAQ,OACjB,GAAG,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,KAC5C,GAAG,KAAK,YAAY,KAAK,IAAI,KAAK,YAAY,MAAM;GAExD,MAAM,OAAO,MAAM,KAAK,YAAY,SAAS;IAC3C;IACA,IAAI,MAAM,QAAQ,QAAQ,GAAG,GAAG,QAAQ,GAAG,KAAK,KAAK,GAAG,QAAQ;IAChE,SAAS,QAAQ;IACjB,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,SAAS,QAAQ;IACjB,IAAI,QAAQ,IAAI,KAAK,KAAK;IAC1B,KAAK,QAAQ,KAAK,KAAK,KAAK;IAC5B,aAAa,QAAQ,aAAa,KAAI,gBAAe;KACnD,UAAU,WAAW;KACrB,SAAS,KAAK,aAAa,WAAW,QAAQ;KAC9C,aAAa,WAAW;KACzB,EAAE;IACJ,CAAC;AAEF,UAAO;IACL,WAAW,KAAK;IAChB,UAAU;IACV,UAAU;KACR,UAAU;KACV,UAAU,KAAK;KAChB;IACF;UACK;AACN,SAAM,IAAI,+BACR,KAAK,QAAQ,MAAM,QAAQ,IAC3B,KAAK,QAAQ,MAAM,QAAQ,IAC5B;;;;;;;;;CAUL,aAAqB,SAAgE;AACnF,MAAI,OAAO,SAAS,QAAQ,CAC1B,QAAO;AAGT,SAAO,SAAS,QAAQ,QAA6D"}
|
package/dist/storage/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { d as ApplicationError,
|
|
2
|
-
import {
|
|
1
|
+
import { V as RouterContext, d as ApplicationError, gn as AsyncModuleOptions, vn as DynamicModule } from "../index-D0US0X14.mjs";
|
|
2
|
+
import { t as StratalEnv } from "../env-D1rcZ8_r.mjs";
|
|
3
|
+
import { _ as StorageEntry, a as uploadResultSchema, c as getPresignedUrlInputSchema, d as fileExistsInputSchema, f as DownloadResult, g as StorageConfig, h as PresignedUrlConfig, i as UploadResult, l as presignedUrlResultSchema, m as deleteFileInputSchema, n as StreamingBlobPayloadInputTypes, o as GetPresignedUrlInput, p as DeleteFileInput, r as UploadOptions, s as PresignedUrlResult, t as IStorageProvider, u as FileExistsInput, v as StorageRouteConfig } from "../storage-provider.interface-Bd6vA4ak.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/storage/storage.module.d.ts
|
|
5
6
|
/**
|
|
@@ -11,13 +12,10 @@ declare class StorageModule {
|
|
|
11
12
|
/**
|
|
12
13
|
* Configure StorageModule with static options
|
|
13
14
|
*
|
|
14
|
-
* @param options - Storage configuration options
|
|
15
|
-
* @returns Dynamic module with storage infrastructure
|
|
16
|
-
*
|
|
17
15
|
* @example
|
|
18
16
|
* ```typescript
|
|
19
17
|
* StorageModule.forRoot({
|
|
20
|
-
* storage: [{ disk: 'uploads',
|
|
18
|
+
* storage: [{ disk: 'uploads', binding: 'MY_BUCKET', root: 'uploads' }],
|
|
21
19
|
* defaultStorageDisk: 'uploads',
|
|
22
20
|
* presignedUrl: { defaultExpiry: 3600, maxExpiry: 86400 }
|
|
23
21
|
* })
|
|
@@ -29,9 +27,6 @@ declare class StorageModule {
|
|
|
29
27
|
*
|
|
30
28
|
* Use when configuration depends on other services.
|
|
31
29
|
*
|
|
32
|
-
* @param options - Async configuration with factory and inject tokens
|
|
33
|
-
* @returns Dynamic module with storage infrastructure
|
|
34
|
-
*
|
|
35
30
|
* @example
|
|
36
31
|
* ```typescript
|
|
37
32
|
* StorageModule.forRootAsync({
|
|
@@ -62,14 +57,15 @@ declare const STORAGE_TOKENS: {
|
|
|
62
57
|
/**
|
|
63
58
|
* Storage Manager Service
|
|
64
59
|
* Manages multiple storage providers (one per disk)
|
|
65
|
-
* Handles lazy initialization and caching of
|
|
60
|
+
* Handles lazy initialization and caching of R2 providers
|
|
66
61
|
*/
|
|
67
62
|
declare class StorageManagerService {
|
|
68
63
|
private readonly options;
|
|
64
|
+
private readonly env;
|
|
69
65
|
private readonly providers;
|
|
70
66
|
private readonly creationPromises;
|
|
71
67
|
private readonly diskConfigs;
|
|
72
|
-
constructor(options: StorageConfig);
|
|
68
|
+
constructor(options: StorageConfig, env: StratalEnv);
|
|
73
69
|
/**
|
|
74
70
|
* Initialize disk configurations from options
|
|
75
71
|
*/
|
|
@@ -82,8 +78,8 @@ declare class StorageManagerService {
|
|
|
82
78
|
*/
|
|
83
79
|
getProvider(diskName: string): Promise<IStorageProvider>;
|
|
84
80
|
/**
|
|
85
|
-
* Create
|
|
86
|
-
* Dynamically imports
|
|
81
|
+
* Create an R2 provider instance
|
|
82
|
+
* Dynamically imports R2StorageProvider to support code splitting
|
|
87
83
|
* @param config - Storage entry configuration
|
|
88
84
|
* @returns Storage provider instance
|
|
89
85
|
*/
|
|
@@ -240,6 +236,27 @@ declare class StorageService {
|
|
|
240
236
|
}, disk?: string): Promise<UploadResult>;
|
|
241
237
|
}
|
|
242
238
|
//#endregion
|
|
239
|
+
//#region src/storage/controllers/storage.controller.d.ts
|
|
240
|
+
/**
|
|
241
|
+
* Storage Controller
|
|
242
|
+
*
|
|
243
|
+
* Auto-registered controller that proxies R2 operations behind signed URLs.
|
|
244
|
+
* Signature verification is applied via VerifySignatureMiddleware on the module's
|
|
245
|
+
* configureRoutes() method.
|
|
246
|
+
*
|
|
247
|
+
* Routes:
|
|
248
|
+
* - GET /storage/:disk/* → download file
|
|
249
|
+
* - PUT /storage/:disk/* → upload file
|
|
250
|
+
* - DELETE /storage/:disk/* → delete file
|
|
251
|
+
*/
|
|
252
|
+
declare class StorageController {
|
|
253
|
+
private readonly storage;
|
|
254
|
+
constructor(storage: StorageService);
|
|
255
|
+
download(ctx: RouterContext): Promise<Response>;
|
|
256
|
+
upload(ctx: RouterContext): Promise<Response>;
|
|
257
|
+
destroy(ctx: RouterContext): Promise<Response>;
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
243
260
|
//#region src/storage/errors/disk-not-configured.error.d.ts
|
|
244
261
|
declare class DiskNotConfiguredError extends ApplicationError {
|
|
245
262
|
constructor(disk: string);
|
|
@@ -270,9 +287,14 @@ declare class PresignedUrlInvalidExpiryError extends ApplicationError {
|
|
|
270
287
|
constructor(expiresIn: number, min: number, max: number);
|
|
271
288
|
}
|
|
272
289
|
//#endregion
|
|
273
|
-
//#region src/storage/errors/
|
|
274
|
-
declare class
|
|
275
|
-
constructor(
|
|
290
|
+
//#region src/storage/errors/r2-binding-not-found.error.d.ts
|
|
291
|
+
declare class R2BindingNotFoundError extends ApplicationError {
|
|
292
|
+
constructor(binding: string);
|
|
293
|
+
}
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region src/storage/errors/r2-presigned-url-secret-missing.error.d.ts
|
|
296
|
+
declare class R2PresignedUrlSecretMissingError extends ApplicationError {
|
|
297
|
+
constructor();
|
|
276
298
|
}
|
|
277
299
|
//#endregion
|
|
278
300
|
//#region src/storage/errors/storage-response-body-missing.error.d.ts
|
|
@@ -280,5 +302,5 @@ declare class StorageResponseBodyMissingError extends ApplicationError {
|
|
|
280
302
|
constructor(path: string);
|
|
281
303
|
}
|
|
282
304
|
//#endregion
|
|
283
|
-
export { DeleteFileInput, DiskNotConfiguredError, DownloadResult, FileExistsInput, FileNotFoundError, FileTooLargeError, GetPresignedUrlInput, type IStorageProvider, InvalidDiskError, InvalidFileTypeError, type PresignedUrlConfig, PresignedUrlInvalidExpiryError, PresignedUrlResult, STORAGE_TOKENS, type StorageConfig, type StorageEntry, StorageManagerService, StorageModule,
|
|
305
|
+
export { DeleteFileInput, DiskNotConfiguredError, DownloadResult, FileExistsInput, FileNotFoundError, FileTooLargeError, GetPresignedUrlInput, type IStorageProvider, InvalidDiskError, InvalidFileTypeError, type PresignedUrlConfig, PresignedUrlInvalidExpiryError, PresignedUrlResult, R2BindingNotFoundError, R2PresignedUrlSecretMissingError, STORAGE_TOKENS, type StorageConfig, StorageController, type StorageEntry, StorageManagerService, StorageModule, StorageResponseBodyMissingError, type StorageRouteConfig, StorageService, type StreamingBlobPayloadInputTypes, UploadOptions, UploadResult, deleteFileInputSchema, fileExistsInputSchema, getPresignedUrlInputSchema, presignedUrlResultSchema, uploadResultSchema };
|
|
284
306
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/storage/storage.module.ts","../../src/storage/storage.tokens.ts","../../src/storage/services/storage-manager.service.ts","../../src/storage/services/storage.service.ts","../../src/storage/errors/disk-not-configured.error.ts","../../src/storage/errors/file-not-found.error.ts","../../src/storage/errors/file-too-large.error.ts","../../src/storage/errors/invalid-disk.error.ts","../../src/storage/errors/invalid-file-type.error.ts","../../src/storage/errors/presigned-url-invalid-expiry.error.ts","../../src/storage/errors/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/storage/storage.module.ts","../../src/storage/storage.tokens.ts","../../src/storage/services/storage-manager.service.ts","../../src/storage/services/storage.service.ts","../../src/storage/controllers/storage.controller.ts","../../src/storage/errors/disk-not-configured.error.ts","../../src/storage/errors/file-not-found.error.ts","../../src/storage/errors/file-too-large.error.ts","../../src/storage/errors/invalid-disk.error.ts","../../src/storage/errors/invalid-file-type.error.ts","../../src/storage/errors/presigned-url-invalid-expiry.error.ts","../../src/storage/errors/r2-binding-not-found.error.ts","../../src/storage/errors/r2-presigned-url-secret-missing.error.ts","../../src/storage/errors/storage-response-body-missing.error.ts"],"mappings":"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"}
|
package/dist/storage/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as deleteFileInputSchema, c as
|
|
3
|
-
export { DiskNotConfiguredError, FileNotFoundError, FileTooLargeError, InvalidDiskError, InvalidFileTypeError, PresignedUrlInvalidExpiryError, STORAGE_TOKENS, StorageManagerService, StorageModule,
|
|
1
|
+
import { a as InvalidFileTypeError, c as FileNotFoundError, i as PresignedUrlInvalidExpiryError, l as DiskNotConfiguredError, n as R2PresignedUrlSecretMissingError, o as InvalidDiskError, r as R2BindingNotFoundError, s as FileTooLargeError, t as StorageResponseBodyMissingError } from "../errors-Da3Pz2X7.mjs";
|
|
2
|
+
import { a as deleteFileInputSchema, c as StorageService, i as fileExistsInputSchema, l as StorageManagerService, n as getPresignedUrlInputSchema, o as StorageController, r as presignedUrlResultSchema, s as StorageModule, t as uploadResultSchema, u as STORAGE_TOKENS } from "../storage-1zw-6Yiz.mjs";
|
|
3
|
+
export { DiskNotConfiguredError, FileNotFoundError, FileTooLargeError, InvalidDiskError, InvalidFileTypeError, PresignedUrlInvalidExpiryError, R2BindingNotFoundError, R2PresignedUrlSecretMissingError, STORAGE_TOKENS, StorageController, StorageManagerService, StorageModule, StorageResponseBodyMissingError, StorageService, deleteFileInputSchema, fileExistsInputSchema, getPresignedUrlInputSchema, presignedUrlResultSchema, uploadResultSchema };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as StratalEnv } from "../../env-D1rcZ8_r.mjs";
|
|
2
|
+
import { _ as StorageEntry, f as DownloadResult, i as UploadResult, n as StreamingBlobPayloadInputTypes, r as UploadOptions, s as PresignedUrlResult, t as IStorageProvider, v as StorageRouteConfig } from "../../storage-provider.interface-Bd6vA4ak.mjs";
|
|
2
3
|
|
|
3
|
-
//#region src/storage/providers/
|
|
4
|
+
//#region src/storage/providers/multipart-provider.interface.d.ts
|
|
4
5
|
/**
|
|
5
6
|
* Options for creating a multipart upload
|
|
6
7
|
*/
|
|
@@ -9,16 +10,14 @@ interface CreateMultipartOptions {
|
|
|
9
10
|
contentType?: string;
|
|
10
11
|
/** Cache control header */
|
|
11
12
|
cacheControl?: string;
|
|
12
|
-
/** Custom
|
|
13
|
+
/** Custom metadata */
|
|
13
14
|
metadata?: Record<string, string>;
|
|
14
|
-
/** S3 object tagging (key=value format) */
|
|
15
|
-
tagging?: string;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
17
|
* Result of creating a multipart upload
|
|
19
18
|
*/
|
|
20
19
|
interface CreateMultipartResult {
|
|
21
|
-
/**
|
|
20
|
+
/** Upload ID for subsequent part uploads */
|
|
22
21
|
uploadId: string;
|
|
23
22
|
/** Object key */
|
|
24
23
|
key: string;
|
|
@@ -27,7 +26,7 @@ interface CreateMultipartResult {
|
|
|
27
26
|
* Result of uploading a part
|
|
28
27
|
*/
|
|
29
28
|
interface UploadPartResult {
|
|
30
|
-
/** ETag returned by
|
|
29
|
+
/** ETag returned by the storage provider */
|
|
31
30
|
etag: string;
|
|
32
31
|
/** Part number */
|
|
33
32
|
partNumber: number;
|
|
@@ -45,7 +44,7 @@ interface CompletedPart {
|
|
|
45
44
|
* Result of completing a multipart upload
|
|
46
45
|
*/
|
|
47
46
|
interface CompleteMultipartResult {
|
|
48
|
-
/**
|
|
47
|
+
/** Location URL */
|
|
49
48
|
location?: string;
|
|
50
49
|
/** Object key */
|
|
51
50
|
key: string;
|
|
@@ -121,13 +120,12 @@ interface DeleteObjectsResult {
|
|
|
121
120
|
}[];
|
|
122
121
|
}
|
|
123
122
|
/**
|
|
124
|
-
*
|
|
123
|
+
* Storage provider interface with multipart upload support
|
|
125
124
|
*
|
|
126
|
-
* Extends the generic IStorageProvider with
|
|
127
|
-
*
|
|
128
|
-
* their own resumable upload interfaces if needed.
|
|
125
|
+
* Extends the generic IStorageProvider with multipart upload operations
|
|
126
|
+
* needed by resumable upload protocols like TUS.
|
|
129
127
|
*/
|
|
130
|
-
interface
|
|
128
|
+
interface IMultipartProvider extends IStorageProvider {
|
|
131
129
|
/**
|
|
132
130
|
* Create a multipart upload
|
|
133
131
|
* @param key - Object key
|
|
@@ -160,6 +158,7 @@ interface IS3MultipartProvider extends IStorageProvider {
|
|
|
160
158
|
abortMultipartUpload(key: string, uploadId: string): Promise<void>;
|
|
161
159
|
/**
|
|
162
160
|
* List parts of a multipart upload
|
|
161
|
+
* Requires s3Compat configuration on the storage entry
|
|
163
162
|
* @param key - Object key
|
|
164
163
|
* @param uploadId - Upload ID
|
|
165
164
|
* @param partNumberMarker - Optional marker for pagination
|
|
@@ -168,6 +167,7 @@ interface IS3MultipartProvider extends IStorageProvider {
|
|
|
168
167
|
listParts(key: string, uploadId: string, partNumberMarker?: string): Promise<ListPartsResult>;
|
|
169
168
|
/**
|
|
170
169
|
* List all in-progress multipart uploads
|
|
170
|
+
* Requires s3Compat configuration on the storage entry
|
|
171
171
|
* @param keyMarker - Optional key marker for pagination
|
|
172
172
|
* @param uploadIdMarker - Optional upload ID marker for pagination
|
|
173
173
|
* @returns List of uploads
|
|
@@ -188,86 +188,46 @@ interface IS3MultipartProvider extends IStorageProvider {
|
|
|
188
188
|
*/
|
|
189
189
|
deleteObjects(keys: string[]): Promise<DeleteObjectsResult>;
|
|
190
190
|
/**
|
|
191
|
-
* Get the bucket name
|
|
192
|
-
* @returns Bucket name from configuration
|
|
191
|
+
* Get the bucket/binding name
|
|
192
|
+
* @returns Bucket or binding name from configuration
|
|
193
193
|
*/
|
|
194
194
|
getBucket(): string;
|
|
195
195
|
}
|
|
196
196
|
//#endregion
|
|
197
|
-
//#region src/storage/providers/
|
|
197
|
+
//#region src/storage/providers/r2-storage.provider.d.ts
|
|
198
198
|
/**
|
|
199
|
-
*
|
|
200
|
-
* Implements storage operations using
|
|
201
|
-
* Works with AWS S3, Cloudflare R2, MinIO, and other S3-compatible services
|
|
199
|
+
* R2 Storage Provider
|
|
200
|
+
* Implements storage operations using native Cloudflare R2 bindings
|
|
202
201
|
*
|
|
203
|
-
* Implements
|
|
202
|
+
* Implements IMultipartProvider for multipart upload support needed by TUS.
|
|
203
|
+
* Tracks multipart upload metadata using companion R2 objects so that
|
|
204
|
+
* listParts/listMultipartUploads work in all environments (local, test, prod).
|
|
204
205
|
*/
|
|
205
|
-
declare class
|
|
206
|
-
private readonly
|
|
207
|
-
private readonly presigningClient;
|
|
206
|
+
declare class R2StorageProvider implements IMultipartProvider {
|
|
207
|
+
private readonly config;
|
|
208
208
|
private readonly bucket;
|
|
209
|
-
private readonly
|
|
210
|
-
|
|
209
|
+
private readonly env;
|
|
210
|
+
private readonly routeBasePath;
|
|
211
|
+
constructor(config: StorageEntry, bucket: R2Bucket, env: StratalEnv, routeConfig?: StorageRouteConfig);
|
|
211
212
|
upload(body: StreamingBlobPayloadInputTypes, path: string, options: UploadOptions): Promise<UploadResult>;
|
|
212
213
|
download(path: string): Promise<DownloadResult>;
|
|
213
214
|
delete(path: string): Promise<void>;
|
|
214
215
|
exists(path: string): Promise<boolean>;
|
|
215
216
|
getPresignedUrl(path: string, method: 'GET' | 'PUT' | 'DELETE' | 'HEAD', expiresIn: number): Promise<PresignedUrlResult>;
|
|
216
|
-
/**
|
|
217
|
-
* Chunked upload for streaming data without known size
|
|
218
|
-
* Uses @aws-sdk/lib-storage for multipart upload handling
|
|
219
|
-
*
|
|
220
|
-
* Benefits:
|
|
221
|
-
* - Handles unknown Content-Length automatically
|
|
222
|
-
* - Automatic retry on transient failures
|
|
223
|
-
* - Cleanup of partial uploads on error
|
|
224
|
-
* - Works with S3-compatible storage (R2, MinIO, RustFS)
|
|
225
|
-
*
|
|
226
|
-
* @param body - Content to upload (stream or buffer)
|
|
227
|
-
* @param path - Full path including disk root
|
|
228
|
-
* @param options - Upload options (mimeType required, size optional)
|
|
229
|
-
* @returns Upload result with metadata
|
|
230
|
-
*/
|
|
231
217
|
chunkedUpload(body: StreamingBlobPayloadInputTypes, path: string, options: Omit<UploadOptions, 'size'> & {
|
|
232
218
|
size?: number;
|
|
233
219
|
}): Promise<UploadResult>;
|
|
234
|
-
/**
|
|
235
|
-
* Get the bucket name
|
|
236
|
-
*/
|
|
237
220
|
getBucket(): string;
|
|
238
|
-
/**
|
|
239
|
-
* Get object metadata without downloading the body
|
|
240
|
-
*/
|
|
241
221
|
headObject(key: string): Promise<HeadObjectResult | null>;
|
|
242
|
-
/**
|
|
243
|
-
* Delete multiple objects in a single request
|
|
244
|
-
*/
|
|
245
222
|
deleteObjects(keys: string[]): Promise<DeleteObjectsResult>;
|
|
246
|
-
/**
|
|
247
|
-
* Create a multipart upload
|
|
248
|
-
*/
|
|
249
223
|
createMultipartUpload(key: string, options?: CreateMultipartOptions): Promise<CreateMultipartResult>;
|
|
250
|
-
/**
|
|
251
|
-
* Upload a part to an existing multipart upload
|
|
252
|
-
*/
|
|
253
224
|
uploadPart(key: string, uploadId: string, partNumber: number, body: Uint8Array): Promise<UploadPartResult>;
|
|
254
|
-
/**
|
|
255
|
-
* Complete a multipart upload
|
|
256
|
-
*/
|
|
257
225
|
completeMultipartUpload(key: string, uploadId: string, parts: CompletedPart[]): Promise<CompleteMultipartResult>;
|
|
258
|
-
/**
|
|
259
|
-
* Abort a multipart upload
|
|
260
|
-
*/
|
|
261
226
|
abortMultipartUpload(key: string, uploadId: string): Promise<void>;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
listParts(key: string, uploadId: string, partNumberMarker?: string): Promise<ListPartsResult>;
|
|
266
|
-
/**
|
|
267
|
-
* List all in-progress multipart uploads
|
|
268
|
-
*/
|
|
269
|
-
listMultipartUploads(keyMarker?: string, uploadIdMarker?: string): Promise<ListMultipartUploadsResult>;
|
|
227
|
+
listParts(_key: string, uploadId: string, partNumberMarker?: string): Promise<ListPartsResult>;
|
|
228
|
+
listMultipartUploads(keyMarker?: string, _uploadIdMarker?: string): Promise<ListMultipartUploadsResult>;
|
|
229
|
+
private cleanupTrackingObjects;
|
|
270
230
|
}
|
|
271
231
|
//#endregion
|
|
272
|
-
export { CompleteMultipartResult, CompletedPart, CreateMultipartOptions, CreateMultipartResult, DeleteObjectsResult, HeadObjectResult,
|
|
232
|
+
export { CompleteMultipartResult, CompletedPart, CreateMultipartOptions, CreateMultipartResult, DeleteObjectsResult, HeadObjectResult, IMultipartProvider, IStorageProvider, ListMultipartUploadsResult, ListPartsResult, MultipartUploadInfo, PartInfo, R2StorageProvider, StreamingBlobPayloadInputTypes, UploadPartResult };
|
|
273
233
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/storage/providers/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/storage/providers/multipart-provider.interface.ts","../../../src/storage/providers/r2-storage.provider.ts"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
export {
|
|
1
|
+
import { t as R2StorageProvider } from "../../r2-storage.provider-Co6F0ZYV.mjs";
|
|
2
|
+
export { R2StorageProvider };
|