@visulima/storage 1.0.0-alpha.3 → 1.0.0-alpha.30
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/CHANGELOG.md +361 -0
- package/LICENSE.md +213 -573
- package/README.md +83 -470
- package/dist/adapter/nuxt/module.d.ts +41 -34
- package/dist/adapter/nuxt/module.js +1 -93
- package/dist/adapter/nuxt/node_modules/.bin/nuxi +22 -0
- package/dist/adapter/nuxt/node_modules/.bin/nuxt +22 -0
- package/dist/adapter/nuxt/package.json +0 -6
- package/dist/ai/ai-sdk/index.d.ts +113 -0
- package/dist/ai/ai-sdk/index.js +1 -0
- package/dist/ai/claude/index.d.ts +177 -0
- package/dist/ai/claude/index.js +1 -0
- package/dist/ai/openai/index.d.ts +205 -0
- package/dist/ai/openai/index.js +1 -0
- package/dist/ai/tanstack/index.d.ts +115 -0
- package/dist/ai/tanstack/index.js +1 -0
- package/dist/handler/http/fetch/index.d.ts +303 -4
- package/dist/handler/http/fetch/index.js +1 -4
- package/dist/handler/http/hono/index.d.ts +73 -64
- package/dist/handler/http/hono/index.js +1 -65
- package/dist/handler/http/nextjs/index.d.ts +66 -58
- package/dist/handler/http/nextjs/index.js +1 -37
- package/dist/handler/http/node/index.d.ts +361 -4
- package/dist/handler/http/node/index.js +1 -4
- package/dist/handler/http/solid-start/index.d.ts +66 -57
- package/dist/handler/http/solid-start/index.js +1 -44
- package/dist/index.d.ts +58 -17
- package/dist/index.js +1 -13
- package/dist/openapi/index.d.ts +24 -5
- package/dist/openapi/index.js +1 -5
- package/dist/packem_shared/AwsLightFile-BSqjc_rD.js +1 -0
- package/dist/packem_shared/AwsLightMetaStorage-B-iQbToR.js +1 -0
- package/dist/packem_shared/AwsLightStorage-w21RxjUm.js +1 -0
- package/dist/packem_shared/AzureFile-Dgj2Tef4.js +1 -0
- package/dist/packem_shared/AzureSMetaStorage-CR-lfQNQ.js +1 -0
- package/dist/packem_shared/AzureStorage-2kl7JDXs.js +1 -0
- package/dist/packem_shared/BaseTransformer-Fpcuz4kj.js +1 -0
- package/dist/packem_shared/BoxFile-Be0S4N1L.js +1 -0
- package/dist/packem_shared/BoxMetaStorage-DLdXbZaV.js +1 -0
- package/dist/packem_shared/BoxStorage-BUeEJoGL.js +1 -0
- package/dist/packem_shared/BunS3File-D-SRiyrm.js +1 -0
- package/dist/packem_shared/BunS3MetaStorage-Bv_CTTMz.js +1 -0
- package/dist/packem_shared/BunS3Storage-WM3rF6Fw.js +1 -0
- package/dist/packem_shared/BunnyFile-Dotl-lO9.js +1 -0
- package/dist/packem_shared/BunnyMetaStorage-DNMTSeoN.js +1 -0
- package/dist/packem_shared/BunnyStorage-D3s2fRB3.js +1 -0
- package/dist/packem_shared/CloudinaryFile-B5-m33eS.js +1 -0
- package/dist/packem_shared/CloudinaryMetaStorage-DEBk5eQy.js +1 -0
- package/dist/packem_shared/CloudinaryStorage-BBE2-aVz.js +1 -0
- package/dist/packem_shared/DiskStorage-DL0GiG6k.js +1 -0
- package/dist/packem_shared/DiskStorageWithChecksum-BvUTn7O-.js +1 -0
- package/dist/packem_shared/DropboxFile-BGVG2kXM.js +1 -0
- package/dist/packem_shared/DropboxMetaStorage-C6vj1QDA.js +1 -0
- package/dist/packem_shared/DropboxStorage-BL3OIdE_.js +1 -0
- package/dist/packem_shared/ERRORS-CyOuSMLY.js +1 -0
- package/dist/packem_shared/File-BhfUgJjs.js +1 -0
- package/dist/packem_shared/Files-CJh9_N-9.js +1 -0
- package/dist/packem_shared/FirebaseFile-JEu3plMP.js +1 -0
- package/dist/packem_shared/FirebaseMetaStorage-CzyOim-J.js +1 -0
- package/dist/packem_shared/FirebaseStorage-lXMXy3Pm.js +2 -0
- package/dist/packem_shared/FtpFile-B8jaICTB.js +1 -0
- package/dist/packem_shared/FtpMetaStorage-1Njy0DpU.js +1 -0
- package/dist/packem_shared/FtpStorage-Dw94efNW.js +1 -0
- package/dist/packem_shared/GCSConfig-BQ0OpVhe.js +1 -0
- package/dist/packem_shared/GCSFile-CDQ6IWAz.js +1 -0
- package/dist/packem_shared/GCSMetaStorage-udgXA5ia.js +1 -0
- package/dist/packem_shared/GCStorage-ChY6uJuO.js +1 -0
- package/dist/packem_shared/GoogleDriveFile-D0aGfGbL.js +1 -0
- package/dist/packem_shared/GoogleDriveMetaStorage-WGuUZPyx.js +1 -0
- package/dist/packem_shared/GoogleDriveStorage-C0NhBBWH.js +1 -0
- package/dist/packem_shared/LocalMetaStorage-QMKL7McF.js +1 -0
- package/dist/packem_shared/MediaTransformer-D-1c9Q_k.js +1 -0
- package/dist/packem_shared/MetaStorage-Y4m1dWgd.js +1 -0
- package/dist/packem_shared/Metadata-B6Ir0KO7.js +1 -0
- package/dist/packem_shared/Multipart-CIFfQksD.js +1 -0
- package/dist/packem_shared/Multipart-D9WIud9R.js +1 -0
- package/dist/packem_shared/NetlifyBlobFile-PMZLJ8AC.js +1 -0
- package/dist/packem_shared/NetlifyBlobMetaStorage-ClIFdTkT.js +1 -0
- package/dist/packem_shared/NetlifyBlobStorage-CO89TGvF.js +1 -0
- package/dist/packem_shared/NoOpMetrics-Dky06sf1.js +1 -0
- package/dist/packem_shared/OneDriveFile-XbVVKIJh.js +1 -0
- package/dist/packem_shared/OneDriveMetaStorage-DS4f83X2.js +1 -0
- package/dist/packem_shared/OneDriveStorage-jAN46vRm.js +1 -0
- package/dist/packem_shared/OpenTelemetryMetrics-9uxQMSlg.js +1 -0
- package/dist/packem_shared/PocketBaseFile-CkAiSBb0.js +1 -0
- package/dist/packem_shared/PocketBaseMetaStorage-B6utPncj.js +1 -0
- package/dist/packem_shared/PocketBaseStorage-DpOjOKAt.js +1 -0
- package/dist/packem_shared/Rest-BuD3ySAg.js +1 -0
- package/dist/packem_shared/Rest-URrQ5FYM.js +1 -0
- package/dist/packem_shared/S3File-BfmCOET4.js +1 -0
- package/dist/packem_shared/S3MetaStorage-vcriiosn.js +1 -0
- package/dist/packem_shared/S3Storage-n1ohEZj4.js +1 -0
- package/dist/packem_shared/SftpFile-CQCxZNVq.js +1 -0
- package/dist/packem_shared/SftpMetaStorage-DYqXwCdM.js +1 -0
- package/dist/packem_shared/SftpStorage-Ban-WN8v.js +1 -0
- package/dist/packem_shared/SharePointFile-BA6X9Sxr.js +1 -0
- package/dist/packem_shared/SharePointMetaStorage-DVM5-X6g.js +1 -0
- package/dist/packem_shared/SharePointStorage-BY90zh1c.js +1 -0
- package/dist/packem_shared/SupabaseFile-DZ1iv9gM.js +1 -0
- package/dist/packem_shared/SupabaseMetaStorage-ivXoYVUu.js +1 -0
- package/dist/packem_shared/SupabaseStorage-pNbHAE1Y.js +1 -0
- package/dist/packem_shared/TUS_RESUMABLE-B7KtPVeC.js +1 -0
- package/dist/packem_shared/Tus-Fp_hx5ug.js +1 -0
- package/dist/packem_shared/Tus-TNG9HAY8.js +1 -0
- package/dist/packem_shared/UploadThingFile-BpG9mE8K.js +1 -0
- package/dist/packem_shared/UploadThingMetaStorage-BvKNzgm7.js +1 -0
- package/dist/packem_shared/UploadThingStorage-BcmIE2dI.js +1 -0
- package/dist/packem_shared/ValidationError-D8KKJiKA.js +1 -0
- package/dist/packem_shared/VercelBlobFile-Cni_1qwD.js +1 -0
- package/dist/packem_shared/VercelBlobMetaStorage-CwaqWucZ.js +1 -0
- package/dist/packem_shared/VercelBlobStorage-s260zfFo.js +1 -0
- package/dist/packem_shared/_commonjsHelpers-D6W6KoPK.js +1 -0
- package/dist/packem_shared/agentsListFiles-R-CnGKc4.js +1 -0
- package/dist/packem_shared/akamai-BYS9pP8S.js +1 -0
- package/dist/packem_shared/alibaba-BJQ6ijoK.js +1 -0
- package/dist/packem_shared/approval-BBeX3o4E.js +1 -0
- package/dist/packem_shared/approval.d-CMAYH9GF.d.ts +75 -0
- package/dist/packem_shared/aws-light-meta-storage-CstQBYXG.js +4 -0
- package/dist/packem_shared/azure-meta-storage-C4SrMtT2.js +1 -0
- package/dist/packem_shared/backblaze-CvdtCvJL.js +1 -0
- package/dist/packem_shared/base-handler-core-BYDQditz.js +1 -0
- package/dist/packem_shared/base-handler-fetch-DWzsPkmV.js +1 -0
- package/dist/packem_shared/base-handler-node-Dety2rQB.js +1 -0
- package/dist/packem_shared/cache-qV_5Umeq.js +1 -0
- package/dist/packem_shared/claudeListFiles-DAezbKEi.js +1 -0
- package/dist/packem_shared/cloudflare-Bm_Pg6yx.js +1 -0
- package/dist/packem_shared/createResponsesFileTools-BCep-qdO.js +1 -0
- package/dist/packem_shared/defaultCloudStorageFileNameValidation-shIZX_7L.js +1 -0
- package/dist/packem_shared/detect-file-type-5JhzC9RU.js +1 -0
- package/dist/packem_shared/digitalOcean-Lj1NfDzc.js +1 -0
- package/dist/packem_shared/disk-storage-CKAJvhcj.js +1 -0
- package/dist/packem_shared/disk-storage-with-checksum.d-mHcg2uLw.d.ts +150 -0
- package/dist/packem_shared/executors-DG6hGtvm.js +1 -0
- package/dist/packem_shared/executors.d-X4hz3zfu.d.ts +65 -0
- package/dist/packem_shared/exoscale-O0HzxoDz.js +1 -0
- package/dist/packem_shared/filebase-D-urO4Ob.js +1 -0
- package/dist/packem_shared/gcs-meta-storage-mZiqlX-9.js +1 -0
- package/dist/packem_shared/has-content-Bx2p8Okx.js +1 -0
- package/dist/packem_shared/headers-DC2MEOrK.js +27 -0
- package/dist/packem_shared/hetzner-DDxE7Gy7.js +1 -0
- package/dist/packem_shared/ibmCos-Rx_yku4H.js +1 -0
- package/dist/packem_shared/idriveE2-BFhw0Vwy.js +1 -0
- package/dist/packem_shared/index-B4ETk0Lu.js +5 -0
- package/dist/packem_shared/index.d-C4Fivh4I.d.ts +94 -0
- package/dist/packem_shared/is-expired-1JuZjDtb.js +1 -0
- package/dist/packem_shared/isRetryableError-BhizNeAz.js +1 -0
- package/dist/packem_shared/isValidMediaType-B-2UKjZx.js +1 -0
- package/dist/packem_shared/listFiles-B6VF05d-.js +1 -0
- package/dist/packem_shared/listFiles-BtP6VnUp.js +1 -0
- package/dist/packem_shared/local-meta-storage-Bi0mK6gD.js +1 -0
- package/dist/packem_shared/local-meta-storage.d-B11vHYNm.d.ts +21 -0
- package/dist/packem_shared/media-transformer.d-C3QvECD7.d.ts +331 -0
- package/dist/packem_shared/minio-T_Z3iEy7.js +1 -0
- package/dist/packem_shared/multipart-base-BxckfvQf.js +1 -0
- package/dist/packem_shared/oauth-refresh-Dg2ybc6_.js +1 -0
- package/dist/packem_shared/oracleCloud-D5T9s4JV.js +1 -0
- package/dist/packem_shared/ovhCloud-DCwef2fe.js +1 -0
- package/dist/packem_shared/part-match-B5fLLmFw.js +1 -0
- package/dist/packem_shared/path-D7rMc9nq-B718mbm6.js +1 -0
- package/dist/packem_shared/posix-dirname-CiHXPPnw.js +1 -0
- package/dist/packem_shared/response-builder-Wdo_fvcF.js +1 -0
- package/dist/packem_shared/rest-base-DI7xFXr5.js +1 -0
- package/dist/packem_shared/restOpenApiSpec-PaIVbESh.js +1 -0
- package/dist/packem_shared/s3-base-storage-Dbexfg7p.js +1 -0
- package/dist/packem_shared/s3-base-storage.d-V3N2nKCt.d.ts +260 -0
- package/dist/packem_shared/scaleway-ygRXOss9.js +1 -0
- package/dist/packem_shared/sharedGet-Ce7WGAsc.js +1 -0
- package/dist/packem_shared/storage-Dh0tJh7j.js +1 -0
- package/dist/packem_shared/storage.d-RteRC-cG.d.ts +1106 -0
- package/dist/packem_shared/storj-CVA9mM-7.js +1 -0
- package/dist/packem_shared/tencent-CAcAGaIW.js +1 -0
- package/dist/packem_shared/tigris-wmhjfsH2.js +1 -0
- package/dist/packem_shared/transformOpenApiSpec-C0vEbDTO.js +1 -0
- package/dist/packem_shared/tus-base.d-CygntIPM.d.ts +99 -0
- package/dist/packem_shared/tusOpenApiSpec-DF0-hlWV.js +1 -0
- package/dist/packem_shared/types.d-ChNXbbHG.d.ts +104 -0
- package/dist/packem_shared/types.d-DxonY4XS.d.ts +720 -0
- package/dist/packem_shared/types.d-cI_cMxcZ.d.ts +49 -0
- package/dist/packem_shared/update-size-DANV7aa2.js +1 -0
- package/dist/packem_shared/vultr-lK9L-sFk.js +1 -0
- package/dist/packem_shared/waitForStorage-ChSBLhLc.js +1 -0
- package/dist/packem_shared/wasabi-JQzxdrFy.js +1 -0
- package/dist/packem_shared/xhrOpenApiSpec-nyoboz83.js +1 -0
- package/dist/packem_shared/yandex-ZwvE77v4.js +1 -0
- package/dist/storage/aws/clients/index.d.ts +612 -6
- package/dist/storage/aws/clients/index.js +1 -6
- package/dist/storage/aws/index.d.ts +321 -4
- package/dist/storage/aws/index.js +1 -3
- package/dist/storage/aws-light/index.d.ts +254 -4
- package/dist/storage/aws-light/index.js +1 -3
- package/dist/storage/azure/index.d.ts +217 -4
- package/dist/storage/azure/index.js +1 -3
- package/dist/storage/box/index.d.ts +189 -0
- package/dist/storage/box/index.js +1 -0
- package/dist/storage/bun-s3/index.d.ts +200 -0
- package/dist/storage/bun-s3/index.js +1 -0
- package/dist/storage/bunny/index.d.ts +119 -0
- package/dist/storage/bunny/index.js +1 -0
- package/dist/storage/cloudinary/index.d.ts +121 -0
- package/dist/storage/cloudinary/index.js +1 -0
- package/dist/storage/dropbox/index.d.ts +132 -0
- package/dist/storage/dropbox/index.js +1 -0
- package/dist/storage/firebase/index.d.ts +192 -0
- package/dist/storage/firebase/index.js +1 -0
- package/dist/storage/ftp/index.d.ts +85 -0
- package/dist/storage/ftp/index.js +1 -0
- package/dist/storage/gcs/index.d.ts +181 -5
- package/dist/storage/gcs/index.js +1 -4
- package/dist/storage/google-drive/index.d.ts +148 -0
- package/dist/storage/google-drive/index.js +1 -0
- package/dist/storage/local/index.d.ts +7 -4
- package/dist/storage/local/index.js +1 -3
- package/dist/storage/netlify-blob/index.d.ts +147 -4
- package/dist/storage/netlify-blob/index.js +1 -3
- package/dist/storage/onedrive/index.d.ts +103 -0
- package/dist/storage/onedrive/index.js +1 -0
- package/dist/storage/pocketbase/index.d.ts +172 -0
- package/dist/storage/pocketbase/index.js +1 -0
- package/dist/storage/sftp/index.d.ts +86 -0
- package/dist/storage/sftp/index.js +1 -0
- package/dist/storage/sharepoint/index.d.ts +180 -0
- package/dist/storage/sharepoint/index.js +1 -0
- package/dist/storage/supabase/index.d.ts +115 -0
- package/dist/storage/supabase/index.js +1 -0
- package/dist/storage/uploadthing/index.d.ts +95 -0
- package/dist/storage/uploadthing/index.js +1 -0
- package/dist/storage/vercel-blob/index.d.ts +189 -4
- package/dist/storage/vercel-blob/index.js +1 -3
- package/dist/transformer/audio-transformer.d.ts +127 -125
- package/dist/transformer/audio-transformer.js +1 -278
- package/dist/transformer/image-transformer.d.ts +573 -568
- package/dist/transformer/image-transformer.js +1 -1100
- package/dist/transformer/index.d.ts +62 -5
- package/dist/transformer/index.js +1 -4
- package/dist/transformer/video-transformer.d.ts +144 -142
- package/dist/transformer/video-transformer.js +1 -310
- package/package.json +195 -47
- package/dist/handler/base/base-handler-core.d.ts +0 -91
- package/dist/handler/base/base-handler-fetch.d.ts +0 -76
- package/dist/handler/base/base-handler-node.d.ts +0 -137
- package/dist/handler/multipart/multipart-base.d.ts +0 -84
- package/dist/handler/multipart/multipart-fetch.d.ts +0 -64
- package/dist/handler/multipart/multipart.d.ts +0 -49
- package/dist/handler/rest/rest-base.d.ts +0 -106
- package/dist/handler/rest/rest-fetch.d.ts +0 -88
- package/dist/handler/rest/rest.d.ts +0 -93
- package/dist/handler/tus/tus-base.d.ts +0 -152
- package/dist/handler/tus/tus-fetch.d.ts +0 -72
- package/dist/handler/tus/tus.d.ts +0 -78
- package/dist/handler/types.d.ts +0 -53
- package/dist/handler/utils/request-parser.d.ts +0 -72
- package/dist/handler/utils/response-builder.d.ts +0 -83
- package/dist/handler/utils/storage-utils.d.ts +0 -10
- package/dist/handler/utils/stream-utils.d.ts +0 -29
- package/dist/handler/utils/upload-handlers.d.ts +0 -76
- package/dist/metrics/index.d.ts +0 -2
- package/dist/metrics/no-op-metrics.d.ts +0 -15
- package/dist/metrics/opentelemetry-metrics.d.ts +0 -55
- package/dist/openapi/rest.d.ts +0 -7
- package/dist/openapi/shared.d.ts +0 -13
- package/dist/openapi/transform.d.ts +0 -3
- package/dist/openapi/tus.d.ts +0 -7
- package/dist/openapi/xhr.d.ts +0 -7
- package/dist/packem_shared/AwsLightFile-tTneXZgG.js +0 -11
- package/dist/packem_shared/AwsLightMetaStorage-BWSOtVaN.js +0 -4
- package/dist/packem_shared/AwsLightStorage-Blv-GP4v.js +0 -133
- package/dist/packem_shared/AzureFile-CesgFzps.js +0 -8
- package/dist/packem_shared/AzureSMetaStorage-CFs-OYJT.js +0 -88
- package/dist/packem_shared/AzureStorage-B0v048hG.js +0 -357
- package/dist/packem_shared/BaseTransformer-C2gLib6v.js +0 -82
- package/dist/packem_shared/DiskStorage-BlltBst6.js +0 -12
- package/dist/packem_shared/DiskStorageWithChecksum-BJTmMklc.js +0 -238
- package/dist/packem_shared/ERRORS-D0apMqnc.js +0 -97
- package/dist/packem_shared/File-Bb3P23dr.js +0 -69
- package/dist/packem_shared/GCSConfig-vPP22kN6.js +0 -11
- package/dist/packem_shared/GCSFile-BIEunhAN.js +0 -8
- package/dist/packem_shared/GCSMetaStorage-BMFEdzJ7.js +0 -7
- package/dist/packem_shared/GCStorage-DnhiwaS9.js +0 -406
- package/dist/packem_shared/LocalMetaStorage-CZHhKkMd.js +0 -7
- package/dist/packem_shared/MediaTransformer-D6658DL1.js +0 -1197
- package/dist/packem_shared/MetaStorage-pECeFOad.js +0 -46
- package/dist/packem_shared/Metadata-DRLXeJ0F.js +0 -89
- package/dist/packem_shared/Multipart-CNFK_Okz.js +0 -163
- package/dist/packem_shared/Multipart-CtUL7BQw.js +0 -128
- package/dist/packem_shared/NetlifyBlobFile-CXzyjqrD.js +0 -14
- package/dist/packem_shared/NetlifyBlobMetaStorage-DxZ5aDvD.js +0 -9
- package/dist/packem_shared/NetlifyBlobStorage-CLPtjHqd.js +0 -376
- package/dist/packem_shared/NoOpMetrics-DhAk5rXc.js +0 -10
- package/dist/packem_shared/OpenTelemetryMetrics-BnxhqIaH.js +0 -67
- package/dist/packem_shared/Rest-CAOAEkOj.js +0 -267
- package/dist/packem_shared/Rest-DNuLwBrK.js +0 -228
- package/dist/packem_shared/S3File-DZiyk9Qt.js +0 -11
- package/dist/packem_shared/S3MetaStorage-Dz9aDabA.js +0 -76
- package/dist/packem_shared/S3Storage-DHmTk-hU.js +0 -316
- package/dist/packem_shared/TUS_RESUMABLE-GJzZ9R-f.js +0 -434
- package/dist/packem_shared/Tus-B8PmlMgR.js +0 -200
- package/dist/packem_shared/Tus-C4F1aYOl.js +0 -195
- package/dist/packem_shared/ValidationError-BfF1aE4h.js +0 -26
- package/dist/packem_shared/VercelBlobFile-BCg4aTEq.js +0 -18
- package/dist/packem_shared/VercelBlobMetaStorage-Bd9F-VFm.js +0 -9
- package/dist/packem_shared/VercelBlobStorage-DD9LMOS6.js +0 -261
- package/dist/packem_shared/_commonjsHelpers-B85MJLTf.js +0 -5
- package/dist/packem_shared/aws-light-meta-storage-DKJBgbR6.js +0 -446
- package/dist/packem_shared/backblaze-BlMnIcBC.js +0 -20
- package/dist/packem_shared/base-handler-core-BKuf4YLT.js +0 -303
- package/dist/packem_shared/base-handler-fetch-Cr0hLiqg.js +0 -291
- package/dist/packem_shared/base-handler-node-gk5aN9Cx.js +0 -730
- package/dist/packem_shared/cache-B88MXQ_2.js +0 -18
- package/dist/packem_shared/cloudflare-Bi1q8wXE.js +0 -21
- package/dist/packem_shared/defaultCloudStorageFileNameValidation-DUuacjWv.js +0 -11
- package/dist/packem_shared/digitalOcean-CWQRJM3L.js +0 -21
- package/dist/packem_shared/disk-storage-Bh2wy3YW.js +0 -810
- package/dist/packem_shared/gcs-meta-storage-0tgMNnPO.js +0 -158
- package/dist/packem_shared/has-content-CY66ehMK.js +0 -3
- package/dist/packem_shared/headers-DoS5nwM-.js +0 -3220
- package/dist/packem_shared/is-expired-CTThU1q5.js +0 -8
- package/dist/packem_shared/isRetryableError-Dycp7127.js +0 -82
- package/dist/packem_shared/isValidMediaType-BeDgiObq.js +0 -35
- package/dist/packem_shared/local-meta-storage-By-3SNBI.js +0 -649
- package/dist/packem_shared/minio-C2YBZQOw.js +0 -22
- package/dist/packem_shared/multipart-base-B3i67SSX.js +0 -102
- package/dist/packem_shared/part-match-BMNqHDYD.js +0 -96
- package/dist/packem_shared/path-CR6YkPXX-7R1-9CMk.js +0 -161
- package/dist/packem_shared/response-builder-BtnRiBUI.js +0 -45
- package/dist/packem_shared/rest-base-GRCcnan7.js +0 -457
- package/dist/packem_shared/restOpenApiSpec-CwcHHY2C.js +0 -800
- package/dist/packem_shared/s3-base-storage-C1DIHTYY.js +0 -510
- package/dist/packem_shared/sharedGet-Cpo7QUyu.js +0 -1019
- package/dist/packem_shared/storage-C6NSXb8h.js +0 -1175
- package/dist/packem_shared/tigris-Hac8TKnX.js +0 -21
- package/dist/packem_shared/transformOpenApiSpec-DWM5WtnN.js +0 -975
- package/dist/packem_shared/tusOpenApiSpec-6ohiToBy.js +0 -740
- package/dist/packem_shared/update-size-CCGm6i1J.js +0 -8
- package/dist/packem_shared/validator-BeX_lJet.js +0 -78
- package/dist/packem_shared/waitForStorage-Cscw85sx.js +0 -18
- package/dist/packem_shared/wasabi-DIyflHSd.js +0 -21
- package/dist/packem_shared/xhrOpenApiSpec-DS17brnx.js +0 -264
- package/dist/storage/aws/clients/backblaze.d.ts +0 -12
- package/dist/storage/aws/clients/cloudflare.d.ts +0 -13
- package/dist/storage/aws/clients/digital-ocean.d.ts +0 -12
- package/dist/storage/aws/clients/minio.d.ts +0 -13
- package/dist/storage/aws/clients/tigris.d.ts +0 -12
- package/dist/storage/aws/clients/types.d.ts +0 -95
- package/dist/storage/aws/clients/wasabi.d.ts +0 -12
- package/dist/storage/aws/s3-base-storage.d.ts +0 -248
- package/dist/storage/aws/s3-client-adapter.d.ts +0 -110
- package/dist/storage/aws/s3-file.d.ts +0 -10
- package/dist/storage/aws/s3-meta-storage.d.ts +0 -15
- package/dist/storage/aws/s3-storage.d.ts +0 -70
- package/dist/storage/aws/types.d.ts +0 -119
- package/dist/storage/aws-light/aws-light-api-adapter.d.ts +0 -130
- package/dist/storage/aws-light/aws-light-file.d.ts +0 -10
- package/dist/storage/aws-light/aws-light-meta-storage.d.ts +0 -19
- package/dist/storage/aws-light/aws-light-storage.d.ts +0 -65
- package/dist/storage/aws-light/types.d.ts +0 -37
- package/dist/storage/azure/azure-file.d.ts +0 -6
- package/dist/storage/azure/azure-meta-storage.d.ts +0 -15
- package/dist/storage/azure/azure-storage.d.ts +0 -69
- package/dist/storage/azure/types.d.ts +0 -62
- package/dist/storage/gcs/fetch-error.d.ts +0 -11
- package/dist/storage/gcs/gcs-config.d.ts +0 -2
- package/dist/storage/gcs/gcs-file.d.ts +0 -6
- package/dist/storage/gcs/gcs-meta-storage.d.ts +0 -27
- package/dist/storage/gcs/gcs-storage.d.ts +0 -91
- package/dist/storage/gcs/types.d.ts +0 -55
- package/dist/storage/gcs/utils.d.ts +0 -7
- package/dist/storage/local/disk-storage-with-checksum.d.ts +0 -15
- package/dist/storage/local/disk-storage.d.ts +0 -135
- package/dist/storage/local/local-meta-storage.d.ts +0 -32
- package/dist/storage/meta-storage.d.ts +0 -30
- package/dist/storage/netlify-blob/netlify-blob-file.d.ts +0 -12
- package/dist/storage/netlify-blob/netlify-blob-meta-storage.d.ts +0 -7
- package/dist/storage/netlify-blob/netlify-blob-storage.d.ts +0 -93
- package/dist/storage/netlify-blob/types.d.ts +0 -30
- package/dist/storage/storage.d.ts +0 -353
- package/dist/storage/types.d.ts +0 -221
- package/dist/storage/utils/file/file.d.ts +0 -25
- package/dist/storage/utils/file/get-file-status.d.ts +0 -9
- package/dist/storage/utils/file/has-content.d.ts +0 -9
- package/dist/storage/utils/file/index.d.ts +0 -10
- package/dist/storage/utils/file/is-expired.d.ts +0 -8
- package/dist/storage/utils/file/metadata.d.ts +0 -18
- package/dist/storage/utils/file/part-match.d.ts +0 -11
- package/dist/storage/utils/file/types.d.ts +0 -37
- package/dist/storage/utils/file/update-metadata.d.ts +0 -10
- package/dist/storage/utils/file/update-size.d.ts +0 -10
- package/dist/storage/vercel-blob/types.d.ts +0 -32
- package/dist/storage/vercel-blob/vercel-blob-file.d.ts +0 -16
- package/dist/storage/vercel-blob/vercel-blob-meta-storage.d.ts +0 -7
- package/dist/storage/vercel-blob/vercel-blob-storage.d.ts +0 -76
- package/dist/transformer/base-transformer.d.ts +0 -63
- package/dist/transformer/media-transformer.d.ts +0 -332
- package/dist/transformer/types.d.ts +0 -652
- package/dist/transformer/utils.d.ts +0 -33
- package/dist/transformer/validation-error.d.ts +0 -23
- package/dist/utils/cache.d.ts +0 -32
- package/dist/utils/chunked-upload.d.ts +0 -65
- package/dist/utils/detect-file-type.d.ts +0 -28
- package/dist/utils/errors.d.ts +0 -74
- package/dist/utils/file-path-url-matcher.d.ts +0 -18
- package/dist/utils/headers.d.ts +0 -111
- package/dist/utils/http.d.ts +0 -92
- package/dist/utils/locker.d.ts +0 -26
- package/dist/utils/pipes/stream-checksum.d.ts +0 -47
- package/dist/utils/pipes/stream-length.d.ts +0 -22
- package/dist/utils/primitives/get-last-one.d.ts +0 -3
- package/dist/utils/primitives/is-record.d.ts +0 -2
- package/dist/utils/primitives/map-values.d.ts +0 -9
- package/dist/utils/primitives/pick.d.ts +0 -2
- package/dist/utils/primitives/to-milliseconds.d.ts +0 -12
- package/dist/utils/primitives/to-seconds.d.ts +0 -12
- package/dist/utils/range-checksum.d.ts +0 -33
- package/dist/utils/range-hasher.d.ts +0 -46
- package/dist/utils/retry.d.ts +0 -64
- package/dist/utils/types.d.ts +0 -108
- package/dist/utils/validation-error.d.ts +0 -22
- package/dist/utils/validator.d.ts +0 -36
|
@@ -1,1175 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'node:stream';
|
|
2
|
-
import { setInterval } from 'node:timers';
|
|
3
|
-
import { inspect } from 'node:util';
|
|
4
|
-
import typeis from 'type-is';
|
|
5
|
-
import NoOpMetrics from './NoOpMetrics-DhAk5rXc.js';
|
|
6
|
-
import { N as NoOpCache } from './cache-B88MXQ_2.js';
|
|
7
|
-
import { ErrorMap, throwErrorCode, ERRORS } from './ERRORS-D0apMqnc.js';
|
|
8
|
-
import { LRUCache } from 'lru-cache';
|
|
9
|
-
import { a as Validator } from './validator-BeX_lJet.js';
|
|
10
|
-
import { n as normalize, i as isAbsolute } from './path-CR6YkPXX-7R1-9CMk.js';
|
|
11
|
-
import { i as isExpired } from './is-expired-CTThU1q5.js';
|
|
12
|
-
|
|
13
|
-
const BYTE_SIZES = {
|
|
14
|
-
iec: [
|
|
15
|
-
{
|
|
16
|
-
long: "Bytes",
|
|
17
|
-
short: "B"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
long: "Kibibytes",
|
|
21
|
-
short: "KiB"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
long: "Mebibytes",
|
|
25
|
-
short: "MiB"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
long: "Gibibytes",
|
|
29
|
-
short: "GiB"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
long: "Tebibytes",
|
|
33
|
-
short: "TiB"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
long: "Pebibytes",
|
|
37
|
-
short: "PiB"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
long: "Exbibytes",
|
|
41
|
-
short: "EiB"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
long: "Zebibytes",
|
|
45
|
-
short: "ZiB"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
long: "Yobibytes",
|
|
49
|
-
short: "YiB"
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
iec_octet: [
|
|
53
|
-
{
|
|
54
|
-
long: "Octets",
|
|
55
|
-
short: "o"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
long: "Kibioctets",
|
|
59
|
-
short: "Kio"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
long: "Mebioctets",
|
|
63
|
-
short: "Mio"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
long: "Gibioctets",
|
|
67
|
-
short: "Gio"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
long: "Tebioctets",
|
|
71
|
-
short: "Tio"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
long: "Pebioctets",
|
|
75
|
-
short: "Pio"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
long: "Exbioctets",
|
|
79
|
-
short: "Eio"
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
long: "Zebioctets",
|
|
83
|
-
short: "Zio"
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
long: "Yobioctets",
|
|
87
|
-
short: "Yio"
|
|
88
|
-
}
|
|
89
|
-
],
|
|
90
|
-
metric: [
|
|
91
|
-
{
|
|
92
|
-
long: "Bytes",
|
|
93
|
-
short: "Bytes"
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
long: "Kilobytes",
|
|
97
|
-
short: "KB"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
long: "Megabytes",
|
|
101
|
-
short: "MB"
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
long: "Gigabytes",
|
|
105
|
-
short: "GB"
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
long: "Terabytes",
|
|
109
|
-
short: "TB"
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
long: "Petabytes",
|
|
113
|
-
short: "PB"
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
long: "Exabytes",
|
|
117
|
-
short: "EB"
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
long: "Zettabytes",
|
|
121
|
-
short: "ZB"
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
long: "Yottabytes",
|
|
125
|
-
short: "YB"
|
|
126
|
-
}
|
|
127
|
-
],
|
|
128
|
-
metric_octet: [
|
|
129
|
-
{
|
|
130
|
-
long: "Octets",
|
|
131
|
-
short: "o"
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
long: "Kilo-octets",
|
|
135
|
-
short: "ko"
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
long: "Mega-octets",
|
|
139
|
-
short: "Mo"
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
long: "Giga-octets",
|
|
143
|
-
short: "Go"
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
long: "Tera-octets",
|
|
147
|
-
short: "To"
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
long: "Peta-octets",
|
|
151
|
-
short: "Po"
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
long: "Exa-octets",
|
|
155
|
-
short: "Eo"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
long: "Zetta-octets",
|
|
159
|
-
short: "Zo"
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
long: "Yotta-octets",
|
|
163
|
-
short: "Yo"
|
|
164
|
-
}
|
|
165
|
-
]
|
|
166
|
-
};
|
|
167
|
-
const parseLocalizedNumber = (stringNumber, locale) => {
|
|
168
|
-
const thousandSeparator = new Intl.NumberFormat(locale).format(11111).replaceAll(new RegExp("\\p{Number}", "gu"), "");
|
|
169
|
-
const decimalSeparator = new Intl.NumberFormat(locale).format(1.1).replaceAll(new RegExp("\\p{Number}", "gu"), "");
|
|
170
|
-
return Number.parseFloat(stringNumber.replaceAll(new RegExp(`\\${thousandSeparator}`, "g"), "").replace(new RegExp(`\\${decimalSeparator}`), "."));
|
|
171
|
-
};
|
|
172
|
-
const fromBase = (base) => {
|
|
173
|
-
if (base === 2) {
|
|
174
|
-
return 1024;
|
|
175
|
-
}
|
|
176
|
-
if (base === 10) {
|
|
177
|
-
return 1e3;
|
|
178
|
-
}
|
|
179
|
-
throw new TypeError(`Unsupported base.`);
|
|
180
|
-
};
|
|
181
|
-
const parseBytes = (value, options) => {
|
|
182
|
-
const config = {
|
|
183
|
-
base: 2,
|
|
184
|
-
locale: "en-US",
|
|
185
|
-
units: "metric",
|
|
186
|
-
...options
|
|
187
|
-
};
|
|
188
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
189
|
-
throw new TypeError("Value is not a string or is empty.");
|
|
190
|
-
}
|
|
191
|
-
if (value.length > 100) {
|
|
192
|
-
throw new TypeError("Value exceeds the maximum length of 100 characters.");
|
|
193
|
-
}
|
|
194
|
-
const match = /^(?<value>-?(?:\d+(([.,])\d+)*)?[.,]?\d+) *(?<type>bytes?|b|kb|kib|mb|mib|gb|gib|tb|tib|pb|pib|eb|eib|zb|zib|yb|yib|(kilo|kibi|mega|mebi|giga|gibi|tera|tebi|peta|pebi|exa|exbi|zetta|zebi|yotta|yobi)?bytes)?$/i.exec(
|
|
195
|
-
value
|
|
196
|
-
);
|
|
197
|
-
const groups = match?.groups;
|
|
198
|
-
if (!groups) {
|
|
199
|
-
return Number.NaN;
|
|
200
|
-
}
|
|
201
|
-
const localizedNumber = parseLocalizedNumber(groups.value, config.locale);
|
|
202
|
-
const type = (groups.type ?? "Bytes").toUpperCase().replace(/^KIBI/, "KILO").replace(/^MIBI/, "MEGA").replace(/^GIBI/, "GIGA").replace(/^TEBI/, "TERA").replace(/^PEBI/, "PETA").replace(/^EXBI/, "EXA").replace(/^ZEBI/, "ZETTA").replace(/^YIBI/, "YOTTA").replace(/^(.)IB$/, "$1B");
|
|
203
|
-
const level = BYTE_SIZES[config.units].findIndex((unit) => unit.short[0].toUpperCase() === type[0]);
|
|
204
|
-
const base = fromBase(config.base);
|
|
205
|
-
return localizedNumber * base ** level;
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const createDurationLanguage = (y, mo, w, d, h, m, s, ms, future, past, decimal, unitMap, groupSeparator, placeholderSeparator) => {
|
|
209
|
-
const result = {
|
|
210
|
-
d,
|
|
211
|
-
h,
|
|
212
|
-
m,
|
|
213
|
-
mo,
|
|
214
|
-
ms,
|
|
215
|
-
s,
|
|
216
|
-
w,
|
|
217
|
-
y
|
|
218
|
-
};
|
|
219
|
-
{
|
|
220
|
-
result.future = future;
|
|
221
|
-
}
|
|
222
|
-
{
|
|
223
|
-
result.past = past;
|
|
224
|
-
}
|
|
225
|
-
{
|
|
226
|
-
result.decimal = decimal;
|
|
227
|
-
}
|
|
228
|
-
if (unitMap !== void 0) {
|
|
229
|
-
result.unitMap = unitMap;
|
|
230
|
-
}
|
|
231
|
-
{
|
|
232
|
-
result.groupSeparator = groupSeparator;
|
|
233
|
-
}
|
|
234
|
-
{
|
|
235
|
-
result.placeholderSeparator = placeholderSeparator;
|
|
236
|
-
}
|
|
237
|
-
return result;
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
const englishUnitMap = {
|
|
241
|
-
d: "d",
|
|
242
|
-
day: "d",
|
|
243
|
-
days: "d",
|
|
244
|
-
h: "h",
|
|
245
|
-
hour: "h",
|
|
246
|
-
hours: "h",
|
|
247
|
-
hr: "h",
|
|
248
|
-
hrs: "h",
|
|
249
|
-
m: "m",
|
|
250
|
-
millisecond: "ms",
|
|
251
|
-
milliseconds: "ms",
|
|
252
|
-
min: "m",
|
|
253
|
-
mins: "m",
|
|
254
|
-
minute: "m",
|
|
255
|
-
minutes: "m",
|
|
256
|
-
mo: "mo",
|
|
257
|
-
month: "mo",
|
|
258
|
-
months: "mo",
|
|
259
|
-
ms: "ms",
|
|
260
|
-
s: "s",
|
|
261
|
-
sec: "s",
|
|
262
|
-
second: "s",
|
|
263
|
-
seconds: "s",
|
|
264
|
-
secs: "s",
|
|
265
|
-
w: "w",
|
|
266
|
-
week: "w",
|
|
267
|
-
weeks: "w",
|
|
268
|
-
y: "y",
|
|
269
|
-
year: "y",
|
|
270
|
-
years: "y",
|
|
271
|
-
yr: "y",
|
|
272
|
-
yrs: "y"
|
|
273
|
-
};
|
|
274
|
-
const durationLanguage = createDurationLanguage(
|
|
275
|
-
(counter) => `year${counter === 1 ? "" : "s"}`,
|
|
276
|
-
(counter) => `month${counter === 1 ? "" : "s"}`,
|
|
277
|
-
(counter) => `week${counter === 1 ? "" : "s"}`,
|
|
278
|
-
(counter) => `day${counter === 1 ? "" : "s"}`,
|
|
279
|
-
(counter) => `hour${counter === 1 ? "" : "s"}`,
|
|
280
|
-
(counter) => `minute${counter === 1 ? "" : "s"}`,
|
|
281
|
-
(counter) => `second${counter === 1 ? "" : "s"}`,
|
|
282
|
-
(counter) => `millisecond${counter === 1 ? "" : "s"}`,
|
|
283
|
-
"in %s",
|
|
284
|
-
"%s ago",
|
|
285
|
-
".",
|
|
286
|
-
// decimal
|
|
287
|
-
englishUnitMap,
|
|
288
|
-
",",
|
|
289
|
-
// groupSeparator
|
|
290
|
-
"_"
|
|
291
|
-
// placeholderSeparator
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
const validateDurationLanguage = (language) => {
|
|
295
|
-
const requiredProperties = ["y", "mo", "w", "d", "h", "m", "s", "ms", "future", "past"];
|
|
296
|
-
for (const property of requiredProperties) {
|
|
297
|
-
if (!Object.prototype.hasOwnProperty.call(language, property)) {
|
|
298
|
-
throw new TypeError(`Missing required property: ${property}`);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (typeof language.future !== "string" || typeof language.past !== "string") {
|
|
302
|
-
throw new TypeError("Properties future and past must be of type string");
|
|
303
|
-
}
|
|
304
|
-
for (const property of ["y", "mo", "w", "d", "h", "m", "s", "ms"]) {
|
|
305
|
-
if (typeof language[property] !== "string" && typeof language[property] !== "function") {
|
|
306
|
-
throw new TypeError(`Property ${property} must be of type string or function`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
if (language.decimal && typeof language.decimal !== "string") {
|
|
310
|
-
throw new TypeError("Property decimal must be of type string");
|
|
311
|
-
}
|
|
312
|
-
if (language.delimiter && typeof language.delimiter !== "string") {
|
|
313
|
-
throw new TypeError("Property delimiter must be of type string");
|
|
314
|
-
}
|
|
315
|
-
if (language._digitReplacements && !Array.isArray(language._digitReplacements)) {
|
|
316
|
-
throw new TypeError("Property _digitReplacements must be an array");
|
|
317
|
-
}
|
|
318
|
-
if (language._numberFirst && typeof language._numberFirst !== "boolean") {
|
|
319
|
-
throw new TypeError("Property _numberFirst must be of type boolean");
|
|
320
|
-
}
|
|
321
|
-
if (language.unitMap && typeof language.unitMap !== "object") {
|
|
322
|
-
throw new TypeError("Property unitMap must be an object");
|
|
323
|
-
}
|
|
324
|
-
if (language.unitMap && Object.values(language.unitMap).some((value) => typeof value !== "string")) {
|
|
325
|
-
throw new TypeError("All values in unitMap must be of type string");
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const STANDARD_UNIT_MEASURES = {
|
|
330
|
-
d: 864e5,
|
|
331
|
-
h: 36e5,
|
|
332
|
-
m: 6e4,
|
|
333
|
-
mo: 2629746e3,
|
|
334
|
-
ms: 1,
|
|
335
|
-
s: 1e3,
|
|
336
|
-
w: 6048e5,
|
|
337
|
-
y: 31556952e3
|
|
338
|
-
};
|
|
339
|
-
const ESCAPE_REGEX = /[-/\\^$*+?.()|[\]{}]/g;
|
|
340
|
-
const ISO_FORMAT = /^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/i;
|
|
341
|
-
const COLON_FORMAT = /^(?:(\d+):)?(?:(\d+):)?(\d+)$/;
|
|
342
|
-
const NUMERIC_STRING_REGEX = /^[+-]?\d+(?:\.\d+)?$/;
|
|
343
|
-
const parseDuration = (value, options) => {
|
|
344
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
345
|
-
return void 0;
|
|
346
|
-
}
|
|
347
|
-
const { defaultUnit = "ms", language = durationLanguage } = {};
|
|
348
|
-
validateDurationLanguage(language);
|
|
349
|
-
const decimalSeparator = language.decimal ?? ".";
|
|
350
|
-
const groupSeparator = language.groupSeparator ?? ",";
|
|
351
|
-
const placeholderSeparator = language.placeholderSeparator ?? "_";
|
|
352
|
-
const escapedDecimal = decimalSeparator.replaceAll(ESCAPE_REGEX, String.raw`\$&`);
|
|
353
|
-
const escapedGroup = groupSeparator.replaceAll(ESCAPE_REGEX, String.raw`\$&`);
|
|
354
|
-
const escapedPlaceholder = placeholderSeparator.replaceAll(ESCAPE_REGEX, String.raw`\$&`);
|
|
355
|
-
const currentUnitMap = language.unitMap ?? englishUnitMap;
|
|
356
|
-
let processedValue = value.replaceAll(new RegExp(String.raw`(\d)[${escapedPlaceholder}${escapedGroup}](\d)`, "g"), "$1$2");
|
|
357
|
-
if (decimalSeparator !== ".") {
|
|
358
|
-
processedValue = processedValue.replace(escapedDecimal, ".");
|
|
359
|
-
}
|
|
360
|
-
if (NUMERIC_STRING_REGEX.test(value)) {
|
|
361
|
-
const numberOnly = Number.parseFloat(processedValue.trim());
|
|
362
|
-
if (!Number.isNaN(numberOnly)) {
|
|
363
|
-
const unitKey = currentUnitMap[defaultUnit];
|
|
364
|
-
if (unitKey !== void 0) {
|
|
365
|
-
return numberOnly * STANDARD_UNIT_MEASURES[unitKey];
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return void 0;
|
|
369
|
-
}
|
|
370
|
-
const isoMatch = ISO_FORMAT.exec(value);
|
|
371
|
-
if (isoMatch) {
|
|
372
|
-
const hours = Number.parseInt(isoMatch[1] ?? "0", 10);
|
|
373
|
-
const minutes = Number.parseInt(isoMatch[2] ?? "0", 10);
|
|
374
|
-
const seconds = Number.parseInt(isoMatch[3] ?? "0", 10);
|
|
375
|
-
return hours * 36e5 + minutes * 6e4 + seconds * 1e3;
|
|
376
|
-
}
|
|
377
|
-
const colonMatch = COLON_FORMAT.exec(value);
|
|
378
|
-
if (colonMatch) {
|
|
379
|
-
let hours = 0;
|
|
380
|
-
let minutes = 0;
|
|
381
|
-
let seconds = 0;
|
|
382
|
-
if (colonMatch[2] !== void 0) {
|
|
383
|
-
hours = Number.parseInt(colonMatch[1] ?? "0", 10);
|
|
384
|
-
minutes = Number.parseInt(colonMatch[2], 10);
|
|
385
|
-
} else if (colonMatch[1] !== void 0) {
|
|
386
|
-
minutes = Number.parseInt(colonMatch[1], 10);
|
|
387
|
-
}
|
|
388
|
-
seconds = Number.parseInt(colonMatch[3] ?? "0", 10);
|
|
389
|
-
return hours * 36e5 + minutes * 6e4 + seconds * 1e3;
|
|
390
|
-
}
|
|
391
|
-
const currentUnitMapKeys = Object.keys(currentUnitMap);
|
|
392
|
-
const regexKeys = currentUnitMapKeys.toSorted((a, b) => b.length - a.length).map((k) => k.replaceAll(ESCAPE_REGEX, String.raw`\$&`)).join("|");
|
|
393
|
-
const durationRegex = new RegExp(String.raw`(-?\d*\.?\d+)\s*(${regexKeys})`, "gi");
|
|
394
|
-
let totalMs = 0;
|
|
395
|
-
let match;
|
|
396
|
-
let unitsFound = false;
|
|
397
|
-
let firstMatchIndex = -1;
|
|
398
|
-
let lastMatchEndIndex = 0;
|
|
399
|
-
durationRegex.lastIndex = 0;
|
|
400
|
-
while ((match = durationRegex.exec(processedValue)) !== null) {
|
|
401
|
-
if (!unitsFound) {
|
|
402
|
-
firstMatchIndex = match.index;
|
|
403
|
-
}
|
|
404
|
-
unitsFound = true;
|
|
405
|
-
const numberString = match[1];
|
|
406
|
-
const unitString = match[2];
|
|
407
|
-
if (!numberString || !unitString) {
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
const trimmedNumberString = numberString.trim();
|
|
411
|
-
const sign = trimmedNumberString.startsWith("-") ? -1 : 1;
|
|
412
|
-
const absNumberString = trimmedNumberString.replace(/^[-+]/, "");
|
|
413
|
-
const parsedNumber = Number.parseFloat(absNumberString);
|
|
414
|
-
const unitKey = currentUnitMap[unitString.toLowerCase()];
|
|
415
|
-
if (unitKey === void 0) {
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
const unitValue = STANDARD_UNIT_MEASURES[unitKey];
|
|
419
|
-
if (Number.isNaN(parsedNumber)) {
|
|
420
|
-
return void 0;
|
|
421
|
-
}
|
|
422
|
-
totalMs += sign * parsedNumber * unitValue;
|
|
423
|
-
lastMatchEndIndex = durationRegex.lastIndex;
|
|
424
|
-
}
|
|
425
|
-
const leadingText = processedValue.slice(0, firstMatchIndex).trim();
|
|
426
|
-
const trailingText = processedValue.slice(lastMatchEndIndex).trim();
|
|
427
|
-
if (unitsFound && (leadingText.length > 0 || trailingText.length > 0)) {
|
|
428
|
-
return void 0;
|
|
429
|
-
}
|
|
430
|
-
if (!unitsFound) {
|
|
431
|
-
return void 0;
|
|
432
|
-
}
|
|
433
|
-
return totalMs;
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
const toMilliseconds = (value) => {
|
|
437
|
-
if (value === Number(value)) {
|
|
438
|
-
return value;
|
|
439
|
-
}
|
|
440
|
-
if (!value) {
|
|
441
|
-
return void 0;
|
|
442
|
-
}
|
|
443
|
-
const parsed = parseDuration(value);
|
|
444
|
-
if (parsed === void 0) {
|
|
445
|
-
return void 0;
|
|
446
|
-
}
|
|
447
|
-
return parsed;
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
class Locker extends LRUCache {
|
|
451
|
-
/**
|
|
452
|
-
* Creates a new Locker instance with configurable TTL and cache options.
|
|
453
|
-
* @param options LRU cache configuration options
|
|
454
|
-
*/
|
|
455
|
-
constructor(options) {
|
|
456
|
-
super({
|
|
457
|
-
ttl: 1e3,
|
|
458
|
-
ttlAutopurge: true,
|
|
459
|
-
...options
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Acquires a lock for the specified key.
|
|
464
|
-
* Throws an error if the key is already locked.
|
|
465
|
-
* @param key The key to lock
|
|
466
|
-
* @returns The lock token (same as the key)
|
|
467
|
-
* @throws Error if the key is already locked
|
|
468
|
-
*/
|
|
469
|
-
lock(key) {
|
|
470
|
-
const locked = this.get(key);
|
|
471
|
-
if (locked) {
|
|
472
|
-
throw new Error(`${key} is locked`);
|
|
473
|
-
}
|
|
474
|
-
this.set(key, key);
|
|
475
|
-
return key;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Releases the lock for the specified key.
|
|
479
|
-
* @param key The key to unlock
|
|
480
|
-
*/
|
|
481
|
-
unlock(key) {
|
|
482
|
-
this.delete(key);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const extractOriginalName = (meta) => {
|
|
487
|
-
if (typeof meta.name === "string") {
|
|
488
|
-
return meta.name;
|
|
489
|
-
}
|
|
490
|
-
if (typeof meta.title === "string") {
|
|
491
|
-
return meta.title;
|
|
492
|
-
}
|
|
493
|
-
if (typeof meta.originalName === "string") {
|
|
494
|
-
return meta.originalName;
|
|
495
|
-
}
|
|
496
|
-
if (typeof meta.filename === "string") {
|
|
497
|
-
return meta.filename;
|
|
498
|
-
}
|
|
499
|
-
return void 0;
|
|
500
|
-
};
|
|
501
|
-
const deepMerge = (target, source) => {
|
|
502
|
-
const result = { ...target };
|
|
503
|
-
Object.keys(source).forEach((key) => {
|
|
504
|
-
const sourceValue = source[key];
|
|
505
|
-
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
506
|
-
const targetValue = result[key];
|
|
507
|
-
const targetObject = targetValue && typeof targetValue === "object" && !Array.isArray(targetValue) ? targetValue : {};
|
|
508
|
-
result[key] = deepMerge(targetObject, sourceValue);
|
|
509
|
-
} else {
|
|
510
|
-
result[key] = sourceValue;
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
return result;
|
|
514
|
-
};
|
|
515
|
-
const updateMetadata = (file, metadata) => {
|
|
516
|
-
const merged = deepMerge(file, metadata);
|
|
517
|
-
Object.assign(file, merged);
|
|
518
|
-
file.originalName = extractOriginalName(file.metadata) || file.originalName;
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
const defaults = {
|
|
522
|
-
allowMIME: ["*/*"],
|
|
523
|
-
filename: ({ id }) => id,
|
|
524
|
-
maxMetadataSize: "8MB",
|
|
525
|
-
maxUploadSize: "5TB",
|
|
526
|
-
onComplete: () => {
|
|
527
|
-
},
|
|
528
|
-
onCreate: () => {
|
|
529
|
-
},
|
|
530
|
-
onDelete: () => {
|
|
531
|
-
},
|
|
532
|
-
onError: () => {
|
|
533
|
-
},
|
|
534
|
-
onUpdate: () => {
|
|
535
|
-
},
|
|
536
|
-
useRelativeLocation: false,
|
|
537
|
-
validation: {}
|
|
538
|
-
};
|
|
539
|
-
const defaultCloudStorageFileNameValidation = (name) => {
|
|
540
|
-
if (!name || name.length < 3 || name.length > 255 || isAbsolute(name)) {
|
|
541
|
-
return false;
|
|
542
|
-
}
|
|
543
|
-
const upperCase = name.toUpperCase();
|
|
544
|
-
return !(upperCase.includes("../") || name.includes("\0"));
|
|
545
|
-
};
|
|
546
|
-
const defaultFilesystemFileNameValidation = (name) => {
|
|
547
|
-
if (!name || name.length < 3 || name.length > 255 || isAbsolute(name)) {
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
const upperCase = name.toUpperCase();
|
|
551
|
-
const filesystemInvalidChars = ['"', "*", ":", "<", ">", "?", "\\", "|", "../", "\0"];
|
|
552
|
-
return !filesystemInvalidChars.some((char) => upperCase.includes(char));
|
|
553
|
-
};
|
|
554
|
-
class BaseStorage {
|
|
555
|
-
/**
|
|
556
|
-
* Hook called when a new file is created.
|
|
557
|
-
* @param file The newly created file object.
|
|
558
|
-
* @remarks This hook is called after file metadata is saved but before returning the file.
|
|
559
|
-
* Can be used for side effects like logging, notifications, or custom processing.
|
|
560
|
-
*/
|
|
561
|
-
onCreate;
|
|
562
|
-
/**
|
|
563
|
-
* Hook called when file metadata is updated.
|
|
564
|
-
* @param file The updated file object.
|
|
565
|
-
* @remarks This hook is called after metadata is updated and saved.
|
|
566
|
-
* Can be used for side effects like logging or custom processing.
|
|
567
|
-
*/
|
|
568
|
-
onUpdate;
|
|
569
|
-
/**
|
|
570
|
-
* Hook called when a file upload is completed.
|
|
571
|
-
* @param file The completed file object.
|
|
572
|
-
* @param response The response object that can be modified in place (headers, statusCode, body).
|
|
573
|
-
* @param request Optional request object for additional context.
|
|
574
|
-
* @remarks This hook is called when file status becomes "completed".
|
|
575
|
-
* The response object can be modified directly to add headers or change the status code.
|
|
576
|
-
*/
|
|
577
|
-
onComplete;
|
|
578
|
-
/**
|
|
579
|
-
* Hook called when a file is deleted.
|
|
580
|
-
* @param file The deleted file object.
|
|
581
|
-
* @remarks This hook is called after the file is deleted but before returning.
|
|
582
|
-
* Can be used for side effects like cleanup or logging.
|
|
583
|
-
*/
|
|
584
|
-
onDelete;
|
|
585
|
-
/**
|
|
586
|
-
* Hook called when an error occurs during storage operations.
|
|
587
|
-
* @param error The HTTP error object that can be modified in place.
|
|
588
|
-
* @remarks This hook allows customizing error responses by modifying the error object.
|
|
589
|
-
* The error object can be modified to change headers, statusCode, or body properties.
|
|
590
|
-
* Error formatting happens in handlers after this hook is called.
|
|
591
|
-
*/
|
|
592
|
-
onError;
|
|
593
|
-
isReady = true;
|
|
594
|
-
errorResponses = {};
|
|
595
|
-
cache;
|
|
596
|
-
logger;
|
|
597
|
-
metrics;
|
|
598
|
-
genericConfig;
|
|
599
|
-
maxMetadataSize;
|
|
600
|
-
checksumTypes = [];
|
|
601
|
-
maxUploadSize;
|
|
602
|
-
expiration;
|
|
603
|
-
locker;
|
|
604
|
-
namingFunction;
|
|
605
|
-
validation = new Validator();
|
|
606
|
-
assetFolder = void 0;
|
|
607
|
-
/**
|
|
608
|
-
* Limits the number of concurrent upload requests
|
|
609
|
-
*/
|
|
610
|
-
concurrency;
|
|
611
|
-
constructor(config) {
|
|
612
|
-
const options = { ...defaults, ...config };
|
|
613
|
-
this.onCreate = options.onCreate;
|
|
614
|
-
this.onUpdate = options.onUpdate;
|
|
615
|
-
this.onComplete = options.onComplete;
|
|
616
|
-
this.onDelete = options.onDelete;
|
|
617
|
-
this.onError = options.onError;
|
|
618
|
-
this.namingFunction = options.filename;
|
|
619
|
-
this.maxUploadSize = typeof options.maxUploadSize === "string" ? parseBytes(options.maxUploadSize) : options.maxUploadSize;
|
|
620
|
-
this.maxMetadataSize = typeof options.maxMetadataSize === "string" ? parseBytes(options.maxMetadataSize) : options.maxMetadataSize;
|
|
621
|
-
this.expiration = options.expiration;
|
|
622
|
-
this.genericConfig = options;
|
|
623
|
-
if (options.assetFolder !== void 0) {
|
|
624
|
-
this.assetFolder = normalize(options.assetFolder);
|
|
625
|
-
}
|
|
626
|
-
this.locker = new Locker({
|
|
627
|
-
max: 1e3,
|
|
628
|
-
ttl: 3e4,
|
|
629
|
-
ttlAutopurge: true
|
|
630
|
-
});
|
|
631
|
-
this.cache = options.cache ?? new NoOpCache();
|
|
632
|
-
this.logger = options.logger;
|
|
633
|
-
this.metrics = options.metrics ?? new NoOpMetrics();
|
|
634
|
-
this.logger?.debug(`${this.constructor.name} config: ${inspect({ ...config, logger: this.logger.constructor })}`);
|
|
635
|
-
const purgeInterval = toMilliseconds(options.expiration?.purgeInterval);
|
|
636
|
-
if (purgeInterval) {
|
|
637
|
-
this.startAutoPurge(purgeInterval);
|
|
638
|
-
}
|
|
639
|
-
const size = {
|
|
640
|
-
isValid(file) {
|
|
641
|
-
if (file.size === void 0) {
|
|
642
|
-
return true;
|
|
643
|
-
}
|
|
644
|
-
const fileSizeValue = file.size;
|
|
645
|
-
if (fileSizeValue === void 0 || fileSizeValue === null) {
|
|
646
|
-
return false;
|
|
647
|
-
}
|
|
648
|
-
const fileSize = typeof fileSizeValue === "number" ? fileSizeValue : Number(fileSizeValue);
|
|
649
|
-
if (Number.isNaN(fileSize) || fileSize < 0) {
|
|
650
|
-
return false;
|
|
651
|
-
}
|
|
652
|
-
const maxSize = typeof this.value === "number" ? this.value : Number(this.value);
|
|
653
|
-
return !Number.isNaN(maxSize) && fileSize <= maxSize;
|
|
654
|
-
},
|
|
655
|
-
response: ErrorMap.RequestEntityTooLarge,
|
|
656
|
-
value: this.maxUploadSize
|
|
657
|
-
};
|
|
658
|
-
const mime = {
|
|
659
|
-
isValid(file) {
|
|
660
|
-
return !!typeis.is(file.contentType, this.value);
|
|
661
|
-
},
|
|
662
|
-
// @TODO: add better error handling for mime types
|
|
663
|
-
response: ErrorMap.UnsupportedMediaType,
|
|
664
|
-
value: options.allowMIME
|
|
665
|
-
};
|
|
666
|
-
const fileNameValidation = options.fileNameValidation ?? defaultCloudStorageFileNameValidation;
|
|
667
|
-
const filename = {
|
|
668
|
-
isValid(file) {
|
|
669
|
-
return fileNameValidation(file.name);
|
|
670
|
-
},
|
|
671
|
-
response: ErrorMap.InvalidFileName
|
|
672
|
-
};
|
|
673
|
-
this.validation.add({ filename, mime, size });
|
|
674
|
-
this.validation.add({ ...options.validation });
|
|
675
|
-
}
|
|
676
|
-
get tusExtension() {
|
|
677
|
-
const extensions = ["creation", "creation-with-upload", "termination", "checksum", "creation-defer-length", "concatenation"];
|
|
678
|
-
if (this.expiration) {
|
|
679
|
-
extensions.push("expiration");
|
|
680
|
-
}
|
|
681
|
-
return extensions;
|
|
682
|
-
}
|
|
683
|
-
/**
|
|
684
|
-
* Validates a file against configured validation rules.
|
|
685
|
-
* @param file File object to validate.
|
|
686
|
-
* @returns Promise resolving to undefined if file is valid, throws ValidationError otherwise.
|
|
687
|
-
* @throws {ValidationError} If validation fails
|
|
688
|
-
*/
|
|
689
|
-
async validate(file) {
|
|
690
|
-
await this.validation.verify(file);
|
|
691
|
-
}
|
|
692
|
-
/**
|
|
693
|
-
* Checks if a file exists by querying its metadata.
|
|
694
|
-
* @param query File query containing the file ID to check.
|
|
695
|
-
* @param query.id File ID to check.
|
|
696
|
-
* @returns Promise resolving to true if file exists, false otherwise.
|
|
697
|
-
* @remarks This method does not throw errors - it returns false if the file is not found.
|
|
698
|
-
*/
|
|
699
|
-
async exists(query) {
|
|
700
|
-
return this.instrumentOperation("exists", async () => {
|
|
701
|
-
try {
|
|
702
|
-
await this.getMeta(query.id);
|
|
703
|
-
return true;
|
|
704
|
-
} catch {
|
|
705
|
-
return false;
|
|
706
|
-
}
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Normalizes errors with storage-specific context.
|
|
711
|
-
* @param error The error to normalize.
|
|
712
|
-
* @returns Normalized HTTP error with storage class context added to the message.
|
|
713
|
-
* @remarks Errors are enhanced with the storage class name for better debugging.
|
|
714
|
-
*/
|
|
715
|
-
normalizeError(error) {
|
|
716
|
-
const baseError = {
|
|
717
|
-
code: error.name,
|
|
718
|
-
message: error.message,
|
|
719
|
-
name: error.name,
|
|
720
|
-
statusCode: 500
|
|
721
|
-
};
|
|
722
|
-
return {
|
|
723
|
-
...baseError,
|
|
724
|
-
message: `[${this.constructor.name}] ${baseError.message}`
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Gets the storage configuration.
|
|
729
|
-
* @returns The current storage configuration options.
|
|
730
|
-
*/
|
|
731
|
-
get config() {
|
|
732
|
-
return this.genericConfig;
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* Saves upload metadata to the metadata storage.
|
|
736
|
-
* @param file File object containing metadata to save.
|
|
737
|
-
* @returns Promise resolving to the saved file object.
|
|
738
|
-
* @remarks Updates timestamps and caches the file metadata.
|
|
739
|
-
*/
|
|
740
|
-
async saveMeta(file) {
|
|
741
|
-
this.updateTimestamps(file);
|
|
742
|
-
this.cache.set(file.id, file);
|
|
743
|
-
return this.meta.save(file.id, file);
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Deletes upload metadata from the metadata storage.
|
|
747
|
-
* @param id File ID whose metadata should be deleted.
|
|
748
|
-
* @returns Promise resolving when metadata is deleted.
|
|
749
|
-
* @remarks Also removes the file from the cache.
|
|
750
|
-
*/
|
|
751
|
-
async deleteMeta(id) {
|
|
752
|
-
this.cache.delete(id);
|
|
753
|
-
return this.meta.delete(id);
|
|
754
|
-
}
|
|
755
|
-
/**
|
|
756
|
-
* Retrieves upload metadata by file ID.
|
|
757
|
-
* @param id File ID to retrieve metadata for.
|
|
758
|
-
* @returns Promise resolving to the file metadata object.
|
|
759
|
-
* @throws {UploadError} If the file metadata cannot be found (ERRORS.FILE_NOT_FOUND).
|
|
760
|
-
* @remarks Caches the retrieved metadata for faster subsequent access.
|
|
761
|
-
*/
|
|
762
|
-
async getMeta(id) {
|
|
763
|
-
try {
|
|
764
|
-
const file = await this.meta.get(id);
|
|
765
|
-
this.cache.set(file.id, file);
|
|
766
|
-
return { ...file };
|
|
767
|
-
} catch (error) {
|
|
768
|
-
const httpError = this.normalizeError(error instanceof Error ? error : new Error(String(error)));
|
|
769
|
-
await this.onError(httpError);
|
|
770
|
-
return throwErrorCode(ERRORS.FILE_NOT_FOUND);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Checks if a file has expired and deletes it if so.
|
|
775
|
-
* @param file File object to check for expiration.
|
|
776
|
-
* @returns Promise resolving to the file object if not expired.
|
|
777
|
-
* @throws {UploadError} If the file has expired (ERRORS.GONE).
|
|
778
|
-
* @remarks If the file is expired, it is automatically deleted and the metadata is removed.
|
|
779
|
-
*/
|
|
780
|
-
async checkIfExpired(file) {
|
|
781
|
-
if (isExpired(file)) {
|
|
782
|
-
this.delete(file).catch(() => void 0);
|
|
783
|
-
this.deleteMeta(file.id).catch(() => void 0);
|
|
784
|
-
return throwErrorCode(ERRORS.GONE);
|
|
785
|
-
}
|
|
786
|
-
return file;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Searches for and purges expired uploads.
|
|
790
|
-
* @param maxAge Maximum age of files to keep (files older than this will be purged).
|
|
791
|
-
* Can be a number (milliseconds) or string (e.g., "1h", "30m", "7d").
|
|
792
|
-
* If not provided, uses the expiration.maxAge from configuration.
|
|
793
|
-
* @returns Promise resolving to a list of purged files.
|
|
794
|
-
* @remarks
|
|
795
|
-
* Errors during individual file deletions are logged but do not stop the purge process.
|
|
796
|
-
* Files with corrupted metadata are skipped with a warning.
|
|
797
|
-
* Uses rolling expiration if configured (based on modifiedAt) or fixed expiration (based on createdAt).
|
|
798
|
-
*/
|
|
799
|
-
async purge(maxAge) {
|
|
800
|
-
return this.instrumentOperation("purge", async () => {
|
|
801
|
-
const maxAgeMs = toMilliseconds(maxAge || this.expiration?.maxAge);
|
|
802
|
-
const purged = { items: [], maxAgeMs };
|
|
803
|
-
if (maxAgeMs) {
|
|
804
|
-
const before = Date.now() - maxAgeMs;
|
|
805
|
-
const list = await this.list();
|
|
806
|
-
const expired = list.filter(
|
|
807
|
-
(item) => Number(new Date(this.expiration?.rolling ? item.modifiedAt || item.createdAt : item.createdAt)) < before
|
|
808
|
-
);
|
|
809
|
-
for await (const { id, ...rest } of expired) {
|
|
810
|
-
try {
|
|
811
|
-
const deleted = await this.delete({ id });
|
|
812
|
-
purged.items.push({ ...deleted, ...rest });
|
|
813
|
-
} catch (error) {
|
|
814
|
-
this.logger?.warn(`Failed to delete file ${id} during purge: ${error instanceof Error ? error.message : String(error)}`);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
if (purged.items.length > 0) {
|
|
818
|
-
this.logger?.info(`Purge: removed ${purged.items.length} uploads`);
|
|
819
|
-
this.metrics.gauge("storage.operations.purge.items_count", purged.items.length, {
|
|
820
|
-
storage: this.constructor.name.toLowerCase().replace("storage", "")
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
return purged;
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* Gets an uploaded file as a readable stream for efficient large file handling.
|
|
829
|
-
* @param query File query containing the file ID to stream.
|
|
830
|
-
* @param query.id File ID to stream.
|
|
831
|
-
* @returns Promise resolving to an object containing the stream, headers, and size.
|
|
832
|
-
* @throws {UploadError} If the file cannot be found (ERRORS.FILE_NOT_FOUND) or has expired (ERRORS.GONE).
|
|
833
|
-
* @remarks
|
|
834
|
-
* Default implementation falls back to get() and creates a stream from the buffer.
|
|
835
|
-
* Storage implementations should override this for better streaming performance.
|
|
836
|
-
* Headers include Content-Type, Content-Length, ETag, and Last-Modified.
|
|
837
|
-
*/
|
|
838
|
-
async getStream({ id }) {
|
|
839
|
-
return this.instrumentOperation("getStream", async () => {
|
|
840
|
-
const file = await this.get({ id });
|
|
841
|
-
const stream = Readable.from(file.content);
|
|
842
|
-
return {
|
|
843
|
-
headers: {
|
|
844
|
-
"Content-Length": String(file.size),
|
|
845
|
-
"Content-Type": file.contentType,
|
|
846
|
-
...file.ETag && { ETag: file.ETag },
|
|
847
|
-
...file.modifiedAt && { "Last-Modified": file.modifiedAt.toString() }
|
|
848
|
-
},
|
|
849
|
-
size: typeof file.size === "number" ? file.size : void 0,
|
|
850
|
-
stream
|
|
851
|
-
};
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
/**
|
|
855
|
-
* Retrieves a list of uploaded files.
|
|
856
|
-
* @param _limit Maximum number of files to return (default: 1000).
|
|
857
|
-
* @returns Promise resolving to an array of file metadata objects.
|
|
858
|
-
* @throws {Error} If not implemented by the storage backend.
|
|
859
|
-
* @remarks Storage implementations must override this method.
|
|
860
|
-
*/
|
|
861
|
-
async list(_limit = 1e3) {
|
|
862
|
-
return this.instrumentOperation("list", async () => {
|
|
863
|
-
throw new Error("Not implemented");
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Updates file metadata with user-provided key-value pairs.
|
|
868
|
-
* @param query File query containing the file ID to update.
|
|
869
|
-
* @param query.id File ID to update.
|
|
870
|
-
* @param metadata Partial file object containing fields to update.
|
|
871
|
-
* @returns Promise resolving to the updated file object.
|
|
872
|
-
* @throws {UploadError} If the file cannot be found (ERRORS.FILE_NOT_FOUND).
|
|
873
|
-
* @remarks
|
|
874
|
-
* Supports TTL (time-to-live) option: if metadata contains a 'ttl' field,
|
|
875
|
-
* it will be converted to an 'expiredAt' timestamp.
|
|
876
|
-
* TTL can be a number (milliseconds) or string (e.g., "1h", "30m", "7d").
|
|
877
|
-
*/
|
|
878
|
-
async update({ id }, metadata) {
|
|
879
|
-
return this.instrumentOperation("update", async () => {
|
|
880
|
-
const file = await this.getMeta(id);
|
|
881
|
-
const processedMetadata = { ...metadata };
|
|
882
|
-
if ("ttl" in processedMetadata && processedMetadata.ttl !== void 0) {
|
|
883
|
-
const ttlValue = processedMetadata.ttl;
|
|
884
|
-
const ttlMs = typeof ttlValue === "string" ? toMilliseconds(ttlValue) : ttlValue;
|
|
885
|
-
if (ttlMs !== void 0) {
|
|
886
|
-
processedMetadata.expiredAt = Date.now() + ttlMs;
|
|
887
|
-
}
|
|
888
|
-
delete processedMetadata.ttl;
|
|
889
|
-
}
|
|
890
|
-
updateMetadata(file, processedMetadata);
|
|
891
|
-
await this.saveMeta(file);
|
|
892
|
-
const updatedFile = { ...file, status: "updated" };
|
|
893
|
-
await this.onUpdate(updatedFile);
|
|
894
|
-
return updatedFile;
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
/**
|
|
898
|
-
* Deletes multiple files in a single batch operation.
|
|
899
|
-
* @param ids Array of file IDs to delete.
|
|
900
|
-
* @returns Promise resolving to batch operation response with successful and failed deletions.
|
|
901
|
-
* @remarks
|
|
902
|
-
* Processes all deletions in parallel using Promise.allSettled.
|
|
903
|
-
* Individual failures do not stop the batch operation.
|
|
904
|
-
* Each deletion is wrapped in error handling to capture failures.
|
|
905
|
-
* Metrics are recorded for the batch operation and individual failures.
|
|
906
|
-
* Returns both successful and failed operations with detailed error information.
|
|
907
|
-
*/
|
|
908
|
-
async deleteBatch(ids) {
|
|
909
|
-
const startTime = Date.now();
|
|
910
|
-
const storageType = this.constructor.name.toLowerCase().replace("storage", "");
|
|
911
|
-
this.metrics.increment("storage.operations.batch.delete.count", 1, {
|
|
912
|
-
batch_size: ids.length,
|
|
913
|
-
storage: storageType
|
|
914
|
-
});
|
|
915
|
-
const successful = [];
|
|
916
|
-
const failed = [];
|
|
917
|
-
const deletePromises = ids.map(async (id) => {
|
|
918
|
-
try {
|
|
919
|
-
const file = await this.delete({ id });
|
|
920
|
-
return { file, id, success: true };
|
|
921
|
-
} catch (error) {
|
|
922
|
-
const errorMessage = error instanceof Error ? error.message : "Delete failed";
|
|
923
|
-
this.metrics.increment("storage.operations.delete.error.count", 1, {
|
|
924
|
-
error: errorMessage,
|
|
925
|
-
storage: storageType
|
|
926
|
-
});
|
|
927
|
-
return { error: errorMessage, id, success: false };
|
|
928
|
-
}
|
|
929
|
-
});
|
|
930
|
-
const results = await Promise.allSettled(deletePromises);
|
|
931
|
-
for (const result of results) {
|
|
932
|
-
if (result.status === "fulfilled") {
|
|
933
|
-
if (result.value.success) {
|
|
934
|
-
successful.push(result.value.file);
|
|
935
|
-
} else {
|
|
936
|
-
failed.push({ error: result.value.error, id: result.value.id });
|
|
937
|
-
}
|
|
938
|
-
} else {
|
|
939
|
-
failed.push({ error: result.reason?.message || "Delete failed", id: "" });
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
const duration = Date.now() - startTime;
|
|
943
|
-
this.metrics.timing("storage.operations.batch.delete.duration", duration, {
|
|
944
|
-
batch_size: ids.length,
|
|
945
|
-
storage: storageType
|
|
946
|
-
});
|
|
947
|
-
this.metrics.gauge("storage.operations.batch.delete.success_count", successful.length, {
|
|
948
|
-
storage: storageType
|
|
949
|
-
});
|
|
950
|
-
this.metrics.gauge("storage.operations.batch.delete.failed_count", failed.length, {
|
|
951
|
-
storage: storageType
|
|
952
|
-
});
|
|
953
|
-
return {
|
|
954
|
-
failed,
|
|
955
|
-
failedCount: failed.length,
|
|
956
|
-
successful,
|
|
957
|
-
successfulCount: successful.length
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
/**
|
|
961
|
-
* Copies multiple files in a single batch operation.
|
|
962
|
-
* @param operations Array of copy operations, each containing:
|
|
963
|
-
* source: Source file ID.
|
|
964
|
-
* destination: Destination file ID or path.
|
|
965
|
-
* options: Optional copy options including storage class.
|
|
966
|
-
* @returns Promise resolving to batch operation response with successful and failed copies.
|
|
967
|
-
* @remarks
|
|
968
|
-
* Processes all copies in parallel using Promise.allSettled.
|
|
969
|
-
* Individual failures do not stop the batch operation.
|
|
970
|
-
* Each copy operation is wrapped in error handling to capture failures.
|
|
971
|
-
* Metrics are recorded for the batch operation and individual failures.
|
|
972
|
-
* Returns both successful and failed operations with detailed error information.
|
|
973
|
-
*/
|
|
974
|
-
async copyBatch(operations) {
|
|
975
|
-
const startTime = Date.now();
|
|
976
|
-
const storageType = this.constructor.name.toLowerCase().replace("storage", "");
|
|
977
|
-
this.metrics.increment("storage.operations.batch.copy.count", 1, {
|
|
978
|
-
batch_size: operations.length,
|
|
979
|
-
storage: storageType
|
|
980
|
-
});
|
|
981
|
-
const successful = [];
|
|
982
|
-
const failed = [];
|
|
983
|
-
const copyPromises = operations.map(async ({ destination, options, source }) => {
|
|
984
|
-
try {
|
|
985
|
-
const copiedFile = await this.copy(source, destination, options);
|
|
986
|
-
return { file: copiedFile, id: destination, success: true };
|
|
987
|
-
} catch (error) {
|
|
988
|
-
const errorMessage = error instanceof Error ? error.message : "Copy failed";
|
|
989
|
-
this.metrics.increment("storage.operations.copy.error.count", 1, {
|
|
990
|
-
error: errorMessage,
|
|
991
|
-
storage: storageType
|
|
992
|
-
});
|
|
993
|
-
return { error: errorMessage, id: destination, success: false };
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
const results = await Promise.allSettled(copyPromises);
|
|
997
|
-
for (const result of results) {
|
|
998
|
-
if (result.status === "fulfilled") {
|
|
999
|
-
if (result.value.success && result.value.file) {
|
|
1000
|
-
successful.push(result.value.file);
|
|
1001
|
-
} else {
|
|
1002
|
-
failed.push({ error: result.value.error || "Copy failed", id: result.value.id });
|
|
1003
|
-
}
|
|
1004
|
-
} else {
|
|
1005
|
-
failed.push({ error: result.reason?.message || "Copy failed", id: "" });
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
const duration = Date.now() - startTime;
|
|
1009
|
-
this.metrics.timing("storage.operations.batch.copy.duration", duration, {
|
|
1010
|
-
batch_size: operations.length,
|
|
1011
|
-
storage: storageType
|
|
1012
|
-
});
|
|
1013
|
-
this.metrics.gauge("storage.operations.batch.copy.success_count", successful.length, {
|
|
1014
|
-
storage: storageType
|
|
1015
|
-
});
|
|
1016
|
-
this.metrics.gauge("storage.operations.batch.copy.failed_count", failed.length, {
|
|
1017
|
-
storage: storageType
|
|
1018
|
-
});
|
|
1019
|
-
return {
|
|
1020
|
-
failed,
|
|
1021
|
-
failedCount: failed.length,
|
|
1022
|
-
successful,
|
|
1023
|
-
successfulCount: successful.length
|
|
1024
|
-
};
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Moves multiple files in a single batch operation.
|
|
1028
|
-
* @param operations Array of move operations, each containing:
|
|
1029
|
-
* source: Source file ID.
|
|
1030
|
-
* destination: Destination file ID or path.
|
|
1031
|
-
* @returns Promise resolving to batch operation response with successful and failed moves.
|
|
1032
|
-
* @remarks
|
|
1033
|
-
* Processes all moves in parallel using Promise.allSettled.
|
|
1034
|
-
* Individual failures do not stop the batch operation.
|
|
1035
|
-
* Each move operation is wrapped in error handling to capture failures.
|
|
1036
|
-
* Metrics are recorded for the batch operation and individual failures.
|
|
1037
|
-
* Returns both successful and failed operations with detailed error information.
|
|
1038
|
-
*/
|
|
1039
|
-
async moveBatch(operations) {
|
|
1040
|
-
const startTime = Date.now();
|
|
1041
|
-
const storageType = this.constructor.name.toLowerCase().replace("storage", "");
|
|
1042
|
-
this.metrics.increment("storage.operations.batch.move.count", 1, {
|
|
1043
|
-
batch_size: operations.length,
|
|
1044
|
-
storage: storageType
|
|
1045
|
-
});
|
|
1046
|
-
const successful = [];
|
|
1047
|
-
const failed = [];
|
|
1048
|
-
const movePromises = operations.map(async ({ destination, source }) => {
|
|
1049
|
-
try {
|
|
1050
|
-
const movedFile = await this.move(source, destination);
|
|
1051
|
-
return { file: movedFile, id: destination, success: true };
|
|
1052
|
-
} catch (error) {
|
|
1053
|
-
const errorMessage = error instanceof Error ? error.message : "Move failed";
|
|
1054
|
-
this.metrics.increment("storage.operations.move.error.count", 1, {
|
|
1055
|
-
error: errorMessage,
|
|
1056
|
-
storage: storageType
|
|
1057
|
-
});
|
|
1058
|
-
return { error: errorMessage, id: destination, success: false };
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
const results = await Promise.allSettled(movePromises);
|
|
1062
|
-
for (const result of results) {
|
|
1063
|
-
if (result.status === "fulfilled") {
|
|
1064
|
-
if (result.value.success && result.value.file) {
|
|
1065
|
-
successful.push(result.value.file);
|
|
1066
|
-
} else {
|
|
1067
|
-
failed.push({ error: result.value.error || "Move failed", id: result.value.id });
|
|
1068
|
-
}
|
|
1069
|
-
} else {
|
|
1070
|
-
failed.push({ error: result.reason?.message || "Move failed", id: result.reason?.id || "" });
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
const duration = Date.now() - startTime;
|
|
1074
|
-
this.metrics.timing("storage.operations.batch.move.duration", duration, {
|
|
1075
|
-
batch_size: operations.length,
|
|
1076
|
-
storage: storageType
|
|
1077
|
-
});
|
|
1078
|
-
this.metrics.gauge("storage.operations.batch.move.success_count", successful.length, {
|
|
1079
|
-
storage: storageType
|
|
1080
|
-
});
|
|
1081
|
-
this.metrics.gauge("storage.operations.batch.move.failed_count", failed.length, {
|
|
1082
|
-
storage: storageType
|
|
1083
|
-
});
|
|
1084
|
-
return {
|
|
1085
|
-
failed,
|
|
1086
|
-
failedCount: failed.length,
|
|
1087
|
-
successful,
|
|
1088
|
-
successfulCount: successful.length
|
|
1089
|
-
};
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Prevent upload from being accessed by multiple requests
|
|
1093
|
-
*/
|
|
1094
|
-
async lock(key) {
|
|
1095
|
-
const activeUploads = [...this.locker.keys()];
|
|
1096
|
-
if (activeUploads.includes(key)) {
|
|
1097
|
-
return throwErrorCode(ERRORS.FILE_LOCKED);
|
|
1098
|
-
}
|
|
1099
|
-
if (this.config.concurrency && typeof this.config.concurrency === "number" && this.config.concurrency < activeUploads.length) {
|
|
1100
|
-
return throwErrorCode(ERRORS.STORAGE_BUSY);
|
|
1101
|
-
}
|
|
1102
|
-
this.locker.set(key, key);
|
|
1103
|
-
return key;
|
|
1104
|
-
}
|
|
1105
|
-
async unlock(key) {
|
|
1106
|
-
this.locker.unlock(key);
|
|
1107
|
-
}
|
|
1108
|
-
isUnsupportedChecksum(algorithm = "") {
|
|
1109
|
-
return !!algorithm && !this.checksumTypes.includes(algorithm);
|
|
1110
|
-
}
|
|
1111
|
-
startAutoPurge(purgeInterval) {
|
|
1112
|
-
if (purgeInterval >= 2147483647) {
|
|
1113
|
-
throw new Error("“purgeInterval” must be less than 2147483647 ms");
|
|
1114
|
-
}
|
|
1115
|
-
setInterval(() => {
|
|
1116
|
-
this.purge().catch((error) => this.logger?.error(error));
|
|
1117
|
-
}, purgeInterval);
|
|
1118
|
-
}
|
|
1119
|
-
updateTimestamps(file) {
|
|
1120
|
-
file.createdAt ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
1121
|
-
const maxAgeMs = toMilliseconds(this.expiration?.maxAge);
|
|
1122
|
-
if (maxAgeMs && !file.expiredAt) {
|
|
1123
|
-
file.expiredAt = this.expiration?.rolling ? Date.now() + maxAgeMs : +new Date(file.createdAt) + maxAgeMs;
|
|
1124
|
-
}
|
|
1125
|
-
return file;
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Instruments a storage operation with metrics and error tracking.
|
|
1129
|
-
* @param operation Operation name (e.g., "create", "delete", "copy").
|
|
1130
|
-
* @param function_ The operation function to execute.
|
|
1131
|
-
* @param attributes Additional attributes to include in metrics.
|
|
1132
|
-
* @returns Promise resolving to the operation result.
|
|
1133
|
-
* @throws Re-throws any errors from the operation function.
|
|
1134
|
-
* @remarks
|
|
1135
|
-
* Records operation count, duration, and error metrics.
|
|
1136
|
-
* Tracks file sizes for operations returning file objects.
|
|
1137
|
-
* Error metrics include error messages for debugging.
|
|
1138
|
-
* All public methods should use this wrapper for consistent instrumentation.
|
|
1139
|
-
*/
|
|
1140
|
-
async instrumentOperation(operation, function_, attributes) {
|
|
1141
|
-
const startTime = Date.now();
|
|
1142
|
-
const storageType = this.constructor.name.toLowerCase().replace("storage", "");
|
|
1143
|
-
const baseAttributes = {
|
|
1144
|
-
storage: storageType,
|
|
1145
|
-
...attributes
|
|
1146
|
-
};
|
|
1147
|
-
try {
|
|
1148
|
-
this.metrics.increment(`storage.operations.${operation}.count`, 1, baseAttributes);
|
|
1149
|
-
const result = await function_();
|
|
1150
|
-
const duration = Date.now() - startTime;
|
|
1151
|
-
this.metrics.timing(`storage.operations.${operation}.duration`, duration, baseAttributes);
|
|
1152
|
-
if (result && typeof result === "object" && "size" in result && typeof result.size === "number") {
|
|
1153
|
-
this.metrics.gauge("storage.files.size", result.size, {
|
|
1154
|
-
...baseAttributes,
|
|
1155
|
-
operation
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1158
|
-
return result;
|
|
1159
|
-
} catch (error) {
|
|
1160
|
-
const duration = Date.now() - startTime;
|
|
1161
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1162
|
-
this.metrics.timing(`storage.operations.${operation}.duration`, duration, {
|
|
1163
|
-
...baseAttributes,
|
|
1164
|
-
error: "true"
|
|
1165
|
-
});
|
|
1166
|
-
this.metrics.increment(`storage.operations.${operation}.error.count`, 1, {
|
|
1167
|
-
...baseAttributes,
|
|
1168
|
-
error: errorMessage
|
|
1169
|
-
});
|
|
1170
|
-
throw error;
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
export { BaseStorage as B, defaultFilesystemFileNameValidation as a, parseBytes as b, defaultCloudStorageFileNameValidation as d, parseDuration as p, toMilliseconds as t, updateMetadata as u };
|