stratal 0.0.16 → 0.0.18
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 +4 -0
- package/dist/bin/cloudflare-workers-loader.mjs +33 -1
- package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
- package/dist/bin/quarry.mjs +183 -55
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cache/index.d.mts.map +1 -1
- package/dist/cache/index.mjs +3 -11
- package/dist/cache/index.mjs.map +1 -1
- package/dist/{colors-DJaRDXoS.mjs → colors-BTAnQRGU.mjs} +1 -1
- package/dist/{colors-DJaRDXoS.mjs.map → colors-BTAnQRGU.mjs.map} +1 -1
- package/dist/{command-B-QH-Vu3.d.mts → command-B1YuV-UZ.d.mts} +2 -2
- package/dist/{command-B-QH-Vu3.d.mts.map → command-B1YuV-UZ.d.mts.map} +1 -1
- package/dist/{command-BvCOD6df.mjs → command-DjGqCYHv.mjs} +7 -4
- package/dist/command-DjGqCYHv.mjs.map +1 -0
- package/dist/config/index.d.mts +2 -2
- package/dist/config/index.mjs +12 -20
- package/dist/config/index.mjs.map +1 -1
- package/dist/consumer-registry-BkuHXR_u.d.mts +142 -0
- package/dist/consumer-registry-BkuHXR_u.d.mts.map +1 -0
- package/dist/cron/index.d.mts +3 -116
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +1 -4
- package/dist/{cron-manager-DR7fiG6o.mjs → cron-manager-1KnZvojs.mjs} +3 -3
- package/dist/{cron-manager-DR7fiG6o.mjs.map → cron-manager-1KnZvojs.mjs.map} +1 -1
- package/dist/cron-manager-BnEZquBL.d.mts +117 -0
- package/dist/cron-manager-BnEZquBL.d.mts.map +1 -0
- package/dist/di/index.d.mts +2 -2
- package/dist/di/index.mjs +3 -4
- package/dist/email/index.d.mts +3 -3
- package/dist/email/index.mjs +8 -17
- package/dist/email/index.mjs.map +1 -1
- package/dist/{en-DaewN8hc.mjs → en-3QnZwP-u.mjs} +10 -1
- package/dist/en-3QnZwP-u.mjs.map +1 -0
- package/dist/errors/index.d.mts +2 -2
- package/dist/errors/index.mjs +2 -4
- package/dist/errors--RBIvDXr.mjs +1560 -0
- package/dist/errors--RBIvDXr.mjs.map +1 -0
- package/dist/{errors-H3TZnVeX.mjs → errors-B7hCnXgB.mjs} +2 -2
- package/dist/{errors-H3TZnVeX.mjs.map → errors-B7hCnXgB.mjs.map} +1 -1
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +1 -3
- package/dist/{events-CXl-o1Ad.mjs → events-UTJliZhl.mjs} +2 -3
- package/dist/{events-CXl-o1Ad.mjs.map → events-UTJliZhl.mjs.map} +1 -1
- package/dist/{gateway-context-BkZ4UKaX.mjs → gateway-context-BdBFoQd8.mjs} +66 -10
- package/dist/gateway-context-BdBFoQd8.mjs.map +1 -0
- package/dist/guards/index.d.mts +3 -3
- package/dist/guards/index.d.mts.map +1 -1
- package/dist/guards/index.mjs +1 -1
- package/dist/{guards-DUk_Kzst.mjs → guards-MtDgcHnF.mjs} +1 -1
- package/dist/{guards-DUk_Kzst.mjs.map → guards-MtDgcHnF.mjs.map} +1 -1
- package/dist/i18n/index.d.mts +3 -3
- package/dist/i18n/index.mjs +3 -16
- package/dist/i18n/messages/en/index.d.mts +1 -1
- package/dist/i18n/messages/en/index.mjs +1 -1
- package/dist/i18n/utils/index.d.mts +30 -0
- package/dist/i18n/utils/index.d.mts.map +1 -0
- package/dist/i18n/utils/index.mjs +2 -0
- package/dist/i18n/validation/index.d.mts +1 -1
- package/dist/i18n/validation/index.mjs +1 -1
- package/dist/i18n.module-BpLLLCTg.mjs +2462 -0
- package/dist/i18n.module-BpLLLCTg.mjs.map +1 -0
- package/dist/{index-D_w_Rmtd.d.mts → index-BDh9J2KD.d.mts} +10 -1
- package/dist/{index-D_w_Rmtd.d.mts.map → index-BDh9J2KD.d.mts.map} +1 -1
- package/dist/{index-Dp6A5ywM.d.mts → index-BR23zDMy.d.mts} +1 -1
- package/dist/{index-Dp6A5ywM.d.mts.map → index-BR23zDMy.d.mts.map} +1 -1
- package/dist/index-BrmS34sa.d.mts +4287 -0
- package/dist/index-BrmS34sa.d.mts.map +1 -0
- package/dist/{index-D9iYu2Yc.d.mts → index-DPxmo6AY.d.mts} +5 -144
- package/dist/index-DPxmo6AY.d.mts.map +1 -0
- package/dist/{index-DVhdhLvE.d.mts → index-Dfpd_ypO.d.mts} +38 -9
- package/dist/index-Dfpd_ypO.d.mts.map +1 -0
- package/dist/index.d.mts +4 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -20
- package/dist/{is-command-BfCgWAcQ.mjs → is-command-PvULqiTa.mjs} +2 -2
- package/dist/{is-command-BfCgWAcQ.mjs.map → is-command-PvULqiTa.mjs.map} +1 -1
- package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-BN9Ej1r7.mjs} +1 -1
- package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-BN9Ej1r7.mjs.map} +1 -1
- package/dist/logger/index.d.mts +1 -1
- package/dist/logger/index.mjs +1 -2
- package/dist/{logger-BR1-s1Um.mjs → logger-c0ftIK4G.mjs} +170 -4
- package/dist/logger-c0ftIK4G.mjs.map +1 -0
- package/dist/module/index.d.mts +3 -119
- package/dist/module/index.d.mts.map +1 -1
- package/dist/module/index.mjs +1 -11
- package/dist/module-C3YZ-kZN.mjs +719 -0
- package/dist/module-C3YZ-kZN.mjs.map +1 -0
- package/dist/openapi/index.d.mts +54 -54
- package/dist/openapi/index.d.mts.map +1 -1
- package/dist/openapi/index.mjs +3 -16
- package/dist/openapi-tools.service-B77QXD56.mjs +197 -0
- package/dist/openapi-tools.service-B77QXD56.mjs.map +1 -0
- package/dist/openapi.service-6yj0BUY4.d.mts +50 -0
- package/dist/openapi.service-6yj0BUY4.d.mts.map +1 -0
- package/dist/quarry/index.d.mts +124 -29
- package/dist/quarry/index.d.mts.map +1 -1
- package/dist/quarry/index.mjs +5 -7
- package/dist/quarry-registry-CQCIlYTO.mjs +686 -0
- package/dist/quarry-registry-CQCIlYTO.mjs.map +1 -0
- package/dist/queue/index.d.mts +2 -1
- package/dist/queue/index.mjs +3 -14
- package/dist/queue/index.mjs.map +1 -1
- package/dist/{queue.module-BZvmeAMj.mjs → queue.module-DIjD6nr-.mjs} +39 -42
- package/dist/queue.module-DIjD6nr-.mjs.map +1 -0
- package/dist/{resend.provider-BCCACQAU.mjs → resend.provider-Bvw36rQy.mjs} +1 -4
- package/dist/{resend.provider-BCCACQAU.mjs.map → resend.provider-Bvw36rQy.mjs.map} +1 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +5 -16
- package/dist/{s3-storage.provider-BLlzQYiJ.mjs → s3-storage.provider-BAhHDMI3.mjs} +16 -9
- package/dist/s3-storage.provider-BAhHDMI3.mjs.map +1 -0
- package/dist/seeder/index.d.mts +3 -4
- package/dist/seeder/index.d.mts.map +1 -1
- package/dist/seeder/index.mjs +2 -7
- package/dist/{seeder-Cupi5jl-.mjs → seeder-D7VXULXB.mjs} +20 -17
- package/dist/seeder-D7VXULXB.mjs.map +1 -0
- package/dist/setup-BRIN-iYT.mjs +37 -0
- package/dist/setup-BRIN-iYT.mjs.map +1 -0
- package/dist/{smtp.provider-B8XtOcHU.mjs → smtp.provider-CAwpvzvD.mjs} +1 -4
- package/dist/{smtp.provider-B8XtOcHU.mjs.map → smtp.provider-CAwpvzvD.mjs.map} +1 -1
- package/dist/storage/index.d.mts +2 -195
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +2 -14
- package/dist/storage/providers/index.d.mts +273 -0
- package/dist/storage/providers/index.d.mts.map +1 -0
- package/dist/storage/providers/index.mjs +2 -0
- package/dist/{storage-By_ow2o_.mjs → storage-CJ-QOwNv.mjs} +8 -9
- package/dist/storage-CJ-QOwNv.mjs.map +1 -0
- package/dist/storage-provider.interface-YRtyYBxV.d.mts +203 -0
- package/dist/storage-provider.interface-YRtyYBxV.d.mts.map +1 -0
- package/dist/stratal-B7G4i9-N.mjs +502 -0
- package/dist/stratal-B7G4i9-N.mjs.map +1 -0
- package/dist/{types-DahElfUw.d.mts → types-CN0zONAZ.d.mts} +2 -2
- package/dist/types-CN0zONAZ.d.mts.map +1 -0
- package/dist/{usage-generator-C9hWziY4.mjs → usage-generator-Cl1HPlUp.mjs} +2 -2
- package/dist/{usage-generator-C9hWziY4.mjs.map → usage-generator-Cl1HPlUp.mjs.map} +1 -1
- package/dist/{validation-Bh875Lyg.mjs → validation-B4bePOa_.mjs} +5 -5
- package/dist/{validation-Bh875Lyg.mjs.map → validation-B4bePOa_.mjs.map} +1 -1
- package/dist/websocket/index.d.mts +2 -2
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +1 -5
- package/dist/workers/index.d.mts +1 -1
- package/dist/workers/index.d.mts.map +1 -1
- package/dist/workers/index.mjs +2 -20
- package/dist/workers/index.mjs.map +1 -1
- package/package.json +39 -31
- package/dist/application-zG8b-pol.d.mts +0 -116
- package/dist/application-zG8b-pol.d.mts.map +0 -1
- package/dist/command-BvCOD6df.mjs.map +0 -1
- package/dist/decorate-D5j-d9_z.mjs +0 -171
- package/dist/decorate-D5j-d9_z.mjs.map +0 -1
- package/dist/en-DaewN8hc.mjs.map +0 -1
- package/dist/errors-CtCi1wn6.mjs +0 -707
- package/dist/errors-CtCi1wn6.mjs.map +0 -1
- package/dist/gateway-context-BkZ4UKaX.mjs.map +0 -1
- package/dist/i18n.module-W8OJxg3d.mjs +0 -1791
- package/dist/i18n.module-W8OJxg3d.mjs.map +0 -1
- package/dist/index-BJWm863C.d.mts +0 -2616
- package/dist/index-BJWm863C.d.mts.map +0 -1
- package/dist/index-D9iYu2Yc.d.mts.map +0 -1
- package/dist/index-DVhdhLvE.d.mts.map +0 -1
- package/dist/logger-BR1-s1Um.mjs.map +0 -1
- package/dist/middleware/index.d.mts +0 -2
- package/dist/middleware/index.mjs +0 -6
- package/dist/middleware-C0Ebzswy.mjs +0 -362
- package/dist/middleware-C0Ebzswy.mjs.map +0 -1
- package/dist/module-BgdxxzBe.mjs +0 -370
- package/dist/module-BgdxxzBe.mjs.map +0 -1
- package/dist/quarry-registry-DCwqVcRp.mjs +0 -310
- package/dist/quarry-registry-DCwqVcRp.mjs.map +0 -1
- package/dist/queue.module-BZvmeAMj.mjs.map +0 -1
- package/dist/router-context-BEJe9HEB.mjs +0 -264
- package/dist/router-context-BEJe9HEB.mjs.map +0 -1
- package/dist/s3-storage.provider-BLlzQYiJ.mjs.map +0 -1
- package/dist/seeder-Cupi5jl-.mjs.map +0 -1
- package/dist/storage-By_ow2o_.mjs.map +0 -1
- package/dist/stratal-CE0iTz4f.mjs +0 -305
- package/dist/stratal-CE0iTz4f.mjs.map +0 -1
- package/dist/types-CLhOhYsQ.d.mts +0 -64
- package/dist/types-CLhOhYsQ.d.mts.map +0 -1
- package/dist/types-DahElfUw.d.mts.map +0 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { _ as StorageEntry, f as DownloadResult, i as UploadResult, n as StreamingBlobPayloadInputTypes, r as UploadOptions, s as PresignedUrlResult, t as IStorageProvider } from "../../storage-provider.interface-YRtyYBxV.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/storage/providers/s3-multipart-provider.interface.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for creating a multipart upload
|
|
6
|
+
*/
|
|
7
|
+
interface CreateMultipartOptions {
|
|
8
|
+
/** Content type (MIME type) */
|
|
9
|
+
contentType?: string;
|
|
10
|
+
/** Cache control header */
|
|
11
|
+
cacheControl?: string;
|
|
12
|
+
/** Custom S3 metadata */
|
|
13
|
+
metadata?: Record<string, string>;
|
|
14
|
+
/** S3 object tagging (key=value format) */
|
|
15
|
+
tagging?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Result of creating a multipart upload
|
|
19
|
+
*/
|
|
20
|
+
interface CreateMultipartResult {
|
|
21
|
+
/** S3 upload ID for subsequent part uploads */
|
|
22
|
+
uploadId: string;
|
|
23
|
+
/** Object key */
|
|
24
|
+
key: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result of uploading a part
|
|
28
|
+
*/
|
|
29
|
+
interface UploadPartResult {
|
|
30
|
+
/** ETag returned by S3 */
|
|
31
|
+
etag: string;
|
|
32
|
+
/** Part number */
|
|
33
|
+
partNumber: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Part info for completing multipart upload
|
|
37
|
+
*/
|
|
38
|
+
interface CompletedPart {
|
|
39
|
+
/** ETag from uploadPart */
|
|
40
|
+
etag: string;
|
|
41
|
+
/** Part number */
|
|
42
|
+
partNumber: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Result of completing a multipart upload
|
|
46
|
+
*/
|
|
47
|
+
interface CompleteMultipartResult {
|
|
48
|
+
/** S3 location URL */
|
|
49
|
+
location?: string;
|
|
50
|
+
/** Object key */
|
|
51
|
+
key: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Individual part info from listParts
|
|
55
|
+
*/
|
|
56
|
+
interface PartInfo {
|
|
57
|
+
/** Part number */
|
|
58
|
+
partNumber: number;
|
|
59
|
+
/** ETag */
|
|
60
|
+
etag: string;
|
|
61
|
+
/** Part size in bytes */
|
|
62
|
+
size: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Result of listing parts
|
|
66
|
+
*/
|
|
67
|
+
interface ListPartsResult {
|
|
68
|
+
/** List of uploaded parts */
|
|
69
|
+
parts: PartInfo[];
|
|
70
|
+
/** Whether there are more parts */
|
|
71
|
+
isTruncated: boolean;
|
|
72
|
+
/** Marker for next page */
|
|
73
|
+
nextPartNumberMarker?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Individual upload info from listMultipartUploads
|
|
77
|
+
*/
|
|
78
|
+
interface MultipartUploadInfo {
|
|
79
|
+
/** Object key */
|
|
80
|
+
key: string;
|
|
81
|
+
/** Upload ID */
|
|
82
|
+
uploadId: string;
|
|
83
|
+
/** When the upload was initiated */
|
|
84
|
+
initiated?: Date;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Result of listing multipart uploads
|
|
88
|
+
*/
|
|
89
|
+
interface ListMultipartUploadsResult {
|
|
90
|
+
/** List of in-progress uploads */
|
|
91
|
+
uploads: MultipartUploadInfo[];
|
|
92
|
+
/** Whether there are more uploads */
|
|
93
|
+
isTruncated: boolean;
|
|
94
|
+
/** Marker for next page (key) */
|
|
95
|
+
nextKeyMarker?: string;
|
|
96
|
+
/** Marker for next page (uploadId) */
|
|
97
|
+
nextUploadIdMarker?: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Result of headObject
|
|
101
|
+
*/
|
|
102
|
+
interface HeadObjectResult {
|
|
103
|
+
/** Object size in bytes */
|
|
104
|
+
size: number;
|
|
105
|
+
/** Content type */
|
|
106
|
+
contentType?: string;
|
|
107
|
+
/** Custom metadata */
|
|
108
|
+
metadata?: Record<string, string>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Result of batch delete
|
|
112
|
+
*/
|
|
113
|
+
interface DeleteObjectsResult {
|
|
114
|
+
/** Number of objects deleted */
|
|
115
|
+
deleted: number;
|
|
116
|
+
/** Errors that occurred */
|
|
117
|
+
errors: {
|
|
118
|
+
key: string;
|
|
119
|
+
code: string;
|
|
120
|
+
message: string;
|
|
121
|
+
}[];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* S3-specific storage provider interface with multipart upload support
|
|
125
|
+
*
|
|
126
|
+
* Extends the generic IStorageProvider with S3 multipart upload operations.
|
|
127
|
+
* This interface is S3-specific - other providers (GCS, local) would have
|
|
128
|
+
* their own resumable upload interfaces if needed.
|
|
129
|
+
*/
|
|
130
|
+
interface IS3MultipartProvider extends IStorageProvider {
|
|
131
|
+
/**
|
|
132
|
+
* Create a multipart upload
|
|
133
|
+
* @param key - Object key
|
|
134
|
+
* @param options - Upload options
|
|
135
|
+
* @returns Upload ID and key
|
|
136
|
+
*/
|
|
137
|
+
createMultipartUpload(key: string, options?: CreateMultipartOptions): Promise<CreateMultipartResult>;
|
|
138
|
+
/**
|
|
139
|
+
* Upload a part to an existing multipart upload
|
|
140
|
+
* @param key - Object key
|
|
141
|
+
* @param uploadId - Upload ID from createMultipartUpload
|
|
142
|
+
* @param partNumber - Part number (1-10000)
|
|
143
|
+
* @param body - Part data
|
|
144
|
+
* @returns ETag and part number
|
|
145
|
+
*/
|
|
146
|
+
uploadPart(key: string, uploadId: string, partNumber: number, body: Uint8Array): Promise<UploadPartResult>;
|
|
147
|
+
/**
|
|
148
|
+
* Complete a multipart upload
|
|
149
|
+
* @param key - Object key
|
|
150
|
+
* @param uploadId - Upload ID
|
|
151
|
+
* @param parts - List of completed parts with ETags
|
|
152
|
+
* @returns Location and key
|
|
153
|
+
*/
|
|
154
|
+
completeMultipartUpload(key: string, uploadId: string, parts: CompletedPart[]): Promise<CompleteMultipartResult>;
|
|
155
|
+
/**
|
|
156
|
+
* Abort a multipart upload
|
|
157
|
+
* @param key - Object key
|
|
158
|
+
* @param uploadId - Upload ID
|
|
159
|
+
*/
|
|
160
|
+
abortMultipartUpload(key: string, uploadId: string): Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* List parts of a multipart upload
|
|
163
|
+
* @param key - Object key
|
|
164
|
+
* @param uploadId - Upload ID
|
|
165
|
+
* @param partNumberMarker - Optional marker for pagination
|
|
166
|
+
* @returns List of parts
|
|
167
|
+
*/
|
|
168
|
+
listParts(key: string, uploadId: string, partNumberMarker?: string): Promise<ListPartsResult>;
|
|
169
|
+
/**
|
|
170
|
+
* List all in-progress multipart uploads
|
|
171
|
+
* @param keyMarker - Optional key marker for pagination
|
|
172
|
+
* @param uploadIdMarker - Optional upload ID marker for pagination
|
|
173
|
+
* @returns List of uploads
|
|
174
|
+
*/
|
|
175
|
+
listMultipartUploads(keyMarker?: string, uploadIdMarker?: string): Promise<ListMultipartUploadsResult>;
|
|
176
|
+
/**
|
|
177
|
+
* Get object metadata without downloading the body
|
|
178
|
+
* Unlike exists() which returns boolean, this returns actual metadata
|
|
179
|
+
* @param key - Object key
|
|
180
|
+
* @returns Object metadata or null if not found
|
|
181
|
+
*/
|
|
182
|
+
headObject(key: string): Promise<HeadObjectResult | null>;
|
|
183
|
+
/**
|
|
184
|
+
* Delete multiple objects in a single request
|
|
185
|
+
* More efficient than individual delete() calls
|
|
186
|
+
* @param keys - Array of object keys
|
|
187
|
+
* @returns Delete results
|
|
188
|
+
*/
|
|
189
|
+
deleteObjects(keys: string[]): Promise<DeleteObjectsResult>;
|
|
190
|
+
/**
|
|
191
|
+
* Get the bucket name
|
|
192
|
+
* @returns Bucket name from configuration
|
|
193
|
+
*/
|
|
194
|
+
getBucket(): string;
|
|
195
|
+
}
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/storage/providers/s3-storage.provider.d.ts
|
|
198
|
+
/**
|
|
199
|
+
* S3 Storage Provider
|
|
200
|
+
* Implements storage operations using AWS SDK for S3-compatible storage
|
|
201
|
+
* Works with AWS S3, Cloudflare R2, MinIO, and other S3-compatible services
|
|
202
|
+
*
|
|
203
|
+
* Implements IS3MultipartProvider for multipart upload support needed by TUS
|
|
204
|
+
*/
|
|
205
|
+
declare class S3StorageProvider implements IS3MultipartProvider {
|
|
206
|
+
private readonly client;
|
|
207
|
+
private readonly presigningClient;
|
|
208
|
+
private readonly bucket;
|
|
209
|
+
private readonly disk;
|
|
210
|
+
constructor(config: StorageEntry);
|
|
211
|
+
upload(body: StreamingBlobPayloadInputTypes, path: string, options: UploadOptions): Promise<UploadResult>;
|
|
212
|
+
download(path: string): Promise<DownloadResult>;
|
|
213
|
+
delete(path: string): Promise<void>;
|
|
214
|
+
exists(path: string): Promise<boolean>;
|
|
215
|
+
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
|
+
chunkedUpload(body: StreamingBlobPayloadInputTypes, path: string, options: Omit<UploadOptions, 'size'> & {
|
|
232
|
+
size?: number;
|
|
233
|
+
}): Promise<UploadResult>;
|
|
234
|
+
/**
|
|
235
|
+
* Get the bucket name
|
|
236
|
+
*/
|
|
237
|
+
getBucket(): string;
|
|
238
|
+
/**
|
|
239
|
+
* Get object metadata without downloading the body
|
|
240
|
+
*/
|
|
241
|
+
headObject(key: string): Promise<HeadObjectResult | null>;
|
|
242
|
+
/**
|
|
243
|
+
* Delete multiple objects in a single request
|
|
244
|
+
*/
|
|
245
|
+
deleteObjects(keys: string[]): Promise<DeleteObjectsResult>;
|
|
246
|
+
/**
|
|
247
|
+
* Create a multipart upload
|
|
248
|
+
*/
|
|
249
|
+
createMultipartUpload(key: string, options?: CreateMultipartOptions): Promise<CreateMultipartResult>;
|
|
250
|
+
/**
|
|
251
|
+
* Upload a part to an existing multipart upload
|
|
252
|
+
*/
|
|
253
|
+
uploadPart(key: string, uploadId: string, partNumber: number, body: Uint8Array): Promise<UploadPartResult>;
|
|
254
|
+
/**
|
|
255
|
+
* Complete a multipart upload
|
|
256
|
+
*/
|
|
257
|
+
completeMultipartUpload(key: string, uploadId: string, parts: CompletedPart[]): Promise<CompleteMultipartResult>;
|
|
258
|
+
/**
|
|
259
|
+
* Abort a multipart upload
|
|
260
|
+
*/
|
|
261
|
+
abortMultipartUpload(key: string, uploadId: string): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* List parts of a multipart upload
|
|
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>;
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
export { CompleteMultipartResult, CompletedPart, CreateMultipartOptions, CreateMultipartResult, DeleteObjectsResult, HeadObjectResult, IS3MultipartProvider, IStorageProvider, ListMultipartUploadsResult, ListPartsResult, MultipartUploadInfo, PartInfo, S3StorageProvider, StreamingBlobPayloadInputTypes, UploadPartResult };
|
|
273
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/storage/providers/s3-multipart-provider.interface.ts","../../../src/storage/providers/s3-storage.provider.ts"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as withI18n, i as z } from "./validation-
|
|
5
|
-
import { a as InvalidDiskError, c as DiskNotConfiguredError, n as StorageProviderNotSupportedError, r as PresignedUrlInvalidExpiryError } from "./errors-
|
|
1
|
+
import { A as Scope } from "./errors--RBIvDXr.mjs";
|
|
2
|
+
import { a as __decorate, o as __decorateParam, p as Transient, s as __decorateMetadata } from "./logger-c0ftIK4G.mjs";
|
|
3
|
+
import { S as Module } from "./module-C3YZ-kZN.mjs";
|
|
4
|
+
import { a as withI18n, i as z } from "./validation-B4bePOa_.mjs";
|
|
5
|
+
import { a as InvalidDiskError, c as DiskNotConfiguredError, n as StorageProviderNotSupportedError, r as PresignedUrlInvalidExpiryError } from "./errors-B7hCnXgB.mjs";
|
|
6
6
|
import { inject } from "tsyringe";
|
|
7
7
|
//#region src/storage/storage.tokens.ts
|
|
8
8
|
/**
|
|
@@ -63,7 +63,7 @@ let StorageManagerService = class StorageManagerService {
|
|
|
63
63
|
async createProvider(config) {
|
|
64
64
|
switch (config.provider) {
|
|
65
65
|
case "s3": {
|
|
66
|
-
const { S3StorageProvider } = await import("./s3-storage.provider-
|
|
66
|
+
const { S3StorageProvider } = await import("./s3-storage.provider-BAhHDMI3.mjs").then((n) => n.n);
|
|
67
67
|
return new S3StorageProvider(config);
|
|
68
68
|
}
|
|
69
69
|
case "gcs": throw new StorageProviderNotSupportedError(config.provider);
|
|
@@ -103,7 +103,6 @@ StorageManagerService = __decorate([
|
|
|
103
103
|
], StorageManagerService);
|
|
104
104
|
//#endregion
|
|
105
105
|
//#region src/storage/services/storage.service.ts
|
|
106
|
-
var _ref;
|
|
107
106
|
let StorageService = class StorageService {
|
|
108
107
|
constructor(storageManager, options) {
|
|
109
108
|
this.storageManager = storageManager;
|
|
@@ -285,7 +284,7 @@ StorageService = __decorate([
|
|
|
285
284
|
Transient(STORAGE_TOKENS.StorageService),
|
|
286
285
|
__decorateParam(0, inject(STORAGE_TOKENS.StorageManager)),
|
|
287
286
|
__decorateParam(1, inject(STORAGE_TOKENS.Options)),
|
|
288
|
-
__decorateMetadata("design:paramtypes", [
|
|
287
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
289
288
|
], StorageService);
|
|
290
289
|
//#endregion
|
|
291
290
|
//#region src/storage/storage.module.ts
|
|
@@ -408,4 +407,4 @@ const uploadResultSchema = z.object({
|
|
|
408
407
|
//#endregion
|
|
409
408
|
export { deleteFileInputSchema as a, StorageManagerService as c, fileExistsInputSchema as i, STORAGE_TOKENS as l, getPresignedUrlInputSchema as n, StorageModule as o, presignedUrlResultSchema as r, StorageService as s, uploadResultSchema as t };
|
|
410
409
|
|
|
411
|
-
//# sourceMappingURL=storage-
|
|
410
|
+
//# sourceMappingURL=storage-CJ-QOwNv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-CJ-QOwNv.mjs","names":[],"sources":["../src/storage/storage.tokens.ts","../src/storage/services/storage-manager.service.ts","../src/storage/services/storage.service.ts","../src/storage/storage.module.ts","../src/storage/contracts/delete-file.input.ts","../src/storage/contracts/file-exists.input.ts","../src/storage/contracts/get-presigned-url.input.ts","../src/storage/contracts/upload-file.input.ts"],"sourcesContent":["/**\n * Dependency injection tokens for the Storage module\n * Using Symbol-based tokens to avoid magic strings\n */\nexport const STORAGE_TOKENS = {\n Options: Symbol.for('stratal:storage:options'),\n StorageService: Symbol.for('stratal:storage:service'),\n StorageManager: Symbol.for('stratal:storage:manager'),\n} as const\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { DiskNotConfiguredError, StorageProviderNotSupportedError } from '../errors'\nimport type { IStorageProvider } from '../providers/storage-provider.interface'\nimport { STORAGE_TOKENS } from '../storage.tokens'\nimport type { StorageConfig, StorageEntry } from '../types'\n\n/**\n * Storage Manager Service\n * Manages multiple storage providers (one per disk)\n * Handles lazy initialization and caching of S3Clients\n */\n@Transient(STORAGE_TOKENS.StorageManager)\nexport class StorageManagerService {\n private readonly providers = new Map<string, IStorageProvider>()\n private readonly creationPromises = new Map<string, Promise<IStorageProvider>>()\n private readonly diskConfigs = new Map<string, StorageEntry>()\n\n constructor(\n @inject(STORAGE_TOKENS.Options)\n private readonly options: StorageConfig\n ) {\n this.initializeDiskConfigs()\n }\n\n /**\n * Initialize disk configurations from options\n */\n private initializeDiskConfigs(): void {\n for (const entry of this.options.storage) {\n this.diskConfigs.set(entry.disk, entry)\n }\n }\n\n /**\n * Get provider for a specific disk\n * Lazily initializes provider on first access\n * @param diskName - Name of the disk\n * @returns Storage provider instance\n */\n async getProvider(diskName: string): Promise<IStorageProvider> {\n // Return cached provider if exists\n const cached = this.providers.get(diskName)\n if (cached) {\n return cached\n }\n\n // Return in-flight creation promise to deduplicate concurrent calls\n const inflight = this.creationPromises.get(diskName)\n if (inflight) {\n return inflight\n }\n\n // Get disk configuration\n const diskConfig = this.diskConfigs.get(diskName)\n if (!diskConfig) {\n throw new DiskNotConfiguredError(diskName)\n }\n\n // Create provider and deduplicate concurrent calls\n const promise = this.createProvider(diskConfig).then((provider) => {\n this.providers.set(diskName, provider)\n this.creationPromises.delete(diskName)\n return provider\n }).catch((error: unknown) => {\n this.creationPromises.delete(diskName)\n throw error\n })\n\n this.creationPromises.set(diskName, promise)\n\n return promise\n }\n\n /**\n * Create a provider instance based on configuration\n * Dynamically imports S3StorageProvider to avoid loading AWS SDK at module evaluation time\n * @param config - Storage entry configuration\n * @returns Storage provider instance\n */\n private async createProvider(config: StorageEntry): Promise<IStorageProvider> {\n switch (config.provider) {\n case 's3': {\n const { S3StorageProvider } = await import('../providers/s3-storage.provider')\n return new S3StorageProvider(config)\n }\n case 'gcs':\n throw new StorageProviderNotSupportedError(config.provider)\n default:\n throw new StorageProviderNotSupportedError(config.provider)\n }\n }\n\n /**\n * Get disk configuration\n * @param diskName - Name of the disk\n * @returns Storage entry configuration\n */\n getDiskConfig(diskName: string): StorageEntry {\n const config = this.diskConfigs.get(diskName)\n if (!config) {\n throw new DiskNotConfiguredError(diskName)\n }\n return config\n }\n\n /**\n * Check if a disk exists\n * @param diskName - Name of the disk\n * @returns True if disk exists, false otherwise\n */\n hasDisk(diskName: string): boolean {\n return this.diskConfigs.has(diskName)\n }\n\n /**\n * Get all available disk names\n * @returns Array of disk names\n */\n getAvailableDisks(): string[] {\n return Array.from(this.diskConfigs.keys())\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport type { DownloadResult, PresignedUrlResult, UploadOptions, UploadResult } from '../contracts'\nimport {\n InvalidDiskError,\n PresignedUrlInvalidExpiryError,\n} from '../errors'\nimport type { StreamingBlobPayloadInputTypes } from '../providers/storage-provider.interface'\nimport { STORAGE_TOKENS } from '../storage.tokens'\nimport type { StorageConfig } from '../types'\nimport { type StorageManagerService } from './storage-manager.service'\n\n/**\n * Storage Service\n *\n * Main facade for storage operations.\n * Request-scoped for proper isolation.\n *\n * @example\n * ```typescript\n * @inject(STORAGE_TOKENS.StorageService)\n * private readonly storage: StorageService\n *\n * await this.storage.upload(file, 'documents/report.pdf')\n * ```\n */\n@Transient(STORAGE_TOKENS.StorageService)\nexport class StorageService {\n constructor(\n @inject(STORAGE_TOKENS.StorageManager)\n protected readonly storageManager: StorageManagerService,\n @inject(STORAGE_TOKENS.Options)\n protected readonly options: StorageConfig\n ) { }\n\n /**\n * Upload content to storage\n * @param body - Content to upload (stream, buffer, or string)\n * @param relativePath - Relative path within the disk\n * @param options - Upload options including size and mime type\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Upload result with metadata\n */\n async upload(\n body: StreamingBlobPayloadInputTypes,\n relativePath: string,\n options: UploadOptions,\n disk?: string\n ): Promise<UploadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.upload(body, fullPath, options)\n }\n\n /**\n * Download a file from storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Download result with stream and metadata\n */\n async download(relativePath: string, disk?: string): Promise<DownloadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.download(fullPath)\n }\n\n /**\n * Delete a file from storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n */\n async delete(relativePath: string, disk?: string): Promise<void> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n await provider.delete(fullPath)\n }\n\n /**\n * Check if a file exists in storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n * @returns True if file exists, false otherwise\n */\n async exists(relativePath: string, disk?: string): Promise<boolean> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.exists(fullPath)\n }\n\n /**\n * Generate a presigned download URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedDownloadUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'GET', expiresIn, disk)\n }\n\n /**\n * Generate a presigned upload URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedUploadUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'PUT', expiresIn, disk)\n }\n\n /**\n * Generate a presigned delete URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedDeleteUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'DELETE', expiresIn, disk)\n }\n\n /**\n * Generate a presigned URL for any method\n * @param relativePath - Relative path within the disk\n * @param method - HTTP method (GET, PUT, DELETE, HEAD)\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n protected async getPresignedUrl(\n relativePath: string,\n method: 'GET' | 'PUT' | 'DELETE' | 'HEAD',\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n const validatedExpiresIn = this.validateExpiresIn(expiresIn)\n\n return provider.getPresignedUrl(fullPath, method, validatedExpiresIn)\n }\n\n /**\n * Resolve disk name (use default if not provided)\n * @param disk - Optional disk name\n * @returns Resolved disk name\n */\n protected resolveDisk(disk?: string): string {\n const diskName = disk ?? this.options.defaultStorageDisk\n\n if (!this.storageManager.hasDisk(diskName)) {\n throw new InvalidDiskError(diskName)\n }\n\n return diskName\n }\n\n /**\n * Build full path with disk root and path template substitution\n * @param relativePath - Relative path within the disk\n * @param diskName - Name of the disk\n * @returns Full path including disk root\n */\n protected buildFullPath(relativePath: string, diskName: string): string {\n const diskConfig = this.storageManager.getDiskConfig(diskName)\n let root = diskConfig.root || ''\n\n // Substitute template variables\n root = this.substituteTemplateVariables(root)\n\n // Combine root and relative path\n const fullPath = `${root}/${relativePath}`.replace(/\\/+/g, '/').replace(/^\\//, '')\n\n return fullPath\n }\n\n /**\n * Substitute template variables in path\n * Override this method in subclasses to add custom substitutions\n *\n * @param path - Path with template variables\n * @returns Path with substituted variables\n */\n protected substituteTemplateVariables(path: string): string {\n let result = path\n\n // Substitute {date}, {year}, {month}\n const now = new Date()\n result = result.replace(/{date}/g, now.toISOString().split('T')[0])\n result = result.replace(/{year}/g, now.getFullYear().toString())\n result = result.replace(/{month}/g, (now.getMonth() + 1).toString().padStart(2, '0'))\n\n return result\n }\n\n /**\n * Validate expiry time for presigned URLs\n * @param expiresIn - Optional expiry time in seconds\n * @returns Validated expiry time\n */\n protected validateExpiresIn(expiresIn?: number): number {\n const presignedUrlConfig = this.options.presignedUrl\n const validatedExpiresIn = expiresIn ?? presignedUrlConfig.defaultExpiry\n\n // S3 presigned URL limits: 1 second to 7 days (604800 seconds)\n const minExpiry = 1\n const maxExpiry = presignedUrlConfig.maxExpiry\n\n if (validatedExpiresIn < minExpiry || validatedExpiresIn > maxExpiry) {\n throw new PresignedUrlInvalidExpiryError(validatedExpiresIn, minExpiry, maxExpiry)\n }\n\n return validatedExpiresIn\n }\n\n /**\n * Get all available disk names\n * @returns Array of disk names\n */\n getAvailableDisks(): string[] {\n return this.storageManager.getAvailableDisks()\n }\n\n /**\n * Chunked upload for streaming data without known size\n * Uses multipart upload under the hood - handles retries and large files\n *\n * Use this method when:\n * - Content-Length is unknown or unreliable\n * - Uploading from streams that can't be rewound\n * - Need automatic retry handling for transient failures\n *\n * @param body - Content to upload (stream or buffer)\n * @param relativePath - Relative path within the disk\n * @param options - Upload options (mimeType required, size optional)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Upload result with metadata\n */\n async chunkedUpload(\n body: StreamingBlobPayloadInputTypes,\n relativePath: string,\n options: Omit<UploadOptions, 'size'> & { size?: number },\n disk?: string\n ): Promise<UploadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.chunkedUpload(body, fullPath, options)\n }\n}\n","/**\n * Storage Module\n * Provides file storage capabilities using AWS S3\n * Supports multiple disk configurations with dynamic path templates\n */\n\nimport { Scope } from '../di/types'\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule } from '../module/types'\nimport { StorageManagerService } from './services/storage-manager.service'\nimport { StorageService } from './services/storage.service'\nimport { STORAGE_TOKENS } from './storage.tokens'\nimport type { StorageConfig } from './types'\n\n/**\n * Storage module options\n * Same as StorageConfig from types.ts\n */\nexport type StorageModuleOptions = StorageConfig\n\n@Module({\n providers: [{ provide: STORAGE_TOKENS.StorageManager, useClass: StorageManagerService, scope: Scope.Singleton },\n { provide: STORAGE_TOKENS.StorageService, useClass: StorageService },],\n})\nexport class StorageModule {\n /**\n * Configure StorageModule with static options\n *\n * @param options - Storage configuration options\n * @returns Dynamic module with storage infrastructure\n *\n * @example\n * ```typescript\n * StorageModule.forRoot({\n * storage: [{ disk: 'uploads', provider: 's3', ... }],\n * defaultStorageDisk: 'uploads',\n * presignedUrl: { defaultExpiry: 3600, maxExpiry: 86400 }\n * })\n * ```\n */\n static forRoot(options: StorageModuleOptions): DynamicModule {\n return {\n module: StorageModule,\n providers: [\n { provide: STORAGE_TOKENS.Options, useValue: options },\n ],\n }\n }\n\n /**\n * Configure StorageModule with async factory\n *\n * Use when configuration depends on other services.\n *\n * @param options - Async configuration with factory and inject tokens\n * @returns Dynamic module with storage infrastructure\n *\n * @example\n * ```typescript\n * StorageModule.forRootAsync({\n * inject: [storageConfig.KEY],\n * useFactory: (storage) => ({\n * storage: storage.storage,\n * defaultStorageDisk: storage.defaultStorageDisk,\n * presignedUrl: storage.presignedUrl\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<StorageModuleOptions>): DynamicModule {\n return {\n module: StorageModule,\n providers: [\n {\n provide: STORAGE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n}\n","import { z, withI18n } from '../../i18n/validation'\n\nexport const deleteFileInputSchema = z.object({\n path: z.string().min(1, withI18n('zodI18n.errors.custom.filePathRequired')),\n disk: z.string().optional(),\n})\n\nexport type DeleteFileInput = z.infer<typeof deleteFileInputSchema>\n","import { z, withI18n } from '../../i18n/validation'\n\nexport const fileExistsInputSchema = z.object({\n path: z.string().min(1, withI18n('zodI18n.errors.custom.filePathRequired')),\n disk: z.string().optional(),\n})\n\nexport type FileExistsInput = z.infer<typeof fileExistsInputSchema>\n","import { z, withI18n } from '../../i18n/validation'\n\nexport const getPresignedUrlInputSchema = z.object({\n path: z.string().min(1, withI18n('zodI18n.errors.custom.filePathRequired')),\n method: z.enum(['GET', 'PUT', 'DELETE', 'HEAD']).default('GET'),\n expiresIn: z.number().int().min(1).max(604800).optional(),\n disk: z.string().optional(),\n})\n\nexport type GetPresignedUrlInput = z.infer<typeof getPresignedUrlInputSchema>\n\nexport const presignedUrlResultSchema = z.object({\n url: z.string().url(),\n expiresIn: z.number(),\n expiresAt: z.date(),\n method: z.enum(['GET', 'PUT', 'DELETE', 'HEAD']),\n})\n\nexport type PresignedUrlResult = z.infer<typeof presignedUrlResultSchema>\n","import { z } from '../../i18n/validation'\n\n/**\n * Upload options for streaming uploads\n */\nexport interface UploadOptions {\n /**\n * Size of the content in bytes\n */\n size: number\n /**\n * MIME type of the content\n */\n mimeType?: string\n /**\n * Custom metadata to store with the object (S3-specific)\n * Stored as S3 object metadata headers\n */\n metadata?: Record<string, string>\n /**\n * Object tagging for lifecycle policies (S3-specific)\n * Format: key=value (e.g., \"Tus-Completed=true\")\n */\n tagging?: string\n}\n\nexport const uploadResultSchema = z.object({\n path: z.string(),\n disk: z.string(),\n fullPath: z.string(),\n size: z.number(),\n mimeType: z.string(),\n uploadedAt: z.date(),\n})\n\nexport type UploadResult = z.infer<typeof uploadResultSchema>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { o as z } from "./index-Dfpd_ypO.mjs";
|
|
2
|
+
import { PutObjectCommandInput } from "@aws-sdk/client-s3";
|
|
3
|
+
|
|
4
|
+
//#region src/storage/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Storage entry configuration
|
|
7
|
+
* Represents a single storage disk with its credentials
|
|
8
|
+
*/
|
|
9
|
+
interface StorageEntry {
|
|
10
|
+
disk: string;
|
|
11
|
+
provider: 's3' | 'gcs';
|
|
12
|
+
endpoint: string;
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for generating presigned/temporary URLs (client-accessible).
|
|
15
|
+
* When set, presigned URLs use this host instead of `endpoint`.
|
|
16
|
+
* Useful when the S3 API endpoint differs from the client-facing URL.
|
|
17
|
+
*/
|
|
18
|
+
url?: string;
|
|
19
|
+
bucket: string;
|
|
20
|
+
region: string;
|
|
21
|
+
accessKeyId: string;
|
|
22
|
+
secretAccessKey: string;
|
|
23
|
+
root: string;
|
|
24
|
+
visibility: 'public' | 'private';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Presigned URL configuration
|
|
28
|
+
*/
|
|
29
|
+
interface PresignedUrlConfig {
|
|
30
|
+
defaultExpiry: number;
|
|
31
|
+
maxExpiry: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Storage configuration used by framework
|
|
35
|
+
*/
|
|
36
|
+
interface StorageConfig {
|
|
37
|
+
storage: StorageEntry[];
|
|
38
|
+
defaultStorageDisk: string;
|
|
39
|
+
presignedUrl: PresignedUrlConfig;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/storage/contracts/delete-file.input.d.ts
|
|
43
|
+
declare const deleteFileInputSchema: z.ZodObject<{
|
|
44
|
+
path: z.ZodString;
|
|
45
|
+
disk: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
type DeleteFileInput = z.infer<typeof deleteFileInputSchema>;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/storage/contracts/download-result.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* Download Result
|
|
52
|
+
*
|
|
53
|
+
* Result of downloading a file from storage.
|
|
54
|
+
* Includes the file stream and metadata.
|
|
55
|
+
*/
|
|
56
|
+
interface DownloadResult {
|
|
57
|
+
/**
|
|
58
|
+
* ReadableStream of file contents
|
|
59
|
+
*/
|
|
60
|
+
toStream(): undefined | ReadableStream<Uint8Array>;
|
|
61
|
+
toString(): undefined | Promise<string>;
|
|
62
|
+
toArrayBuffer(): undefined | Promise<Uint8Array>;
|
|
63
|
+
/**
|
|
64
|
+
* MIME type of the file (e.g., 'application/pdf', 'image/png')
|
|
65
|
+
*/
|
|
66
|
+
contentType: string;
|
|
67
|
+
/**
|
|
68
|
+
* Size of the file in bytes
|
|
69
|
+
*/
|
|
70
|
+
size: number;
|
|
71
|
+
/**
|
|
72
|
+
* Custom object metadata (S3-specific)
|
|
73
|
+
* Key-value pairs stored with the object
|
|
74
|
+
*/
|
|
75
|
+
metadata?: Record<string, string>;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/storage/contracts/file-exists.input.d.ts
|
|
79
|
+
declare const fileExistsInputSchema: z.ZodObject<{
|
|
80
|
+
path: z.ZodString;
|
|
81
|
+
disk: z.ZodOptional<z.ZodString>;
|
|
82
|
+
}, z.core.$strip>;
|
|
83
|
+
type FileExistsInput = z.infer<typeof fileExistsInputSchema>;
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/storage/contracts/get-presigned-url.input.d.ts
|
|
86
|
+
declare const getPresignedUrlInputSchema: z.ZodObject<{
|
|
87
|
+
path: z.ZodString;
|
|
88
|
+
method: z.ZodDefault<z.ZodEnum<{
|
|
89
|
+
GET: "GET";
|
|
90
|
+
PUT: "PUT";
|
|
91
|
+
DELETE: "DELETE";
|
|
92
|
+
HEAD: "HEAD";
|
|
93
|
+
}>>;
|
|
94
|
+
expiresIn: z.ZodOptional<z.ZodNumber>;
|
|
95
|
+
disk: z.ZodOptional<z.ZodString>;
|
|
96
|
+
}, z.core.$strip>;
|
|
97
|
+
type GetPresignedUrlInput = z.infer<typeof getPresignedUrlInputSchema>;
|
|
98
|
+
declare const presignedUrlResultSchema: z.ZodObject<{
|
|
99
|
+
url: z.ZodString;
|
|
100
|
+
expiresIn: z.ZodNumber;
|
|
101
|
+
expiresAt: z.ZodDate;
|
|
102
|
+
method: z.ZodEnum<{
|
|
103
|
+
GET: "GET";
|
|
104
|
+
PUT: "PUT";
|
|
105
|
+
DELETE: "DELETE";
|
|
106
|
+
HEAD: "HEAD";
|
|
107
|
+
}>;
|
|
108
|
+
}, z.core.$strip>;
|
|
109
|
+
type PresignedUrlResult = z.infer<typeof presignedUrlResultSchema>;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/storage/contracts/upload-file.input.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* Upload options for streaming uploads
|
|
114
|
+
*/
|
|
115
|
+
interface UploadOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Size of the content in bytes
|
|
118
|
+
*/
|
|
119
|
+
size: number;
|
|
120
|
+
/**
|
|
121
|
+
* MIME type of the content
|
|
122
|
+
*/
|
|
123
|
+
mimeType?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Custom metadata to store with the object (S3-specific)
|
|
126
|
+
* Stored as S3 object metadata headers
|
|
127
|
+
*/
|
|
128
|
+
metadata?: Record<string, string>;
|
|
129
|
+
/**
|
|
130
|
+
* Object tagging for lifecycle policies (S3-specific)
|
|
131
|
+
* Format: key=value (e.g., "Tus-Completed=true")
|
|
132
|
+
*/
|
|
133
|
+
tagging?: string;
|
|
134
|
+
}
|
|
135
|
+
declare const uploadResultSchema: z.ZodObject<{
|
|
136
|
+
path: z.ZodString;
|
|
137
|
+
disk: z.ZodString;
|
|
138
|
+
fullPath: z.ZodString;
|
|
139
|
+
size: z.ZodNumber;
|
|
140
|
+
mimeType: z.ZodString;
|
|
141
|
+
uploadedAt: z.ZodDate;
|
|
142
|
+
}, z.core.$strip>;
|
|
143
|
+
type UploadResult = z.infer<typeof uploadResultSchema>;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/storage/providers/storage-provider.interface.d.ts
|
|
146
|
+
/**
|
|
147
|
+
* Streaming blob payload input types from AWS SDK
|
|
148
|
+
* Represents the types that can be used as the Body of a PutObjectCommand
|
|
149
|
+
*/
|
|
150
|
+
type StreamingBlobPayloadInputTypes = PutObjectCommandInput['Body'];
|
|
151
|
+
/**
|
|
152
|
+
* Storage provider interface
|
|
153
|
+
* Defines the contract for storage implementations (R2, S3, GCS, etc.)
|
|
154
|
+
*/
|
|
155
|
+
interface IStorageProvider {
|
|
156
|
+
/**
|
|
157
|
+
* Upload content to storage
|
|
158
|
+
* @param body - Content to upload (stream, buffer, or string)
|
|
159
|
+
* @param path - Full path including disk root
|
|
160
|
+
* @param options - Upload options including size and mime type
|
|
161
|
+
* @returns Upload result with metadata
|
|
162
|
+
*/
|
|
163
|
+
upload(body: StreamingBlobPayloadInputTypes, path: string, options: UploadOptions): Promise<UploadResult>;
|
|
164
|
+
/**
|
|
165
|
+
* Download a file from storage
|
|
166
|
+
* @param path - Full path to the file
|
|
167
|
+
* @returns Download result with stream and metadata
|
|
168
|
+
*/
|
|
169
|
+
download(path: string): Promise<DownloadResult>;
|
|
170
|
+
/**
|
|
171
|
+
* Delete a file from storage
|
|
172
|
+
* @param path - Full path to the file
|
|
173
|
+
*/
|
|
174
|
+
delete(path: string): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Check if a file exists in storage
|
|
177
|
+
* @param path - Full path to the file
|
|
178
|
+
* @returns True if file exists, false otherwise
|
|
179
|
+
*/
|
|
180
|
+
exists(path: string): Promise<boolean>;
|
|
181
|
+
/**
|
|
182
|
+
* Generate a presigned URL for temporary access
|
|
183
|
+
* @param path - Full path to the file
|
|
184
|
+
* @param method - HTTP method (GET, PUT, DELETE, HEAD)
|
|
185
|
+
* @param expiresIn - Expiry time in seconds (1-604800)
|
|
186
|
+
* @returns Presigned URL result
|
|
187
|
+
*/
|
|
188
|
+
getPresignedUrl(path: string, method: 'GET' | 'PUT' | 'DELETE' | 'HEAD', expiresIn: number): Promise<PresignedUrlResult>;
|
|
189
|
+
/**
|
|
190
|
+
* Chunked upload for streaming data without known size
|
|
191
|
+
* Uses multipart upload under the hood for reliability
|
|
192
|
+
* @param body - Content to upload (stream or buffer)
|
|
193
|
+
* @param path - Full path including disk root
|
|
194
|
+
* @param options - Upload options (mimeType required, size optional)
|
|
195
|
+
* @returns Upload result with metadata
|
|
196
|
+
*/
|
|
197
|
+
chunkedUpload(body: StreamingBlobPayloadInputTypes, path: string, options: Omit<UploadOptions, 'size'> & {
|
|
198
|
+
size?: number;
|
|
199
|
+
}): Promise<UploadResult>;
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { StorageEntry as _, uploadResultSchema as a, getPresignedUrlInputSchema as c, fileExistsInputSchema as d, DownloadResult as f, StorageConfig as g, PresignedUrlConfig as h, UploadResult as i, presignedUrlResultSchema as l, deleteFileInputSchema as m, StreamingBlobPayloadInputTypes as n, GetPresignedUrlInput as o, DeleteFileInput as p, UploadOptions as r, PresignedUrlResult as s, IStorageProvider as t, FileExistsInput as u };
|
|
203
|
+
//# sourceMappingURL=storage-provider.interface-YRtyYBxV.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-provider.interface-YRtyYBxV.d.mts","names":[],"sources":["../src/storage/types.ts","../src/storage/contracts/delete-file.input.ts","../src/storage/contracts/download-result.ts","../src/storage/contracts/file-exists.input.ts","../src/storage/contracts/get-presigned-url.input.ts","../src/storage/contracts/upload-file.input.ts","../src/storage/providers/storage-provider.interface.ts"],"mappings":";;;;;;;;UAIiB,YAAA;EAChB,IAAA;EACA,QAAA;EACA,QAAA;EAFA;;;;;EAQA,GAAA;EACA,MAAA;EACA,MAAA;EACA,WAAA;EACA,eAAA;EACA,IAAA;EACA,UAAA;AAAA;;;;UAMgB,kBAAA;EAChB,aAAA;EACA,SAAA;AAAA;;;;UAMgB,aAAA;EAChB,OAAA,EAAS,YAAA;EACT,kBAAA;EACA,YAAA,EAAc,kBAAA;AAAA;;;cClCF,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;KAKtB,eAAA,GAAkB,CAAA,CAAE,KAAA,QAAa,qBAAA;;;;;;;ADH7C;;UEEiB,cAAA;EFFY;;;EEM3B,QAAA,gBAAwB,cAAA,CAAe,UAAA;EAEvC,QAAA,gBAAwB,OAAA;EAExB,aAAA,gBAA6B,OAAA,CAAQ,UAAA;EFCtC;;;EEIC,WAAA;EFAD;;;EEKC,IAAA;EFCiC;;;;EEKjC,QAAA,GAAW,MAAA;AAAA;;;cC5BA,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;KAKtB,eAAA,GAAkB,CAAA,CAAE,KAAA,QAAa,qBAAA;;;cCLhC,0BAAA,EAA0B,CAAA,CAAA,SAAA;;;;;;;;;;;KAO3B,oBAAA,GAAuB,CAAA,CAAE,KAAA,QAAa,0BAAA;AAAA,cAErC,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;;;KAOzB,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;;;;;;UCb/B,aAAA;ELDY;;;EKK3B,IAAA;ELHD;;;EKOC,QAAA;ELED;;;;EKGC,QAAA,GAAW,MAAA;ELCF;;AAMX;;EKFE,OAAA;AAAA;AAAA,cAGW,kBAAA,EAAkB,CAAA,CAAA,SAAA;;;;;;;;KASnB,YAAA,GAAe,CAAA,CAAE,KAAA,QAAa,kBAAA;;;;;AL/B1C;;KMGY,8BAAA,GAAiC,qBAAA;;;;;UAM5B,gBAAA;ENChB;;;;;;;EMOC,MAAA,CAAO,IAAA,EAAM,8BAAA,EAAgC,IAAA,UAAc,OAAA,EAAS,aAAA,GAAgB,OAAA,CAAQ,YAAA;ENI7E;;;;;EMGf,QAAA,CAAS,IAAA,WAAe,OAAA,CAAQ,cAAA;ENKJ;;;;EMC5B,MAAA,CAAO,IAAA,WAAe,OAAA;ENCvB;;;;;EMMC,MAAA,CAAO,IAAA,WAAe,OAAA;;;ALvCxB;;;;;EKgDE,eAAA,CACE,IAAA,UACA,MAAA,qCACA,SAAA,WACC,OAAA,CAAQ,kBAAA;;;;;;;;;EAUX,aAAA,CACE,IAAA,EAAM,8BAAA,EACN,IAAA,UACA,OAAA,EAAS,IAAA,CAAK,aAAA;IAA2B,IAAA;EAAA,IACxC,OAAA,CAAQ,YAAA;AAAA"}
|