@visulima/storage 1.0.0-alpha.17 → 1.0.0-alpha.19

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 (185) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE.md +3 -0
  3. package/dist/adapter/nuxt/module.d.ts +3 -3
  4. package/dist/adapter/nuxt/module.js +1 -93
  5. package/dist/handler/http/fetch/index.d.ts +6 -6
  6. package/dist/handler/http/fetch/index.js +1 -4
  7. package/dist/handler/http/hono/index.d.ts +3 -3
  8. package/dist/handler/http/hono/index.js +1 -65
  9. package/dist/handler/http/nextjs/index.d.ts +4 -4
  10. package/dist/handler/http/nextjs/index.js +1 -37
  11. package/dist/handler/http/node/index.d.ts +6 -6
  12. package/dist/handler/http/node/index.js +1 -8
  13. package/dist/handler/http/solid-start/index.d.ts +4 -4
  14. package/dist/handler/http/solid-start/index.js +1 -44
  15. package/dist/index.js +1 -13
  16. package/dist/openapi/index.js +1 -5
  17. package/dist/packem_shared/AwsLightFile-BTLiRxXj.js +1 -0
  18. package/dist/packem_shared/AwsLightMetaStorage-DHz1nf_H.js +1 -0
  19. package/dist/packem_shared/AwsLightStorage-CA9cdfJ6.js +1 -0
  20. package/dist/packem_shared/AzureFile-BKHru1zB.js +1 -0
  21. package/dist/packem_shared/AzureSMetaStorage-BqA4jUDJ.js +1 -0
  22. package/dist/packem_shared/AzureStorage-BKUjCymW.js +1 -0
  23. package/dist/packem_shared/BaseTransformer-D68eLyz1.js +1 -0
  24. package/dist/packem_shared/DiskStorage-DNjpDMX9.js +1 -0
  25. package/dist/packem_shared/DiskStorageWithChecksum-Bb6JX_tC.js +1 -0
  26. package/dist/packem_shared/ERRORS-B9jkvKwx.js +1 -0
  27. package/dist/packem_shared/File-alcSNpLq.js +1 -0
  28. package/dist/packem_shared/GCSConfig-BQ0OpVhe.js +1 -0
  29. package/dist/packem_shared/GCSFile-CHjX_fJk.js +1 -0
  30. package/dist/packem_shared/GCSMetaStorage-CpxQ8wM9.js +1 -0
  31. package/dist/packem_shared/GCStorage-DAg1V55T.js +1 -0
  32. package/dist/packem_shared/LocalMetaStorage-BWuFvWn4.js +1 -0
  33. package/dist/packem_shared/MediaTransformer-2C8MJeAg.js +1 -0
  34. package/dist/packem_shared/MetaStorage-Y4m1dWgd.js +1 -0
  35. package/dist/packem_shared/Metadata-B6Ir0KO7.js +1 -0
  36. package/dist/packem_shared/Multipart-Bd9YFFn0.js +1 -0
  37. package/dist/packem_shared/Multipart-D5bcEvga.js +1 -0
  38. package/dist/packem_shared/NetlifyBlobFile-CpzkMKng.js +1 -0
  39. package/dist/packem_shared/NetlifyBlobMetaStorage-dD0oBLom.js +1 -0
  40. package/dist/packem_shared/NetlifyBlobStorage-ByTwCN-h.js +1 -0
  41. package/dist/packem_shared/NoOpMetrics-Dky06sf1.js +1 -0
  42. package/dist/packem_shared/OpenTelemetryMetrics-9uxQMSlg.js +1 -0
  43. package/dist/packem_shared/Rest-CYEBbtCD.js +1 -0
  44. package/dist/packem_shared/Rest-DoonVU7B.js +1 -0
  45. package/dist/packem_shared/S3File-Du6wP0Sz.js +1 -0
  46. package/dist/packem_shared/S3MetaStorage-vcriiosn.js +1 -0
  47. package/dist/packem_shared/S3Storage-Fx6-OSc-.js +1 -0
  48. package/dist/packem_shared/TUS_RESUMABLE-B7KtPVeC.js +1 -0
  49. package/dist/packem_shared/Tus-Bd_2Ki2G.js +1 -0
  50. package/dist/packem_shared/Tus-CUBCkuPE.js +1 -0
  51. package/dist/packem_shared/ValidationError-D8KKJiKA.js +1 -0
  52. package/dist/packem_shared/VercelBlobFile-CL9MjKcY.js +1 -0
  53. package/dist/packem_shared/VercelBlobMetaStorage-BsOTx-Su.js +1 -0
  54. package/dist/packem_shared/VercelBlobStorage-kNkk5Cn4.js +1 -0
  55. package/dist/packem_shared/_commonjsHelpers-D6W6KoPK.js +1 -0
  56. package/dist/packem_shared/aws-light-meta-storage-TPyQwLvk.js +4 -0
  57. package/dist/packem_shared/backblaze-DEflv87m.js +1 -0
  58. package/dist/packem_shared/base-handler-core-DaggCVsq.js +1 -0
  59. package/dist/packem_shared/base-handler-fetch-DnarP64X.js +1 -0
  60. package/dist/packem_shared/base-handler-node-BTes6sql.js +1 -0
  61. package/dist/packem_shared/cache-qV_5Umeq.js +1 -0
  62. package/dist/packem_shared/cloudflare-DLAeQvgD.js +1 -0
  63. package/dist/packem_shared/defaultCloudStorageFileNameValidation-yiM9GxHr.js +1 -0
  64. package/dist/packem_shared/digitalOcean-nhZUds87.js +1 -0
  65. package/dist/packem_shared/disk-storage-BvdK4bqF.js +5 -0
  66. package/dist/packem_shared/gcs-meta-storage-CvGkpzVE.js +1 -0
  67. package/dist/packem_shared/has-content-Bx2p8Okx.js +1 -0
  68. package/dist/packem_shared/headers-DC2MEOrK.js +27 -0
  69. package/dist/packem_shared/is-expired-1JuZjDtb.js +1 -0
  70. package/dist/packem_shared/isRetryableError-DQNSZiBc.js +1 -0
  71. package/dist/packem_shared/isValidMediaType-B-2UKjZx.js +1 -0
  72. package/dist/packem_shared/local-meta-storage-Bkwqi_gi.js +1 -0
  73. package/dist/packem_shared/{media-transformer.d-ChmjTvjc.d.ts → media-transformer.d-CY9CsEOe.d.ts} +1 -1
  74. package/dist/packem_shared/minio-BWwgGXeE.js +1 -0
  75. package/dist/packem_shared/multipart-base-C6OjBwMS.js +1 -0
  76. package/dist/packem_shared/part-match-DqD5U7An.js +1 -0
  77. package/dist/packem_shared/path-D7rMc9nq-B718mbm6.js +1 -0
  78. package/dist/packem_shared/response-builder-Wdo_fvcF.js +1 -0
  79. package/dist/packem_shared/rest-base-B2Dv7esY.js +1 -0
  80. package/dist/packem_shared/restOpenApiSpec-PaIVbESh.js +1 -0
  81. package/dist/packem_shared/s3-base-storage-xHZNtsGe.js +1 -0
  82. package/dist/packem_shared/sharedGet-Ce7WGAsc.js +1 -0
  83. package/dist/packem_shared/storage-m_Cxgiih.js +1 -0
  84. package/dist/packem_shared/tigris-DZoyrMNd.js +1 -0
  85. package/dist/packem_shared/transformOpenApiSpec-C0vEbDTO.js +1 -0
  86. package/dist/packem_shared/{tus-base.d-CpLzyd-S.d.ts → tus-base.d-DNZRXR9X.d.ts} +2 -2
  87. package/dist/packem_shared/tusOpenApiSpec-DF0-hlWV.js +1 -0
  88. package/dist/packem_shared/{types.d-DBjmJvIT.d.ts → types.d-BCN94sB_.d.ts} +1 -1
  89. package/dist/packem_shared/{types.d-DviSTLOg.d.ts → types.d-D4caL2Fp.d.ts} +1 -1
  90. package/dist/packem_shared/update-size-DANV7aa2.js +1 -0
  91. package/dist/packem_shared/validator-DK41xp8N.js +1 -0
  92. package/dist/packem_shared/waitForStorage-ChSBLhLc.js +1 -0
  93. package/dist/packem_shared/wasabi-Dmce4x9s.js +1 -0
  94. package/dist/packem_shared/xhrOpenApiSpec-nyoboz83.js +1 -0
  95. package/dist/storage/aws/clients/index.js +1 -6
  96. package/dist/storage/aws/index.js +1 -3
  97. package/dist/storage/aws-light/index.js +1 -3
  98. package/dist/storage/azure/index.js +1 -3
  99. package/dist/storage/gcs/index.js +1 -4
  100. package/dist/storage/local/index.js +1 -3
  101. package/dist/storage/netlify-blob/index.js +1 -3
  102. package/dist/storage/vercel-blob/index.js +1 -3
  103. package/dist/transformer/audio-transformer.d.ts +1 -1
  104. package/dist/transformer/audio-transformer.js +1 -278
  105. package/dist/transformer/image-transformer.d.ts +1 -1
  106. package/dist/transformer/image-transformer.js +1 -1100
  107. package/dist/transformer/index.d.ts +2 -2
  108. package/dist/transformer/index.js +1 -4
  109. package/dist/transformer/video-transformer.d.ts +1 -1
  110. package/dist/transformer/video-transformer.js +1 -310
  111. package/package.json +18 -18
  112. package/dist/packem_shared/AwsLightFile-C-Nd5rtl.js +0 -11
  113. package/dist/packem_shared/AwsLightMetaStorage-BIDb5EPg.js +0 -4
  114. package/dist/packem_shared/AwsLightStorage-CMuKw4bI.js +0 -133
  115. package/dist/packem_shared/AzureFile-C0kug4w4.js +0 -8
  116. package/dist/packem_shared/AzureSMetaStorage-BEbXX9Uk.js +0 -89
  117. package/dist/packem_shared/AzureStorage-98-LRZ1e.js +0 -359
  118. package/dist/packem_shared/BaseTransformer-9965D4pb.js +0 -83
  119. package/dist/packem_shared/DiskStorage-COMe_G42.js +0 -12
  120. package/dist/packem_shared/DiskStorageWithChecksum-BVaaZiyS.js +0 -249
  121. package/dist/packem_shared/ERRORS-D0apMqnc.js +0 -97
  122. package/dist/packem_shared/File-CPUhj3DI.js +0 -69
  123. package/dist/packem_shared/GCSConfig-vPP22kN6.js +0 -11
  124. package/dist/packem_shared/GCSFile-DaDiCKE2.js +0 -8
  125. package/dist/packem_shared/GCSMetaStorage-BygVH0Ee.js +0 -7
  126. package/dist/packem_shared/GCStorage-4hSx_bN1.js +0 -410
  127. package/dist/packem_shared/LocalMetaStorage-DvnZqf61.js +0 -7
  128. package/dist/packem_shared/MediaTransformer-BRRqYA0E.js +0 -1202
  129. package/dist/packem_shared/MetaStorage-pECeFOad.js +0 -46
  130. package/dist/packem_shared/Metadata-DRLXeJ0F.js +0 -89
  131. package/dist/packem_shared/Multipart-BzzvNxt4.js +0 -128
  132. package/dist/packem_shared/Multipart-DLtFLQ8s.js +0 -163
  133. package/dist/packem_shared/NetlifyBlobFile-CfyJtGWN.js +0 -14
  134. package/dist/packem_shared/NetlifyBlobMetaStorage-eJT6RFy9.js +0 -9
  135. package/dist/packem_shared/NetlifyBlobStorage-nPv7iIAG.js +0 -376
  136. package/dist/packem_shared/NoOpMetrics-DhAk5rXc.js +0 -10
  137. package/dist/packem_shared/OpenTelemetryMetrics-BnxhqIaH.js +0 -67
  138. package/dist/packem_shared/Rest-DEa7IA9R.js +0 -267
  139. package/dist/packem_shared/Rest-qhMbCn5a.js +0 -228
  140. package/dist/packem_shared/S3File-BXCuJaQZ.js +0 -11
  141. package/dist/packem_shared/S3MetaStorage-yT4CznlV.js +0 -77
  142. package/dist/packem_shared/S3Storage-wi5XT-yu.js +0 -317
  143. package/dist/packem_shared/TUS_RESUMABLE-Dtfsffnj.js +0 -434
  144. package/dist/packem_shared/Tus-Ck0Hdle5.js +0 -195
  145. package/dist/packem_shared/Tus-_0vCdHyB.js +0 -200
  146. package/dist/packem_shared/ValidationError-BfF1aE4h.js +0 -26
  147. package/dist/packem_shared/VercelBlobFile-DkFIIb9Q.js +0 -18
  148. package/dist/packem_shared/VercelBlobMetaStorage-DjFmi4vp.js +0 -9
  149. package/dist/packem_shared/VercelBlobStorage-CmMgiDgr.js +0 -261
  150. package/dist/packem_shared/_commonjsHelpers-BqLXS_qQ.js +0 -5
  151. package/dist/packem_shared/aws-light-meta-storage-BGZEiY3y.js +0 -447
  152. package/dist/packem_shared/backblaze-BlMnIcBC.js +0 -20
  153. package/dist/packem_shared/base-handler-core-lVB-D59L.js +0 -306
  154. package/dist/packem_shared/base-handler-fetch-CitgN-Aw.js +0 -291
  155. package/dist/packem_shared/base-handler-node-BiO2DF87.js +0 -731
  156. package/dist/packem_shared/cache-B88MXQ_2.js +0 -18
  157. package/dist/packem_shared/cloudflare-Bi1q8wXE.js +0 -21
  158. package/dist/packem_shared/defaultCloudStorageFileNameValidation-Brw40ZEP.js +0 -11
  159. package/dist/packem_shared/digitalOcean-CWQRJM3L.js +0 -21
  160. package/dist/packem_shared/disk-storage-D9RfoKjW.js +0 -832
  161. package/dist/packem_shared/gcs-meta-storage-8FovEDbW.js +0 -159
  162. package/dist/packem_shared/has-content-CY66ehMK.js +0 -3
  163. package/dist/packem_shared/headers-YLRp1dLo.js +0 -1318
  164. package/dist/packem_shared/is-expired-CTThU1q5.js +0 -8
  165. package/dist/packem_shared/isRetryableError-Dycp7127.js +0 -82
  166. package/dist/packem_shared/isValidMediaType-BeDgiObq.js +0 -35
  167. package/dist/packem_shared/local-meta-storage-D-pPc3FI.js +0 -658
  168. package/dist/packem_shared/minio-C2YBZQOw.js +0 -22
  169. package/dist/packem_shared/multipart-base-C994naBi.js +0 -102
  170. package/dist/packem_shared/part-match-Dt738Ddb.js +0 -96
  171. package/dist/packem_shared/path-aV9lMdcn-DMU5H1-h.js +0 -162
  172. package/dist/packem_shared/response-builder-BtnRiBUI.js +0 -45
  173. package/dist/packem_shared/rest-base-k1ory8uB.js +0 -457
  174. package/dist/packem_shared/restOpenApiSpec-BBJ_SiPE.js +0 -800
  175. package/dist/packem_shared/s3-base-storage-zUO8u8Cp.js +0 -510
  176. package/dist/packem_shared/sharedGet-CkSLSnMd.js +0 -1022
  177. package/dist/packem_shared/storage-5XW1E7XU.js +0 -1188
  178. package/dist/packem_shared/tigris-Hac8TKnX.js +0 -21
  179. package/dist/packem_shared/transformOpenApiSpec-BodFhFls.js +0 -975
  180. package/dist/packem_shared/tusOpenApiSpec-DzppyJTW.js +0 -740
  181. package/dist/packem_shared/update-size-CCGm6i1J.js +0 -8
  182. package/dist/packem_shared/validator-DuO17wFF.js +0 -79
  183. package/dist/packem_shared/waitForStorage-Cscw85sx.js +0 -18
  184. package/dist/packem_shared/wasabi-DIyflHSd.js +0 -21
  185. package/dist/packem_shared/xhrOpenApiSpec-CXz7BC5J.js +0 -264
