@visulima/storage 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +33 -14
  3. package/dist/adapter/nuxt/module.d.ts +39 -0
  4. package/dist/adapter/nuxt/module.js +93 -0
  5. package/dist/adapter/nuxt/package.json +20 -0
  6. package/dist/handler/base/base-handler-core.d.ts +91 -0
  7. package/dist/handler/base/base-handler-fetch.d.ts +76 -0
  8. package/dist/handler/base/base-handler-node.d.ts +137 -0
  9. package/dist/handler/http/fetch/index.d.ts +4 -0
  10. package/dist/handler/http/fetch/index.js +4 -0
  11. package/dist/handler/http/hono/index.d.ts +67 -0
  12. package/dist/handler/http/hono/index.js +65 -0
  13. package/dist/handler/http/nextjs/index.d.ts +61 -0
  14. package/dist/handler/http/nextjs/index.js +37 -0
  15. package/dist/handler/http/node/index.d.ts +4 -0
  16. package/dist/handler/http/node/index.js +4 -0
  17. package/dist/handler/http/solid-start/index.d.ts +60 -0
  18. package/dist/handler/http/solid-start/index.js +44 -0
  19. package/dist/handler/multipart/multipart-base.d.ts +84 -0
  20. package/dist/handler/multipart/multipart-fetch.d.ts +64 -0
  21. package/dist/handler/multipart/multipart.d.ts +49 -0
  22. package/dist/handler/rest/rest-base.d.ts +106 -0
  23. package/dist/handler/rest/rest-fetch.d.ts +88 -0
  24. package/dist/handler/rest/rest.d.ts +93 -0
  25. package/dist/handler/tus/tus-base.d.ts +152 -0
  26. package/dist/handler/tus/tus-fetch.d.ts +72 -0
  27. package/dist/handler/tus/tus.d.ts +78 -0
  28. package/dist/handler/types.d.ts +53 -0
  29. package/dist/handler/utils/request-parser.d.ts +72 -0
  30. package/dist/handler/utils/response-builder.d.ts +83 -0
  31. package/dist/handler/utils/storage-utils.d.ts +10 -0
  32. package/dist/handler/utils/stream-utils.d.ts +29 -0
  33. package/dist/handler/utils/upload-handlers.d.ts +76 -0
  34. package/dist/index.d.ts +17 -0
  35. package/dist/index.js +13 -0
  36. package/dist/metrics/index.d.ts +2 -0
  37. package/dist/metrics/no-op-metrics.d.ts +15 -0
  38. package/dist/metrics/opentelemetry-metrics.d.ts +55 -0
  39. package/dist/openapi/index.d.ts +5 -0
  40. package/dist/openapi/index.js +5 -0
  41. package/dist/openapi/rest.d.ts +7 -0
  42. package/dist/openapi/shared.d.ts +13 -0
  43. package/dist/openapi/transform.d.ts +3 -0
  44. package/dist/openapi/tus.d.ts +7 -0
  45. package/dist/openapi/xhr.d.ts +7 -0
  46. package/dist/packem_shared/AwsLightFile-tTneXZgG.js +11 -0
  47. package/dist/packem_shared/AwsLightMetaStorage-BWSOtVaN.js +4 -0
  48. package/dist/packem_shared/AwsLightStorage-Blv-GP4v.js +133 -0
  49. package/dist/packem_shared/AzureFile-CesgFzps.js +8 -0
  50. package/dist/packem_shared/AzureSMetaStorage-CFs-OYJT.js +88 -0
  51. package/dist/packem_shared/AzureStorage-B0v048hG.js +357 -0
  52. package/dist/packem_shared/BaseTransformer-C2gLib6v.js +82 -0
  53. package/dist/packem_shared/DiskStorage-BlltBst6.js +12 -0
  54. package/dist/packem_shared/DiskStorageWithChecksum-BJTmMklc.js +238 -0
  55. package/dist/packem_shared/ERRORS-D0apMqnc.js +97 -0
  56. package/dist/packem_shared/File-Bb3P23dr.js +69 -0
  57. package/dist/packem_shared/GCSConfig-vPP22kN6.js +11 -0
  58. package/dist/packem_shared/GCSFile-BIEunhAN.js +8 -0
  59. package/dist/packem_shared/GCSMetaStorage-BMFEdzJ7.js +7 -0
  60. package/dist/packem_shared/GCStorage-DnhiwaS9.js +406 -0
  61. package/dist/packem_shared/LocalMetaStorage-CZHhKkMd.js +7 -0
  62. package/dist/packem_shared/MediaTransformer-D6658DL1.js +1197 -0
  63. package/dist/packem_shared/MetaStorage-pECeFOad.js +46 -0
  64. package/dist/packem_shared/Metadata-DRLXeJ0F.js +89 -0
  65. package/dist/packem_shared/Multipart-CNFK_Okz.js +163 -0
  66. package/dist/packem_shared/Multipart-CtUL7BQw.js +128 -0
  67. package/dist/packem_shared/NetlifyBlobFile-CXzyjqrD.js +14 -0
  68. package/dist/packem_shared/NetlifyBlobMetaStorage-DxZ5aDvD.js +9 -0
  69. package/dist/packem_shared/NetlifyBlobStorage-CLPtjHqd.js +376 -0
  70. package/dist/packem_shared/NoOpMetrics-DhAk5rXc.js +10 -0
  71. package/dist/packem_shared/OpenTelemetryMetrics-BnxhqIaH.js +67 -0
  72. package/dist/packem_shared/Rest-CAOAEkOj.js +267 -0
  73. package/dist/packem_shared/Rest-DNuLwBrK.js +228 -0
  74. package/dist/packem_shared/S3File-DZiyk9Qt.js +11 -0
  75. package/dist/packem_shared/S3MetaStorage-Dz9aDabA.js +76 -0
  76. package/dist/packem_shared/S3Storage-DHmTk-hU.js +316 -0
  77. package/dist/packem_shared/TUS_RESUMABLE-GJzZ9R-f.js +434 -0
  78. package/dist/packem_shared/Tus-B8PmlMgR.js +200 -0
  79. package/dist/packem_shared/Tus-C4F1aYOl.js +195 -0
  80. package/dist/packem_shared/ValidationError-BfF1aE4h.js +26 -0
  81. package/dist/packem_shared/VercelBlobFile-BCg4aTEq.js +18 -0
  82. package/dist/packem_shared/VercelBlobMetaStorage-Bd9F-VFm.js +9 -0
  83. package/dist/packem_shared/VercelBlobStorage-DD9LMOS6.js +261 -0
  84. package/dist/packem_shared/_commonjsHelpers-B85MJLTf.js +5 -0
  85. package/dist/packem_shared/aws-light-meta-storage-DKJBgbR6.js +446 -0
  86. package/dist/packem_shared/backblaze-BlMnIcBC.js +20 -0
  87. package/dist/packem_shared/base-handler-core-BKuf4YLT.js +303 -0
  88. package/dist/packem_shared/base-handler-fetch-Cr0hLiqg.js +291 -0
  89. package/dist/packem_shared/base-handler-node-gk5aN9Cx.js +730 -0
  90. package/dist/packem_shared/cache-B88MXQ_2.js +18 -0
  91. package/dist/packem_shared/cloudflare-Bi1q8wXE.js +21 -0
  92. package/dist/packem_shared/defaultCloudStorageFileNameValidation-DUuacjWv.js +11 -0
  93. package/dist/packem_shared/digitalOcean-CWQRJM3L.js +21 -0
  94. package/dist/packem_shared/disk-storage-Bh2wy3YW.js +810 -0
  95. package/dist/packem_shared/gcs-meta-storage-0tgMNnPO.js +158 -0
  96. package/dist/packem_shared/has-content-CY66ehMK.js +3 -0
  97. package/dist/packem_shared/headers-DoS5nwM-.js +3220 -0
  98. package/dist/packem_shared/is-expired-CTThU1q5.js +8 -0
  99. package/dist/packem_shared/isRetryableError-Dycp7127.js +82 -0
  100. package/dist/packem_shared/isValidMediaType-BeDgiObq.js +35 -0
  101. package/dist/packem_shared/local-meta-storage-By-3SNBI.js +649 -0
  102. package/dist/packem_shared/minio-C2YBZQOw.js +22 -0
  103. package/dist/packem_shared/multipart-base-B3i67SSX.js +102 -0
  104. package/dist/packem_shared/part-match-BMNqHDYD.js +96 -0
  105. package/dist/packem_shared/path-CR6YkPXX-7R1-9CMk.js +161 -0
  106. package/dist/packem_shared/response-builder-BtnRiBUI.js +45 -0
  107. package/dist/packem_shared/rest-base-GRCcnan7.js +457 -0
  108. package/dist/packem_shared/restOpenApiSpec-CwcHHY2C.js +800 -0
  109. package/dist/packem_shared/s3-base-storage-C1DIHTYY.js +510 -0
  110. package/dist/packem_shared/sharedGet-Cpo7QUyu.js +1019 -0
  111. package/dist/packem_shared/storage-C6NSXb8h.js +1175 -0
  112. package/dist/packem_shared/tigris-Hac8TKnX.js +21 -0
  113. package/dist/packem_shared/transformOpenApiSpec-DWM5WtnN.js +975 -0
  114. package/dist/packem_shared/tusOpenApiSpec-6ohiToBy.js +740 -0
  115. package/dist/packem_shared/update-size-CCGm6i1J.js +8 -0
  116. package/dist/packem_shared/validator-BeX_lJet.js +78 -0
  117. package/dist/packem_shared/waitForStorage-Cscw85sx.js +18 -0
  118. package/dist/packem_shared/wasabi-DIyflHSd.js +21 -0
  119. package/dist/packem_shared/xhrOpenApiSpec-DS17brnx.js +264 -0
  120. package/dist/storage/aws/clients/backblaze.d.ts +12 -0
  121. package/dist/storage/aws/clients/cloudflare.d.ts +13 -0
  122. package/dist/storage/aws/clients/digital-ocean.d.ts +12 -0
  123. package/dist/storage/aws/clients/index.d.ts +6 -0
  124. package/dist/storage/aws/clients/index.js +6 -0
  125. package/dist/storage/aws/clients/minio.d.ts +13 -0
  126. package/dist/storage/aws/clients/tigris.d.ts +12 -0
  127. package/dist/storage/aws/clients/types.d.ts +95 -0
  128. package/dist/storage/aws/clients/wasabi.d.ts +12 -0
  129. package/dist/storage/aws/index.d.ts +4 -0
  130. package/dist/storage/aws/index.js +3 -0
  131. package/dist/storage/aws/s3-base-storage.d.ts +248 -0
  132. package/dist/storage/aws/s3-client-adapter.d.ts +110 -0
  133. package/dist/storage/aws/s3-file.d.ts +10 -0
  134. package/dist/storage/aws/s3-meta-storage.d.ts +15 -0
  135. package/dist/storage/aws/s3-storage.d.ts +70 -0
  136. package/dist/storage/aws/types.d.ts +119 -0
  137. package/dist/storage/aws-light/aws-light-api-adapter.d.ts +130 -0
  138. package/dist/storage/aws-light/aws-light-file.d.ts +10 -0
  139. package/dist/storage/aws-light/aws-light-meta-storage.d.ts +19 -0
  140. package/dist/storage/aws-light/aws-light-storage.d.ts +65 -0
  141. package/dist/storage/aws-light/index.d.ts +4 -0
  142. package/dist/storage/aws-light/index.js +3 -0
  143. package/dist/storage/aws-light/types.d.ts +37 -0
  144. package/dist/storage/azure/azure-file.d.ts +6 -0
  145. package/dist/storage/azure/azure-meta-storage.d.ts +15 -0
  146. package/dist/storage/azure/azure-storage.d.ts +69 -0
  147. package/dist/storage/azure/index.d.ts +4 -0
  148. package/dist/storage/azure/index.js +3 -0
  149. package/dist/storage/azure/types.d.ts +62 -0
  150. package/dist/storage/gcs/fetch-error.d.ts +11 -0
  151. package/dist/storage/gcs/gcs-config.d.ts +2 -0
  152. package/dist/storage/gcs/gcs-file.d.ts +6 -0
  153. package/dist/storage/gcs/gcs-meta-storage.d.ts +27 -0
  154. package/dist/storage/gcs/gcs-storage.d.ts +91 -0
  155. package/dist/storage/gcs/index.d.ts +5 -0
  156. package/dist/storage/gcs/index.js +4 -0
  157. package/dist/storage/gcs/types.d.ts +55 -0
  158. package/dist/storage/gcs/utils.d.ts +7 -0
  159. package/dist/storage/local/disk-storage-with-checksum.d.ts +15 -0
  160. package/dist/storage/local/disk-storage.d.ts +135 -0
  161. package/dist/storage/local/index.d.ts +4 -0
  162. package/dist/storage/local/index.js +3 -0
  163. package/dist/storage/local/local-meta-storage.d.ts +32 -0
  164. package/dist/storage/meta-storage.d.ts +30 -0
  165. package/dist/storage/netlify-blob/index.d.ts +4 -0
  166. package/dist/storage/netlify-blob/index.js +3 -0
  167. package/dist/storage/netlify-blob/netlify-blob-file.d.ts +12 -0
  168. package/dist/storage/netlify-blob/netlify-blob-meta-storage.d.ts +7 -0
  169. package/dist/storage/netlify-blob/netlify-blob-storage.d.ts +93 -0
  170. package/dist/storage/netlify-blob/types.d.ts +30 -0
  171. package/dist/storage/storage.d.ts +353 -0
  172. package/dist/storage/types.d.ts +221 -0
  173. package/dist/storage/utils/file/file.d.ts +25 -0
  174. package/dist/storage/utils/file/get-file-status.d.ts +9 -0
  175. package/dist/storage/utils/file/has-content.d.ts +9 -0
  176. package/dist/storage/utils/file/index.d.ts +10 -0
  177. package/dist/storage/utils/file/is-expired.d.ts +8 -0
  178. package/dist/storage/utils/file/metadata.d.ts +18 -0
  179. package/dist/storage/utils/file/part-match.d.ts +11 -0
  180. package/dist/storage/utils/file/types.d.ts +37 -0
  181. package/dist/storage/utils/file/update-metadata.d.ts +10 -0
  182. package/dist/storage/utils/file/update-size.d.ts +10 -0
  183. package/dist/storage/vercel-blob/index.d.ts +4 -0
  184. package/dist/storage/vercel-blob/index.js +3 -0
  185. package/dist/storage/vercel-blob/types.d.ts +32 -0
  186. package/dist/storage/vercel-blob/vercel-blob-file.d.ts +16 -0
  187. package/dist/storage/vercel-blob/vercel-blob-meta-storage.d.ts +7 -0
  188. package/dist/storage/vercel-blob/vercel-blob-storage.d.ts +76 -0
  189. package/dist/transformer/audio-transformer.d.ts +128 -0
  190. package/dist/transformer/audio-transformer.js +278 -0
  191. package/dist/transformer/base-transformer.d.ts +63 -0
  192. package/dist/transformer/image-transformer.d.ts +571 -0
  193. package/dist/transformer/image-transformer.js +1100 -0
  194. package/dist/transformer/index.d.ts +5 -0
  195. package/dist/transformer/index.js +4 -0
  196. package/dist/transformer/media-transformer.d.ts +332 -0
  197. package/dist/transformer/types.d.ts +652 -0
  198. package/dist/transformer/utils.d.ts +33 -0
  199. package/dist/transformer/validation-error.d.ts +23 -0
  200. package/dist/transformer/video-transformer.d.ts +145 -0
  201. package/dist/transformer/video-transformer.js +310 -0
  202. package/dist/utils/cache.d.ts +32 -0
  203. package/dist/utils/chunked-upload.d.ts +65 -0
  204. package/dist/utils/detect-file-type.d.ts +28 -0
  205. package/dist/utils/errors.d.ts +74 -0
  206. package/dist/utils/file-path-url-matcher.d.ts +18 -0
  207. package/dist/utils/headers.d.ts +111 -0
  208. package/dist/utils/http.d.ts +92 -0
  209. package/dist/utils/locker.d.ts +26 -0
  210. package/dist/utils/pipes/stream-checksum.d.ts +47 -0
  211. package/dist/utils/pipes/stream-length.d.ts +22 -0
  212. package/dist/utils/primitives/get-last-one.d.ts +3 -0
  213. package/dist/utils/primitives/is-record.d.ts +2 -0
  214. package/dist/utils/primitives/map-values.d.ts +9 -0
  215. package/dist/utils/primitives/pick.d.ts +2 -0
  216. package/dist/utils/primitives/to-milliseconds.d.ts +12 -0
  217. package/dist/utils/primitives/to-seconds.d.ts +12 -0
  218. package/dist/utils/range-checksum.d.ts +33 -0
  219. package/dist/utils/range-hasher.d.ts +46 -0
  220. package/dist/utils/retry.d.ts +64 -0
  221. package/dist/utils/types.d.ts +108 -0
  222. package/dist/utils/validation-error.d.ts +22 -0
  223. package/dist/utils/validator.d.ts +36 -0
  224. package/package.json +5 -5