@@ -1,359 +0,0 @@
1
- import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';
2
- import { p as partMatch, d as detectFileTypeFromStream, g as getFileStatus } from './part-match-Dt738Ddb.js';
3
- import { throwErrorCode, ERRORS } from './ERRORS-D0apMqnc.js';
4
- import { B as BaseStorage, t as toMilliseconds } from './storage-5XW1E7XU.js';
5
- import { createRetryWrapper } from './isRetryableError-Dycp7127.js';
6
- import { L as LocalMetaStorage } from './local-meta-storage-D-pPc3FI.js';
7
- import AzureFile from './AzureFile-C0kug4w4.js';
8
- import AzureMetaStorage from './AzureSMetaStorage-BEbXX9Uk.js';
9
- import { n as normalize } from './path-aV9lMdcn-DMU5H1-h.js';
10
- import { h as hasContent } from './has-content-CY66ehMK.js';
11
-
12
- class AzureStorage extends BaseStorage {
13
- static name = "azure";
14
- checksumTypes = ["md5"];
15
- meta;
16
- client;
17
- containerClient;
18
- root;
19
- retry;
20
- // eslint-disable-next-line sonarjs/cognitive-complexity
21
- constructor(config) {
22
- super(config);
23
- if (!config.containerName) {
24
- throw new Error("Missing required parameter: Azure container name.");
25
- }
26
- const connectionString = config.connectionString || process.env.AZURE_STORAGE_CONNECTION_STRING || void 0;
27
- if (connectionString) {
28
- this.client = BlobServiceClient.fromConnectionString(connectionString);
29
- } else {
30
- const accountKey = config.accountKey || process.env.AZURE_STORAGE_ACCOUNT_KEY || void 0;
31
- const accountName = config.accountName || process.env.AZURE_STORAGE_ACCOUNT || void 0;
32
- if (!config.accountKey) {
33
- throw new Error("Missing required parameter: Azure blob storage account key.");
34
- }
35
- if (!config.accountName) {
36
- throw new Error("Missing required parameter: Azure blob storage account name.");
37
- }
38
- const signedCredentials = new StorageSharedKeyCredential(accountName, accountKey);
39
- this.client = new BlobServiceClient(config.endpoint ?? `https://${accountName}.blob.core.windows.net`, signedCredentials);
40
- }
41
- this.containerClient = this.client.getContainerClient(config.containerName);
42
- this.root = config.root ? normalize(config.root).replace(/^\//, "") : "";
43
- const retryConfig = {
44
- backoffMultiplier: 2,
45
- initialDelay: 1e3,
46
- maxDelay: 3e4,
47
- maxRetries: 3,
48
- retryableStatusCodes: [408, 429, 500, 502, 503, 504],
49
- shouldRetry: (error) => {
50
- const errorWithCode = error;
51
- if (errorWithCode.statusCode && [408, 429, 500, 502, 503, 504].includes(errorWithCode.statusCode)) {
52
- return true;
53
- }
54
- if (error instanceof Error) {
55
- const errorCode = errorWithCode.code;
56
- if (errorCode === "ECONNRESET" || errorCode === "ETIMEDOUT" || errorCode === "ENOTFOUND" || errorCode === "ECONNREFUSED") {
57
- return true;
58
- }
59
- }
60
- return false;
61
- },
62
- ...config.retryConfig
63
- };
64
- this.retry = createRetryWrapper(retryConfig);
65
- if (config.metaStorage) {
66
- this.meta = config.metaStorage;
67
- } else {
68
- let metaConfig = { ...config, ...config.metaStorageConfig, logger: this.logger };
69
- const localMeta = "directory" in metaConfig;
70
- if (localMeta) {
71
- this.logger?.debug("Using local meta storage");
72
- this.meta = new LocalMetaStorage(metaConfig);
73
- } else {
74
- if (connectionString === metaConfig.connectionString) {
75
- metaConfig = { ...metaConfig, client: this.client };
76
- }
77
- this.meta = new AzureMetaStorage(metaConfig);
78
- }
79
- }
80
- this.isReady = false;
81
- this.accessCheck().then(() => {
82
- this.isReady = true;
83
- return void 0;
84
- }).catch((error) => {
85
- this.logger?.error("Storage access check failed: %O", error);
86
- });
87
- }
88
- async create(config) {
89
- return this.instrumentOperation("create", async () => {
90
- const processedConfig = { ...config };
91
- if (config.ttl) {
92
- const ttlMs = typeof config.ttl === "string" ? toMilliseconds(config.ttl) : config.ttl;
93
- if (ttlMs !== void 0) {
94
- processedConfig.expiredAt = Date.now() + ttlMs;
95
- }
96
- }
97
- const file = new AzureFile(processedConfig);
98
- file.name = this.namingFunction(file);
99
- await this.validate(file);
100
- try {
101
- const existing = await this.getMeta(file.id);
102
- if (existing.bytesWritten >= 0) {
103
- return existing;
104
- }
105
- } catch {
106
- }
107
- const blobClient = this.containerClient.getBlockBlobClient(this.getFullPath(file.name));
108
- const stringifiedMetaValues = {};
109
- for (const [key, value] of Object.entries(file.metadata || {})) {
110
- stringifiedMetaValues[key] = JSON.stringify(value);
111
- }
112
- const response = await this.retry(
113
- () => blobClient.uploadData(Buffer.from(""), {
114
- blobHTTPHeaders: {
115
- blobContentType: file.contentType
116
- },
117
- metadata: {
118
- name: file.name,
119
- originalName: file.originalName,
120
- ...stringifiedMetaValues
121
- }
122
- })
123
- );
124
- if (response.requestId === void 0) {
125
- return throwErrorCode(ERRORS.FILE_ERROR, "azure create upload error");
126
- }
127
- file.requestId = response.requestId;
128
- file.uri = response._response.headers.get("location");
129
- file.bytesWritten = 0;
130
- await this.saveMeta(file);
131
- file.status = "created";
132
- await this.onCreate(file);
133
- return file;
134
- });
135
- }
136
- /**
137
- * Deletes an upload and its metadata.
138
- * @param query File query containing the file ID to delete.
139
- * @param query.id File ID to delete.
140
- * @returns Promise resolving to the deleted file object with status: "deleted".
141
- * @throws {UploadError} If the file metadata cannot be found.
142
- */
143
- async delete({ id }) {
144
- return this.instrumentOperation("delete", async () => {
145
- const file = await this.getMeta(id);
146
- file.status = "deleted";
147
- await Promise.all([
148
- this.deleteMeta(file.id),
149
- this.retry(() => this.containerClient.getBlockBlobClient(this.getFullPath(file.name)).deleteIfExists())
150
- ]);
151
- const deletedFile = { ...file };
152
- await this.onDelete(deletedFile);
153
- return deletedFile;
154
- });
155
- }
156
- /**
157
- * Moves an upload file to a new location.
158
- * @param name Source file name/ID.
159
- * @param destination Destination file name/ID.
160
- * @returns Promise resolving to the moved file object.
161
- * @throws {UploadError} If the source file cannot be found.
162
- */
163
- async move(name, destination) {
164
- return this.instrumentOperation("move", async () => {
165
- const copiedFile = await this.copy(name, destination);
166
- const source = this.getFullPath(name);
167
- await this.retry(() => this.containerClient.getBlockBlobClient(source).deleteIfExists());
168
- return copiedFile;
169
- });
170
- }
171
- async write(part) {
172
- return this.instrumentOperation("write", async () => {
173
- let file;
174
- if ("contentType" in part && "metadata" in part && !("body" in part) && !("start" in part)) {
175
- file = part;
176
- } else {
177
- file = await this.getMeta(part.id);
178
- await this.checkIfExpired(file);
179
- }
180
- if (file.status === "completed") {
181
- return file;
182
- }
183
- if (!partMatch(part, file)) {
184
- return throwErrorCode(ERRORS.FILE_CONFLICT);
185
- }
186
- await this.lock(part.id);
187
- try {
188
- if (hasContent(part)) {
189
- if ((file.bytesWritten === 0 || Number.isNaN(file.bytesWritten)) && (!file.contentType || file.contentType === "application/octet-stream")) {
190
- try {
191
- const { fileType, stream: detectedStream } = await detectFileTypeFromStream(part.body);
192
- if (fileType?.mime) {
193
- file.contentType = fileType.mime;
194
- }
195
- part.body = detectedStream;
196
- } catch {
197
- }
198
- }
199
- const blobClient = this.containerClient.getBlockBlobClient(this.getFullPath(file.name));
200
- const abortController = new AbortController();
201
- part.body.on("error", () => {
202
- abortController.abort();
203
- });
204
- const response = await this.retry(
205
- () => blobClient.uploadStream(part.body, void 0, void 0, {
206
- abortSignal: abortController.signal,
207
- blobHTTPHeaders: {
208
- blobContentType: file.contentType ?? "application/octet-stream"
209
- },
210
- metadata: file.metadata
211
- })
212
- );
213
- if (response.requestId === void 0) {
214
- return throwErrorCode(ERRORS.FILE_ERROR, "azure write upload error");
215
- }
216
- file.requestId = response.requestId;
217
- file.bytesWritten += part.contentLength || 0;
218
- file.status = getFileStatus(file);
219
- if (file.status === "completed") {
220
- file.uri = response._response.headers.get("location");
221
- await this.deleteMeta(file.id);
222
- }
223
- }
224
- } finally {
225
- await this.unlock(part.id);
226
- }
227
- return file;
228
- });
229
- }
230
- async get({ id }) {
231
- return this.instrumentOperation("get", async () => {
232
- const blobClient = this.containerClient.getBlockBlobClient(id);
233
- const exists = await this.retry(() => blobClient.exists());
234
- if (!exists) {
235
- try {
236
- await this.getMeta(id);
237
- return throwErrorCode(ERRORS.GONE);
238
- } catch {
239
- return throwErrorCode(ERRORS.FILE_NOT_FOUND);
240
- }
241
- }
242
- const response = await this.retry(() => blobClient.getProperties());
243
- const { contentLength, contentType, etag, expiresOn, lastModified, metadata } = response;
244
- return {
245
- content: await this.retry(() => blobClient.downloadToBuffer()),
246
- contentType,
247
- ETag: etag,
248
- expiredAt: expiresOn,
249
- id,
250
- metadata: metadata || {},
251
- modifiedAt: lastModified,
252
- name: metadata?.name || id,
253
- originalName: metadata?.originalName || "",
254
- size: contentLength
255
- };
256
- });
257
- }
258
- /**
259
- * Checks if a file exists by verifying both metadata and the actual Azure blob.
260
- * Returns true only if both the metadata and the blob exist.
261
- * @param query File query containing the file ID to check.
262
- * @returns Promise resolving to true if both metadata and blob exist, false otherwise.
263
- */
264
- async exists({ id }) {
265
- return this.instrumentOperation("exists", async () => {
266
- try {
267
- await this.getMeta(id);
268
- const blobClient = this.containerClient.getBlockBlobClient(id);
269
- const exists = await this.retry(() => blobClient.exists());
270
- return exists;
271
- } catch {
272
- return false;
273
- }
274
- });
275
- }
276
- /**
277
- * Copies an upload file to a new location.
278
- * @param name Source file name/ID.
279
- * @param destination Destination file name/ID.
280
- * @returns Promise resolving to the copied file object.
281
- * @throws {UploadError} If the source file cannot be found.
282
- */
283
- async copy(name, destination) {
284
- return this.instrumentOperation("copy", async () => {
285
- const source = this.containerClient.getBlockBlobClient(this.getFullPath(name));
286
- const exists = await this.retry(() => source.exists());
287
- if (!exists) {
288
- try {
289
- await this.getMeta(name);
290
- return throwErrorCode(ERRORS.GONE);
291
- } catch {
292
- return throwErrorCode(ERRORS.FILE_NOT_FOUND);
293
- }
294
- }
295
- const target = this.containerClient.getBlockBlobClient(this.getFullPath(destination));
296
- const poller = await this.retry(() => target.beginCopyFromURL(source.url));
297
- await this.retry(() => poller.pollUntilDone());
298
- const sourceFile = await this.getMeta(name);
299
- return { ...sourceFile, id: destination, name: destination };
300
- });
301
- }
302
- async list(limit = 1e3) {
303
- return this.instrumentOperation(
304
- "list",
305
- async () => {
306
- const files = [];
307
- let truncated = true;
308
- let token;
309
- while (truncated) {
310
- try {
311
- const iterator = this.containerClient.listBlobsFlat({
312
- includeMetadata: true,
313
- prefix: this.root
314
- }).byPage({ continuationToken: token, maxPageSize: limit });
315
- const next = await this.retry(() => iterator.next());
316
- const response = next.value;
317
- if (response !== void 0 && "segment" in response) {
318
- response.segment.blobItems.forEach((blob) => {
319
- if (!blob.deleted) {
320
- files.push({
321
- createdAt: blob.properties.createdOn,
322
- id: blob.name,
323
- modifiedAt: blob.properties.lastModified
324
- });
325
- }
326
- });
327
- }
328
- truncated = response?.continuationToken !== void 0;
329
- if (truncated) {
330
- token = response.continuationToken;
331
- }
332
- } catch (error) {
333
- const httpError = this.normalizeError(error instanceof Error ? error : new Error(String(error)));
334
- await this.onError(httpError);
335
- throw error;
336
- }
337
- }
338
- return files;
339
- },
340
- { limit }
341
- );
342
- }
343
- /**
344
- * Prefixes the given filePath with the storage root location (assetFolder if configured).
345
- * @param filePath Relative file path to prefix.
346
- * @returns Full path with asset folder prefix if configured, otherwise returns original path.
347
- */
348
- getFullPath(filePath) {
349
- if (this.assetFolder !== void 0) {
350
- return `${this.assetFolder}/${filePath}`;
351
- }
352
- return filePath;
353
- }
354
- async accessCheck() {
355
- await this.retry(() => this.containerClient.getProperties());
356
- }
357
- }
358
-
359
- export { AzureStorage as default };
@@ -1,83 +0,0 @@
1
- import { Readable } from 'node:stream';
2
- import mime from 'mime';
3
- import { N as NoOpCache } from './cache-B88MXQ_2.js';
4
-
5
- class BaseTransformer {
6
- /**
7
- * Creates a new BaseTransformer instance with common functionality.
8
- * @param storage The storage backend for retrieving and storing files.
9
- * @param config Configuration options for the transformer.
10
- * @param logger Optional logger instance for logging operations.
11
- * @protected
12
- */
13
- constructor(storage, config, logger) {
14
- this.storage = storage;
15
- this.config = config;
16
- this.logger = logger;
17
- this.cache = config.cache ?? new NoOpCache();
18
- }
19
- storage;
20
- config;
21
- logger;
22
- cache;
23
- /**
24
- * Streams transform of a file with the given steps (for large files).
25
- * @param fileId Unique identifier of the file to transform.
26
- * @param steps Array of transformation steps to apply.
27
- * @returns Promise resolving to streaming result with headers, size, and stream.
28
- */
29
- async transformStream(fileId, steps) {
30
- const result = await this.transform(fileId, steps);
31
- if (result && "buffer" in result) {
32
- const { buffer } = result;
33
- return {
34
- headers: {
35
- "Content-Length": buffer.length.toString(),
36
- "Content-Type": this.getContentTypeFromResult(result)
37
- },
38
- size: buffer.length,
39
- stream: Readable.from(buffer)
40
- };
41
- }
42
- throw new Error("Streaming transformation not supported for this transformer");
43
- }
44
- /**
45
- * Clears cache for a specific file or all files.
46
- * @param fileId Optional file identifier to clear cache for specific file.
47
- */
48
- clearCache(fileId) {
49
- if (fileId) {
50
- this.cache?.delete(fileId);
51
- } else {
52
- this.cache?.clear?.();
53
- }
54
- }
55
- /**
56
- * Gets cache statistics.
57
- * @returns Cache statistics including max size and current size.
58
- */
59
- getCacheStats() {
60
- return {
61
- maxSize: -1,
62
- // -1 indicates unlimited or unknown max size
63
- size: this.cache?.size ?? 0
64
- };
65
- }
66
- /**
67
- * Gets content type from transformation result based on format.
68
- * @param result Transformation result object containing format information.
69
- * @returns Content type string (MIME type).
70
- */
71
- // eslint-disable-next-line class-methods-use-this
72
- getContentTypeFromResult(result) {
73
- if (result?.format) {
74
- const contentType = mime.getType(result.format);
75
- if (contentType) {
76
- return contentType;
77
- }
78
- }
79
- return "application/octet-stream";
80
- }
81
- }
82
-
83
- export { BaseTransformer as default };
@@ -1,12 +0,0 @@
1
- import 'node:fs';
2
- import 'node:fs/promises';
3
- import 'node:stream';
4
- export { D as default } from './disk-storage-D9RfoKjW.js';
5
- import './part-match-Dt738Ddb.js';
6
- import './ERRORS-D0apMqnc.js';
7
- import './storage-5XW1E7XU.js';
8
- import './local-meta-storage-D-pPc3FI.js';
9
- import './File-CPUhj3DI.js';
10
- import './update-size-CCGm6i1J.js';
11
- import './has-content-CY66ehMK.js';
12
- import './path-aV9lMdcn-DMU5H1-h.js';
@@ -1,249 +0,0 @@
1
- import { createReadStream, createWriteStream } from 'node:fs';
2
- import { truncate } from 'node:fs/promises';
3
- import { Transform, pipeline } from 'node:stream';
4
- import { p as partMatch, d as detectFileTypeFromStream, g as getFileStatus } from './part-match-Dt738Ddb.js';
5
- import { throwErrorCode, ERRORS } from './ERRORS-D0apMqnc.js';
6
- import { D as DiskStorage, e as ensureFile, S as StreamLength, s as streamChecksum } from './disk-storage-D9RfoKjW.js';
7
- import { LRUCache } from 'lru-cache';
8
- import { createHash } from 'node:crypto';
9
- import { r as remove } from './local-meta-storage-D-pPc3FI.js';
10
- import { u as updateSize } from './update-size-CCGm6i1J.js';
11
- import { h as hasContent } from './has-content-CY66ehMK.js';
12
-
13
- class RangeChecksum extends Transform {
14
- /**
15
- * Creates a new RangeChecksum transform stream.
16
- * @param hashes Range hasher instance managing multiple file hashes
17
- * @param path File path identifier for this checksum operation
18
- */
19
- constructor(hashes, path) {
20
- super();
21
- this.path = path;
22
- this.hashes = hashes;
23
- this.hash = this.hashes.get(path) || createHash(this.hashes.algorithm);
24
- this.hashCopy = this.hash.copy();
25
- }
26
- path;
27
- hash;
28
- hashCopy;
29
- hashes;
30
- /**
31
- * Resets the hash state to its initial value.
32
- * Useful for reusing the checksum calculator for multiple operations.
33
- */
34
- reset() {
35
- this.hashes.set(this.path, this.hashCopy);
36
- }
37
- /**
38
- * Returns the current hash digest in the specified encoding.
39
- * @param encoding Output encoding format (default: 'hex')
40
- * @returns Hash digest as a string
41
- */
42
- digest(encoding = "hex") {
43
- return this.hash.copy().digest(encoding);
44
- }
45
- // eslint-disable-next-line no-underscore-dangle
46
- _transform(chunk, _encoding, done) {
47
- this.push(chunk);
48
- this.hash.update(chunk);
49
- done();
50
- }
51
- // eslint-disable-next-line class-methods-use-this,no-underscore-dangle
52
- _flush(callback) {
53
- callback();
54
- }
55
- }
56
-
57
- class RangeHasher extends LRUCache {
58
- /**
59
- * Creates a new RangeHasher instance.
60
- * @param algorithm Hash algorithm to use (default: 'sha1')
61
- * @param options LRU cache configuration options
62
- */
63
- constructor(algorithm = "sha1", options) {
64
- super({
65
- ttl: 1e3,
66
- ttlAutopurge: true,
67
- ...options
68
- });
69
- this.algorithm = algorithm;
70
- }
71
- algorithm;
72
- /**
73
- * Returns the hex-encoded digest for a previously initialized path.
74
- * @param path File path identifier
75
- * @returns Hex-encoded hash digest, or empty string if not found
76
- */
77
- hex(path) {
78
- return this.get(path)?.copy().digest("hex") || "";
79
- }
80
- /**
81
- * Returns the base64-encoded digest for a previously initialized path.
82
- * @param path File path identifier
83
- * @returns Base64-encoded hash digest, or empty string if not found
84
- */
85
- base64(path) {
86
- return this.get(path)?.copy().digest("base64") || "";
87
- }
88
- /**
89
- * Initializes or continues a hasher for a file from the specified offset.
90
- * Returns cached hash if available, otherwise calculates from filesystem.
91
- * @param path File path to hash
92
- * @param start Starting offset in bytes (default: 0)
93
- * @returns Promise resolving to the hash instance
94
- */
95
- async init(path, start = 0) {
96
- return this.get(path)?.copy() || this.updateFromFs(path, start);
97
- }
98
- /**
99
- * Creates a transform stream that updates the rolling hash for a file path.
100
- * Useful for incremental hashing during streaming operations.
101
- * @param path File path identifier for hash tracking
102
- * @returns RangeChecksum transform stream instance
103
- */
104
- digester(path) {
105
- return new RangeChecksum(this, path);
106
- }
107
- async updateFromFs(path, start = 0, initial) {
108
- const hash = await this.fromFs(path, start, initial);
109
- this.set(path, hash);
110
- return hash;
111
- }
112
- fromFs(path, start = 0, initial) {
113
- return new Promise((resolve, reject) => {
114
- const digester = this.digester(path);
115
- if (initial !== void 0) {
116
- digester.hash = initial;
117
- }
118
- createReadStream(path, { start }).on("error", reject).on("end", () => {
119
- resolve(digester.hash);
120
- }).pipe(digester).resume();
121
- });
122
- }
123
- }
124
-
125
- class DiskStorageWithChecksum extends DiskStorage {
126
- hashes;
127
- constructor(config) {
128
- super(config);
129
- this.hashes = new RangeHasher(config?.checksum === "sha1" ? "sha1" : "md5");
130
- }
131
- async delete({ id }) {
132
- try {
133
- const file = await this.getMeta(id);
134
- const path = this.getFilePath(file.name);
135
- this.hashes.delete(path);
136
- await remove(path);
137
- await this.deleteMeta(id);
138
- const deletedFile = { ...file, status: "deleted" };
139
- await this.onDelete(deletedFile);
140
- return deletedFile;
141
- } catch (error) {
142
- this.logger?.error("[error]: Could not delete file: %O", error);
143
- const httpError = this.normalizeError(error instanceof Error ? error : new Error(String(error)));
144
- await this.onError(httpError);
145
- }
146
- return { id };
147
- }
148
- async write(part) {
149
- let file;
150
- if ("contentType" in part && "metadata" in part && !("body" in part) && !("start" in part)) {
151
- file = part;
152
- } else {
153
- file = await this.getMeta(part.id);
154
- await this.checkIfExpired(file);
155
- }
156
- if (file.status === "completed") {
157
- return file;
158
- }
159
- if (part.size !== void 0) {
160
- updateSize(file, part.size);
161
- }
162
- if (!partMatch(part, file)) {
163
- return throwErrorCode(ERRORS.FILE_CONFLICT);
164
- }
165
- const path = this.getFilePath(file.name);
166
- try {
167
- const startPosition = part.start || 0;
168
- await ensureFile(path);
169
- if (file.bytesWritten === 0 || Number.isNaN(file.bytesWritten)) {
170
- file.bytesWritten = startPosition;
171
- }
172
- await this.hashes.init(path);
173
- if (hasContent(part)) {
174
- if (this.isUnsupportedChecksum(part.checksumAlgorithm)) {
175
- return throwErrorCode(ERRORS.UNSUPPORTED_CHECKSUM_ALGORITHM);
176
- }
177
- const isFirstChunk = part.start === 0 || part.start === void 0;
178
- if (isFirstChunk && (file.bytesWritten === 0 || Number.isNaN(file.bytesWritten)) && (!file.contentType || file.contentType === "application/octet-stream")) {
179
- try {
180
- const { fileType, stream: detectedStream } = await detectFileTypeFromStream(part.body);
181
- if (fileType?.mime) {
182
- file.contentType = fileType.mime;
183
- }
184
- part.body = detectedStream;
185
- } catch {
186
- }
187
- }
188
- const [bytesWritten, errorCode] = await this.lazyWrite({ ...part, ...file });
189
- if (errorCode) {
190
- await truncate(path, file.bytesWritten);
191
- return throwErrorCode(errorCode);
192
- }
193
- if (typeof bytesWritten !== "number") {
194
- await this.hashes.updateFromFs(path, file.bytesWritten);
195
- }
196
- file.bytesWritten = bytesWritten;
197
- }
198
- file.status = getFileStatus(file);
199
- file.hash = {
200
- algorithm: this.hashes.algorithm,
201
- value: this.hashes.hex(path)
202
- };
203
- if (file.status === "completed") {
204
- this.hashes.delete(path);
205
- }
206
- await this.saveMeta(file);
207
- return file;
208
- } catch (error) {
209
- await this.hashes.updateFromFs(path, file.bytesWritten);
210
- const httpError = this.normalizeError(error instanceof Error ? error : new Error(String(error)));
211
- await this.onError(httpError);
212
- return throwErrorCode(ERRORS.FILE_ERROR, (typeof httpError.message === "string" ? httpError.message : String(error)) || String(error));
213
- }
214
- }
215
- lazyWrite(part) {
216
- return new Promise((resolve, reject) => {
217
- const path = this.getFilePath(part.name);
218
- const destination = createWriteStream(path, { flags: "r+", start: part.start });
219
- const lengthChecker = new StreamLength(part.contentLength || Number(part.size) - part.start);
220
- const checksumChecker = streamChecksum(part.checksum, part.checksumAlgorithm);
221
- const digester = this.hashes.digester(path);
222
- const keepPartial = !part.checksum;
223
- const failWithCode = (code) => {
224
- digester.reset();
225
- destination.close();
226
- resolve([Number.NaN, code]);
227
- };
228
- lengthChecker.on("error", () => {
229
- failWithCode(ERRORS.FILE_CONFLICT);
230
- });
231
- checksumChecker.on("error", () => {
232
- failWithCode(ERRORS.CHECKSUM_MISMATCH);
233
- });
234
- part.body.on("aborted", () => {
235
- failWithCode(keepPartial ? void 0 : ERRORS.REQUEST_ABORTED);
236
- });
237
- pipeline(part.body, lengthChecker, checksumChecker, digester, destination, (error) => {
238
- if (error) {
239
- digester.reset();
240
- reject(error);
241
- return;
242
- }
243
- resolve([part.start + destination.bytesWritten]);
244
- });
245
- });
246
- }
247
- }
248
-
249
- export { DiskStorageWithChecksum as default };