@@ -0,0 +1,316 @@
1
+ import { Readable } from 'node:stream';
2
+ import { CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand, AbortMultipartUploadCommand, ListPartsCommand, GetObjectCommand, HeadObjectCommand, DeleteObjectCommand, CopyObjectCommand, ListObjectsV2Command, waitUntilBucketExists, S3Client } from '@aws-sdk/client-s3';
3
+ import { fromIni } from '@aws-sdk/credential-providers';
4
+ import { S as S3BaseStorage } from './s3-base-storage-C1DIHTYY.js';
5
+ import { ReadableStream } from 'node:stream/web';
6
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
7
+ import S3File from './S3File-DZiyk9Qt.js';
8
+ import S3MetaStorage from './S3MetaStorage-Dz9aDabA.js';
9
+
10
+ class S3ClientAdapter {
11
+ constructor(client, _bucket) {
12
+ this.client = client;
13
+ }
14
+ async createMultipartUpload(params) {
15
+ const command = new CreateMultipartUploadCommand({
16
+ ACL: params.ACL,
17
+ Bucket: params.Bucket,
18
+ ContentType: params.ContentType,
19
+ Key: params.Key,
20
+ Metadata: params.Metadata
21
+ });
22
+ const response = await this.client.send(command);
23
+ if (!response.UploadId) {
24
+ throw new Error("Failed to create multipart upload");
25
+ }
26
+ return { UploadId: response.UploadId };
27
+ }
28
+ async uploadPart(params) {
29
+ const body = params.Body instanceof ReadableStream ? Readable.fromWeb(params.Body) : params.Body;
30
+ const command = new UploadPartCommand({
31
+ Body: body,
32
+ Bucket: params.Bucket,
33
+ ContentLength: params.ContentLength,
34
+ ContentMD5: params.ContentMD5,
35
+ Key: params.Key,
36
+ PartNumber: params.PartNumber,
37
+ UploadId: params.UploadId
38
+ });
39
+ const response = await this.client.send(command);
40
+ if (!response.ETag) {
41
+ throw new Error("Failed to upload part");
42
+ }
43
+ return { ETag: response.ETag };
44
+ }
45
+ async completeMultipartUpload(params) {
46
+ const command = new CompleteMultipartUploadCommand({
47
+ Bucket: params.Bucket,
48
+ Key: params.Key,
49
+ MultipartUpload: {
50
+ Parts: params.Parts.map(({ ETag, PartNumber }) => {
51
+ return { ETag, PartNumber };
52
+ })
53
+ },
54
+ UploadId: params.UploadId
55
+ });
56
+ const response = await this.client.send(command);
57
+ if (!response.Location) {
58
+ throw new Error("Failed to complete multipart upload");
59
+ }
60
+ return {
61
+ ETag: response.ETag,
62
+ Location: response.Location
63
+ };
64
+ }
65
+ async abortMultipartUpload(params) {
66
+ const command = new AbortMultipartUploadCommand({
67
+ Bucket: params.Bucket,
68
+ Key: params.Key,
69
+ UploadId: params.UploadId
70
+ });
71
+ await this.client.send(command);
72
+ }
73
+ async listParts(params) {
74
+ const command = new ListPartsCommand({
75
+ Bucket: params.Bucket,
76
+ Key: params.Key,
77
+ UploadId: params.UploadId
78
+ });
79
+ const response = await this.client.send(command);
80
+ const parts = [];
81
+ if (response.Parts) {
82
+ for (const part of response.Parts) {
83
+ if (part.ETag && part.PartNumber) {
84
+ parts.push({
85
+ ETag: part.ETag,
86
+ PartNumber: part.PartNumber,
87
+ Size: part.Size
88
+ });
89
+ }
90
+ }
91
+ }
92
+ return { Parts: parts.length > 0 ? parts : void 0 };
93
+ }
94
+ async getObject(params) {
95
+ const command = new GetObjectCommand({
96
+ Bucket: params.Bucket,
97
+ Key: params.Key
98
+ });
99
+ const response = await this.client.send(command);
100
+ let body;
101
+ if (response.Body) {
102
+ const sdkStream = response.Body;
103
+ if (sdkStream instanceof Readable) {
104
+ body = sdkStream;
105
+ } else if (typeof sdkStream === "object" && "transform" in sdkStream && sdkStream instanceof ReadableStream) {
106
+ body = sdkStream;
107
+ } else {
108
+ body = Readable.from(sdkStream);
109
+ }
110
+ }
111
+ return {
112
+ Body: body,
113
+ ContentLength: response.ContentLength,
114
+ ContentType: response.ContentType,
115
+ ETag: response.ETag,
116
+ Expires: response.Expires,
117
+ LastModified: response.LastModified,
118
+ Metadata: response.Metadata
119
+ };
120
+ }
121
+ async headObject(params) {
122
+ const command = new HeadObjectCommand({
123
+ Bucket: params.Bucket,
124
+ Key: params.Key
125
+ });
126
+ const response = await this.client.send(command);
127
+ return {
128
+ ContentLength: response.ContentLength,
129
+ ContentType: response.ContentType,
130
+ ETag: response.ETag,
131
+ Expires: response.Expires,
132
+ LastModified: response.LastModified
133
+ };
134
+ }
135
+ async deleteObject(params) {
136
+ const command = new DeleteObjectCommand({
137
+ Bucket: params.Bucket,
138
+ Key: params.Key
139
+ });
140
+ await this.client.send(command);
141
+ }
142
+ async copyObject(params) {
143
+ const commandInput = {
144
+ Bucket: params.Bucket,
145
+ CopySource: params.CopySource,
146
+ Key: params.Key
147
+ };
148
+ if (params.StorageClass) {
149
+ commandInput.StorageClass = params.StorageClass;
150
+ }
151
+ const command = new CopyObjectCommand(commandInput);
152
+ await this.client.send(command);
153
+ }
154
+ async listObjectsV2(params) {
155
+ const command = new ListObjectsV2Command({
156
+ Bucket: params.Bucket,
157
+ ContinuationToken: params.ContinuationToken,
158
+ MaxKeys: params.MaxKeys
159
+ });
160
+ const response = await this.client.send(command);
161
+ return {
162
+ Contents: response.Contents?.map((item) => {
163
+ return {
164
+ Key: item.Key,
165
+ LastModified: item.LastModified
166
+ };
167
+ }),
168
+ IsTruncated: response.IsTruncated,
169
+ NextContinuationToken: response.NextContinuationToken
170
+ };
171
+ }
172
+ async getPresignedUrl(params) {
173
+ const command = new UploadPartCommand({
174
+ Bucket: params.Bucket,
175
+ Key: params.Key,
176
+ PartNumber: params.PartNumber,
177
+ UploadId: params.UploadId
178
+ });
179
+ return getSignedUrl(this.client, command, { expiresIn: params.expiresIn });
180
+ }
181
+ async checkBucketAccess(params) {
182
+ await waitUntilBucketExists({ client: this.client, maxWaitTime: 30 }, { Bucket: params.Bucket });
183
+ }
184
+ }
185
+
186
+ class S3Storage extends S3BaseStorage {
187
+ static name = "s3";
188
+ s3Api;
189
+ constructor(config) {
190
+ const { bucket = process.env.S3_BUCKET, region = process.env.S3_REGION } = config;
191
+ if (!bucket) {
192
+ throw new Error("S3 bucket is not defined");
193
+ }
194
+ if (!region) {
195
+ throw new Error("S3 region is not defined");
196
+ }
197
+ config.region = region;
198
+ const keyFile = config.keyFile || process.env.S3_KEYFILE;
199
+ if (keyFile) {
200
+ config.credentials = fromIni({ configFilepath: keyFile });
201
+ }
202
+ const client = new S3Client(config);
203
+ super({
204
+ bucket,
205
+ clientDirectUpload: config.clientDirectUpload,
206
+ expiration: config.expiration?.maxAge ? { maxAge: String(config.expiration.maxAge) } : void 0,
207
+ filename: config.filename,
208
+ logger: config.logger,
209
+ metaStorage: config.metaStorage,
210
+ metaStorageConfig: config.metaStorageConfig ? { ...config.metaStorageConfig, ...config } : { ...config },
211
+ partSize: config.partSize,
212
+ retryConfig: {
213
+ ...config.retryConfig,
214
+ shouldRetry: (error) => {
215
+ const errorWithMetadata = error;
216
+ if (errorWithMetadata.$metadata) {
217
+ const statusCode = errorWithMetadata.$metadata.httpStatusCode;
218
+ if (statusCode && [408, 429, 500, 502, 503, 504].includes(statusCode)) {
219
+ return true;
220
+ }
221
+ if (errorWithMetadata.$fault === "server") {
222
+ return true;
223
+ }
224
+ }
225
+ return errorWithMetadata.retryable ?? false;
226
+ }
227
+ }
228
+ });
229
+ this.s3Api = new S3ClientAdapter(client, bucket);
230
+ const { metaStorage, metaStorageConfig } = config;
231
+ if (!metaStorage) {
232
+ const metaConfig = { ...config, ...metaStorageConfig, logger: this.logger };
233
+ const localMeta = "directory" in metaConfig;
234
+ if (!localMeta) {
235
+ this.meta = new S3MetaStorage(metaConfig);
236
+ }
237
+ }
238
+ if (this.config.clientDirectUpload) {
239
+ this.onCreate = async () => {
240
+ };
241
+ }
242
+ }
243
+ /**
244
+ * Normalizes AWS S3 errors with S3-specific context.
245
+ */
246
+ normalizeError(error) {
247
+ if (error.$metadata) {
248
+ return {
249
+ code: error.Code || error.name,
250
+ message: error.message,
251
+ name: error.name,
252
+ statusCode: error.$metadata.httpStatusCode || 500
253
+ };
254
+ }
255
+ return super.normalizeError(error);
256
+ }
257
+ async update({ id }, metadata) {
258
+ if (this.config.clientDirectUpload) {
259
+ const file = await this.getMeta(id);
260
+ return this.buildPresigned({ ...file, ...metadata });
261
+ }
262
+ return super.update({ id }, metadata);
263
+ }
264
+ async getStream({ id }) {
265
+ return this.instrumentOperation("getStream", async () => {
266
+ const s3Api = this.getS3Api();
267
+ const { Body, ContentLength, ContentType, ETag, Expires, LastModified } = await this.retry(
268
+ () => s3Api.getObject({
269
+ Bucket: this.bucket,
270
+ Key: id
271
+ })
272
+ );
273
+ await this.checkIfExpired({ expiredAt: Expires });
274
+ const stream = Body;
275
+ const readableStream = new Readable({
276
+ read() {
277
+ stream.on("data", (chunk) => {
278
+ this.push(chunk);
279
+ });
280
+ stream.on("end", () => {
281
+ this.push(null);
282
+ });
283
+ stream.on("error", (error) => {
284
+ this.destroy(error);
285
+ });
286
+ }
287
+ });
288
+ return {
289
+ headers: {
290
+ "Content-Length": ContentLength?.toString() ?? "0",
291
+ "Content-Type": ContentType,
292
+ ...ETag && { ETag },
293
+ ...Expires && { "X-Upload-Expires": Expires.toString() },
294
+ ...LastModified && { "Last-Modified": LastModified.toString() }
295
+ },
296
+ size: Number(ContentLength),
297
+ stream: readableStream
298
+ };
299
+ });
300
+ }
301
+ getS3Api() {
302
+ return this.s3Api;
303
+ }
304
+ // eslint-disable-next-line class-methods-use-this
305
+ getFileClass() {
306
+ return S3File;
307
+ }
308
+ getAcl() {
309
+ return this.config.acl;
310
+ }
311
+ async accessCheck(_maxWaitTime = 30) {
312
+ await this.s3Api.checkBucketAccess({ Bucket: this.bucket });
313
+ }
314
+ }
315
+
316
+ export { S3Storage as default };