@webiny/api-file-manager-s3 0.0.0-unstable.b14eaecf38 → 0.0.0-unstable.b6d7105cee
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/assetDelivery/abstractions.d.ts +11 -0
- package/assetDelivery/abstractions.js +7 -0
- package/assetDelivery/abstractions.js.map +1 -0
- package/assetDelivery/assetDeliveryConfig.d.ts +2 -0
- package/assetDelivery/assetDeliveryConfig.js +15 -0
- package/assetDelivery/assetDeliveryConfig.js.map +1 -0
- package/assetDelivery/createAssetDelivery.d.ts +3 -0
- package/assetDelivery/createAssetDelivery.js +9 -0
- package/assetDelivery/createAssetDelivery.js.map +1 -0
- package/assetDelivery/feature.d.ts +5 -0
- package/assetDelivery/feature.js +38 -0
- package/assetDelivery/feature.js.map +1 -0
- package/assetDelivery/index.d.ts +7 -0
- package/assetDelivery/index.js +7 -0
- package/assetDelivery/s3/S3AssetResolver.d.ts +15 -0
- package/assetDelivery/s3/S3AssetResolver.js +41 -0
- package/assetDelivery/s3/S3AssetResolver.js.map +1 -0
- package/assetDelivery/s3/S3ContentsReader.d.ts +9 -0
- package/assetDelivery/s3/S3ContentsReader.js +20 -0
- package/assetDelivery/s3/S3ContentsReader.js.map +1 -0
- package/assetDelivery/s3/S3ErrorAssetReply.d.ts +5 -0
- package/assetDelivery/s3/S3ErrorAssetReply.js +17 -0
- package/assetDelivery/s3/S3ErrorAssetReply.js.map +1 -0
- package/assetDelivery/s3/S3OutputStrategy.d.ts +17 -0
- package/assetDelivery/s3/S3OutputStrategy.js +41 -0
- package/assetDelivery/s3/S3OutputStrategy.js.map +1 -0
- package/assetDelivery/s3/S3RedirectAssetReply.d.ts +4 -0
- package/assetDelivery/s3/S3RedirectAssetReply.js +17 -0
- package/assetDelivery/s3/S3RedirectAssetReply.js.map +1 -0
- package/assetDelivery/s3/SharpTransform.d.ts +26 -0
- package/assetDelivery/s3/SharpTransform.js +186 -0
- package/assetDelivery/s3/SharpTransform.js.map +1 -0
- package/assetDelivery/threatDetection/createThreatDetectionEventHandler.d.ts +2 -0
- package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js +38 -0
- package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js.map +1 -0
- package/assetDelivery/threatDetection/createThreatDetectionPluginLoader.d.ts +2 -0
- package/assetDelivery/threatDetection/createThreatDetectionPluginLoader.js +5 -0
- package/assetDelivery/threatDetection/createThreatDetectionPluginLoader.js.map +1 -0
- package/assetDelivery/threatDetection/index.d.ts +2 -0
- package/assetDelivery/threatDetection/index.js +2 -0
- package/assetDelivery/threatDetection/processThreatScanResult.d.ts +3 -0
- package/assetDelivery/threatDetection/processThreatScanResult.js +61 -0
- package/assetDelivery/threatDetection/processThreatScanResult.js.map +1 -0
- package/assetDelivery/threatDetection/types.d.ts +9 -0
- package/assetDelivery/threatDetection/types.js +0 -0
- package/assetDelivery/types.d.ts +13 -0
- package/assetDelivery/types.js +0 -0
- package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.d.ts +11 -0
- package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.js +23 -0
- package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.js.map +1 -0
- package/enterprise/ApplyThreatScanning/feature.d.ts +4 -0
- package/enterprise/ApplyThreatScanning/feature.js +11 -0
- package/enterprise/ApplyThreatScanning/feature.js.map +1 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +8 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +51 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -0
- package/features/CompleteMultiPartUpload/feature.d.ts +4 -0
- package/features/CompleteMultiPartUpload/feature.js +11 -0
- package/features/CompleteMultiPartUpload/feature.js.map +1 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +9 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +40 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -0
- package/features/CreateMultiPartUpload/feature.d.ts +4 -0
- package/features/CreateMultiPartUpload/feature.js +11 -0
- package/features/CreateMultiPartUpload/feature.js.map +1 -0
- package/features/DeleteFileFromBucket/DeleteFileFromBucketHandler.d.ts +15 -0
- package/features/DeleteFileFromBucket/DeleteFileFromBucketHandler.js +35 -0
- package/features/DeleteFileFromBucket/DeleteFileFromBucketHandler.js.map +1 -0
- package/features/DeleteFileFromBucket/DeleteS3FolderTask.d.ts +32 -0
- package/features/DeleteFileFromBucket/DeleteS3FolderTask.js +50 -0
- package/features/DeleteFileFromBucket/DeleteS3FolderTask.js.map +1 -0
- package/features/DeleteFileFromBucket/feature.d.ts +4 -0
- package/features/DeleteFileFromBucket/feature.js +13 -0
- package/features/DeleteFileFromBucket/feature.js.map +1 -0
- package/features/ExtractMetadata/ExtractMetadataHandler.d.ts +1 -0
- package/features/ExtractMetadata/ExtractMetadataHandler.js +1 -0
- package/features/ExtractMetadata/ExtractMetadataTask.d.ts +22 -0
- package/features/ExtractMetadata/ExtractMetadataTask.js +88 -0
- package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -0
- package/features/ExtractMetadata/feature.d.ts +4 -0
- package/features/ExtractMetadata/feature.js +13 -0
- package/features/ExtractMetadata/feature.js.map +1 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.d.ts +12 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.js +28 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.js.map +1 -0
- package/features/FlushCache/FlushCacheOnFileUpdateHandler.d.ts +12 -0
- package/features/FlushCache/FlushCacheOnFileUpdateHandler.js +31 -0
- package/features/FlushCache/FlushCacheOnFileUpdateHandler.js.map +1 -0
- package/features/FlushCache/InvalidateCacheTask.d.ts +26 -0
- package/features/FlushCache/InvalidateCacheTask.js +75 -0
- package/features/FlushCache/InvalidateCacheTask.js.map +1 -0
- package/features/FlushCache/feature.d.ts +4 -0
- package/features/FlushCache/feature.js +15 -0
- package/features/FlushCache/feature.js.map +1 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +13 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +39 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -0
- package/features/GetFileContentsById/feature.d.ts +4 -0
- package/features/GetFileContentsById/feature.js +11 -0
- package/features/GetFileContentsById/feature.js.map +1 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +13 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +40 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -0
- package/features/GetFileContentsByKey/feature.d.ts +4 -0
- package/features/GetFileContentsByKey/feature.js +11 -0
- package/features/GetFileContentsByKey/feature.js.map +1 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +14 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js +54 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -0
- package/features/GetUploadPayload/feature.d.ts +4 -0
- package/features/GetUploadPayload/feature.js +11 -0
- package/features/GetUploadPayload/feature.js.map +1 -0
- package/index.d.ts +4 -2
- package/index.js +32 -10
- package/index.js.map +1 -1
- package/package.json +29 -26
- package/types.d.ts +3 -19
- package/types.js +1 -5
- package/utils/CdnPathsGenerator.d.ts +3 -0
- package/utils/CdnPathsGenerator.js +11 -0
- package/utils/CdnPathsGenerator.js.map +1 -0
- package/utils/uploadFileToS3.d.ts +2 -4
- package/utils/uploadFileToS3.js +13 -23
- package/utils/uploadFileToS3.js.map +1 -1
- package/plugins/checkBasePermissions.d.ts +0 -5
- package/plugins/checkBasePermissions.js +0 -24
- package/plugins/checkBasePermissions.js.map +0 -1
- package/plugins/checkPermission.d.ts +0 -4
- package/plugins/checkPermission.js +0 -25
- package/plugins/checkPermission.js.map +0 -1
- package/plugins/fileStorageS3.d.ts +0 -3
- package/plugins/fileStorageS3.js +0 -55
- package/plugins/fileStorageS3.js.map +0 -1
- package/plugins/graphqlFileStorageS3.d.ts +0 -4
- package/plugins/graphqlFileStorageS3.js +0 -108
- package/plugins/graphqlFileStorageS3.js.map +0 -1
- package/types.js.map +0 -1
- package/utils/getPresignedPostPayload.d.ts +0 -3
- package/utils/getPresignedPostPayload.js +0 -83
- package/utils/getPresignedPostPayload.js.map +0 -1
- package/utils/mimeTypes.d.ts +0 -5
- package/utils/mimeTypes.js +0 -20
- package/utils/mimeTypes.js.map +0 -1
package/README.md
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
# @webiny/api-file-manager-s3
|
|
1
|
+
# @webiny/api-file-manager-s3
|
|
2
|
+
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is part of the [Webiny](https://www.webiny.com) monorepo.
|
|
5
|
+
> It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
|
|
6
|
+
|
|
7
|
+
📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
_This README file is automatically generated during the publish process._
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
2
|
+
import type { ImageFormat } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
|
|
3
|
+
export interface IS3AssetDeliveryConfig {
|
|
4
|
+
presignedUrlTtl: number;
|
|
5
|
+
imageResizeWidths: number[];
|
|
6
|
+
imageQuality?: Partial<Record<ImageFormat, number>>;
|
|
7
|
+
assetStreamingMaxSize: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const S3AssetDeliveryConfig: import("@webiny/di").Abstraction<IS3AssetDeliveryConfig>;
|
|
10
|
+
export declare const S3Client: import("@webiny/di").Abstraction<S3>;
|
|
11
|
+
export declare const S3Bucket: import("@webiny/di").Abstraction<string>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createAbstraction } from "@webiny/feature/api";
|
|
2
|
+
const S3AssetDeliveryConfig = createAbstraction("AssetDelivery/S3Config");
|
|
3
|
+
const S3Client = createAbstraction("AssetDelivery/S3Client");
|
|
4
|
+
const S3Bucket = createAbstraction("AssetDelivery/S3Bucket");
|
|
5
|
+
export { S3AssetDeliveryConfig, S3Bucket, S3Client };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=abstractions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/abstractions.js","sources":["../../src/assetDelivery/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport type { ImageFormat } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\n\nexport interface IS3AssetDeliveryConfig {\n presignedUrlTtl: number;\n imageResizeWidths: number[];\n imageQuality?: Partial<Record<ImageFormat, number>>;\n assetStreamingMaxSize: number;\n}\n\nexport const S3AssetDeliveryConfig =\n createAbstraction<IS3AssetDeliveryConfig>(\"AssetDelivery/S3Config\");\n\nexport const S3Client = createAbstraction<S3>(\"AssetDelivery/S3Client\");\n\nexport const S3Bucket = createAbstraction<string>(\"AssetDelivery/S3Bucket\");\n"],"names":["S3AssetDeliveryConfig","createAbstraction","S3Client","S3Bucket"],"mappings":";AAWO,MAAMA,wBACTC,kBAA0C;AAEvC,MAAMC,WAAWD,kBAAsB;AAEvC,MAAME,WAAWF,kBAA0B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { AssetDeliveryParams } from "../assetDelivery/types.js";
|
|
2
|
+
export declare const assetDeliveryConfig: (params: AssetDeliveryParams) => ((import("@webiny/handler").ModifyFastifyPlugin | import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types").Context>)[] | import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types").Context>)[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createAssetDelivery } from "@webiny/api-file-manager";
|
|
2
|
+
import { createRegisterExtensionPlugin } from "@webiny/handler";
|
|
3
|
+
import { createS3AssetDeliveryFeature } from "./feature.js";
|
|
4
|
+
const assetDeliveryConfig = (params)=>{
|
|
5
|
+
const feature = createS3AssetDeliveryFeature(params);
|
|
6
|
+
return [
|
|
7
|
+
createAssetDelivery(),
|
|
8
|
+
createRegisterExtensionPlugin((context)=>{
|
|
9
|
+
feature.register(context.container);
|
|
10
|
+
})
|
|
11
|
+
];
|
|
12
|
+
};
|
|
13
|
+
export { assetDeliveryConfig };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=assetDeliveryConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/assetDeliveryConfig.js","sources":["../../src/assetDelivery/assetDeliveryConfig.ts"],"sourcesContent":["import { createAssetDelivery as createBaseAssetDelivery } from \"@webiny/api-file-manager\";\nimport { createRegisterExtensionPlugin } from \"@webiny/handler\";\nimport type { AssetDeliveryParams } from \"~/assetDelivery/types.js\";\nimport { createS3AssetDeliveryFeature } from \"~/assetDelivery/feature.js\";\n\nexport const assetDeliveryConfig = (params: AssetDeliveryParams) => {\n const feature = createS3AssetDeliveryFeature(params);\n\n return [\n createBaseAssetDelivery(),\n createRegisterExtensionPlugin(context => {\n feature.register(context.container);\n })\n ];\n};\n"],"names":["assetDeliveryConfig","params","feature","createS3AssetDeliveryFeature","createBaseAssetDelivery","createRegisterExtensionPlugin","context"],"mappings":";;;AAKO,MAAMA,sBAAsB,CAACC;IAChC,MAAMC,UAAUC,6BAA6BF;IAE7C,OAAO;QACHG;QACAC,8BAA8BC,CAAAA;YAC1BJ,QAAQ,QAAQ,CAACI,QAAQ,SAAS;QACtC;KACH;AACL"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createAssetDeliveryPluginLoader } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
import { createThreatDetectionPluginLoader } from "./threatDetection/index.js";
|
|
3
|
+
const createAssetDelivery = (params = {})=>[
|
|
4
|
+
createAssetDeliveryPluginLoader(()=>import("./assetDeliveryConfig.js").then(({ assetDeliveryConfig })=>assetDeliveryConfig(params))),
|
|
5
|
+
createThreatDetectionPluginLoader(()=>import("./threatDetection/createThreatDetectionEventHandler.js").then(({ createThreatDetectionEventHandler })=>createThreatDetectionEventHandler()))
|
|
6
|
+
];
|
|
7
|
+
export { createAssetDelivery };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=createAssetDelivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/createAssetDelivery.js","sources":["../../src/assetDelivery/createAssetDelivery.ts"],"sourcesContent":["import { createAssetDeliveryPluginLoader } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport type { PluginFactory } from \"@webiny/plugins/types.js\";\nimport { createThreatDetectionPluginLoader } from \"~/assetDelivery/threatDetection/index.js\";\nimport type { AssetDeliveryParams } from \"~/assetDelivery/types.js\";\n\nexport const createAssetDelivery = (params: AssetDeliveryParams = {}): PluginFactory[] => {\n return [\n /**\n * We only want to load this plugin in the context of the Asset Delivery Lambda function.\n */\n createAssetDeliveryPluginLoader(() => {\n return import(\n /* webpackChunkName: \"s3AssetDelivery\" */ \"./assetDeliveryConfig.js\"\n ).then(({ assetDeliveryConfig }) => assetDeliveryConfig(params));\n }),\n /**\n * We only want to load this plugin in the context of the Threat Detection Lambda function.\n */\n createThreatDetectionPluginLoader(() => {\n return import(\n /* webpackChunkName: \"threatDetectionEventHandler\" */ \"./threatDetection/createThreatDetectionEventHandler.js\"\n ).then(({ createThreatDetectionEventHandler }) => createThreatDetectionEventHandler());\n })\n ];\n};\n"],"names":["createAssetDelivery","params","createAssetDeliveryPluginLoader","assetDeliveryConfig","createThreatDetectionPluginLoader","createThreatDetectionEventHandler"],"mappings":";;AAKO,MAAMA,sBAAsB,CAACC,SAA8B,CAAC,CAAC,GACzD;QAIHC,gCAAgC,IACrB,MAAM,CAAN,4BAEL,IAAI,CAAC,CAAC,EAAEC,mBAAmB,EAAE,GAAKA,oBAAoBF;QAK5DG,kCAAkC,IACvB,MAAM,CAAN,0DAEL,IAAI,CAAC,CAAC,EAAEC,iCAAiC,EAAE,GAAKA;KAEzD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
3
|
+
import { S3AssetDeliveryConfig, S3Bucket, S3Client } from "./abstractions.js";
|
|
4
|
+
import { S3AssetResolverImpl } from "./s3/S3AssetResolver.js";
|
|
5
|
+
import { S3OutputStrategyImpl } from "./s3/S3OutputStrategy.js";
|
|
6
|
+
import { SharpTransformImpl } from "./s3/SharpTransform.js";
|
|
7
|
+
const createS3AssetDeliveryFeature = (params = {})=>createFeature({
|
|
8
|
+
name: "AssetDelivery/S3",
|
|
9
|
+
register (container) {
|
|
10
|
+
container.registerInstance(S3Client, new S3({
|
|
11
|
+
region: process.env.AWS_REGION
|
|
12
|
+
}));
|
|
13
|
+
container.registerInstance(S3Bucket, process.env.S3_BUCKET);
|
|
14
|
+
container.registerInstance(S3AssetDeliveryConfig, {
|
|
15
|
+
presignedUrlTtl: params.presignedUrlTtl ?? 3600,
|
|
16
|
+
imageResizeWidths: params.imageResizeWidths ?? [
|
|
17
|
+
128,
|
|
18
|
+
384,
|
|
19
|
+
640,
|
|
20
|
+
750,
|
|
21
|
+
828,
|
|
22
|
+
1080,
|
|
23
|
+
1200,
|
|
24
|
+
1920,
|
|
25
|
+
2048,
|
|
26
|
+
3840
|
|
27
|
+
],
|
|
28
|
+
imageQuality: params.imageQuality ?? {},
|
|
29
|
+
assetStreamingMaxSize: params.assetStreamingMaxSize ?? 4718592
|
|
30
|
+
});
|
|
31
|
+
container.register(S3AssetResolverImpl);
|
|
32
|
+
container.register(S3OutputStrategyImpl);
|
|
33
|
+
container.register(SharpTransformImpl).inSingletonScope();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
export { createS3AssetDeliveryFeature };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/feature.js","sources":["../../src/assetDelivery/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { S3Client, S3Bucket, S3AssetDeliveryConfig } from \"./abstractions.js\";\nimport type { AssetDeliveryParams } from \"./types.js\";\nimport { S3AssetResolverImpl } from \"./s3/S3AssetResolver.js\";\nimport { S3OutputStrategyImpl } from \"./s3/S3OutputStrategy.js\";\nimport { SharpTransformImpl } from \"./s3/SharpTransform.js\";\n\nexport const createS3AssetDeliveryFeature = (params: AssetDeliveryParams = {}) => {\n return createFeature({\n name: \"AssetDelivery/S3\",\n register(container) {\n container.registerInstance(\n S3Client,\n new S3({ region: process.env.AWS_REGION as string })\n );\n container.registerInstance(S3Bucket, process.env.S3_BUCKET as string);\n container.registerInstance(S3AssetDeliveryConfig, {\n presignedUrlTtl: params.presignedUrlTtl ?? 3600,\n imageResizeWidths: params.imageResizeWidths ?? [\n 128, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840\n ],\n imageQuality: params.imageQuality ?? {},\n assetStreamingMaxSize: params.assetStreamingMaxSize ?? 4718592\n });\n\n container.register(S3AssetResolverImpl);\n container.register(S3OutputStrategyImpl);\n container.register(SharpTransformImpl).inSingletonScope();\n }\n });\n};\n"],"names":["createS3AssetDeliveryFeature","params","createFeature","container","S3Client","S3","process","S3Bucket","S3AssetDeliveryConfig","S3AssetResolverImpl","S3OutputStrategyImpl","SharpTransformImpl"],"mappings":";;;;;;AAQO,MAAMA,+BAA+B,CAACC,SAA8B,CAAC,CAAC,GAClEC,cAAc;QACjB,MAAM;QACN,UAASC,SAAS;YACdA,UAAU,gBAAgB,CACtBC,UACA,IAAIC,GAAG;gBAAE,QAAQC,QAAQ,GAAG,CAAC,UAAU;YAAW;YAEtDH,UAAU,gBAAgB,CAACI,UAAUD,QAAQ,GAAG,CAAC,SAAS;YAC1DH,UAAU,gBAAgB,CAACK,uBAAuB;gBAC9C,iBAAiBP,OAAO,eAAe,IAAI;gBAC3C,mBAAmBA,OAAO,iBAAiB,IAAI;oBAC3C;oBAAK;oBAAK;oBAAK;oBAAK;oBAAK;oBAAM;oBAAM;oBAAM;oBAAM;iBACpD;gBACD,cAAcA,OAAO,YAAY,IAAI,CAAC;gBACtC,uBAAuBA,OAAO,qBAAqB,IAAI;YAC3D;YAEAE,UAAU,QAAQ,CAACM;YACnBN,UAAU,QAAQ,CAACO;YACnBP,UAAU,QAAQ,CAACQ,oBAAoB,gBAAgB;QAC3D;IACJ"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { S3AssetResolver } from "./s3/S3AssetResolver.js";
|
|
2
|
+
export { S3OutputStrategy } from "./s3/S3OutputStrategy.js";
|
|
3
|
+
export { S3ContentsReader } from "./s3/S3ContentsReader.js";
|
|
4
|
+
export { S3ErrorAssetReply } from "./s3/S3ErrorAssetReply.js";
|
|
5
|
+
export { S3RedirectAssetReply } from "./s3/S3RedirectAssetReply.js";
|
|
6
|
+
export { SharpTransform } from "./s3/SharpTransform.js";
|
|
7
|
+
export { CallableContentsReader } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { S3AssetResolver } from "./s3/S3AssetResolver.js";
|
|
2
|
+
export { S3OutputStrategy } from "./s3/S3OutputStrategy.js";
|
|
3
|
+
export { S3ContentsReader } from "./s3/S3ContentsReader.js";
|
|
4
|
+
export { S3ErrorAssetReply } from "./s3/S3ErrorAssetReply.js";
|
|
5
|
+
export { S3RedirectAssetReply } from "./s3/S3RedirectAssetReply.js";
|
|
6
|
+
export { SharpTransform } from "./s3/SharpTransform.js";
|
|
7
|
+
export { CallableContentsReader } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
2
|
+
import { AssetFactory, AssetResolver as AssetResolverAbstraction, ObjectKey } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
3
|
+
import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
|
|
4
|
+
export declare class S3AssetResolver implements AssetResolverAbstraction.Interface {
|
|
5
|
+
private readonly keyValueStore;
|
|
6
|
+
private readonly s3;
|
|
7
|
+
private readonly bucket;
|
|
8
|
+
private readonly objectKey;
|
|
9
|
+
private readonly assetFactory;
|
|
10
|
+
constructor(keyValueStore: GlobalKeyValueStore.Interface, s3: S3, bucket: string, objectKey: ObjectKey.Interface, assetFactory: AssetFactory.Interface);
|
|
11
|
+
resolve(request: AssetResolverAbstraction.Request): Promise<AssetFactory.Asset | undefined>;
|
|
12
|
+
}
|
|
13
|
+
export declare const S3AssetResolverImpl: typeof S3AssetResolver & {
|
|
14
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/delivery").AssetResolver>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AssetFactory, AssetResolver, ObjectKey } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
|
|
3
|
+
import { S3ContentsReader } from "../index.js";
|
|
4
|
+
import { S3Bucket, S3Client } from "../abstractions.js";
|
|
5
|
+
class S3AssetResolver {
|
|
6
|
+
constructor(keyValueStore, s3, bucket, objectKey, assetFactory){
|
|
7
|
+
this.keyValueStore = keyValueStore;
|
|
8
|
+
this.s3 = s3;
|
|
9
|
+
this.bucket = bucket;
|
|
10
|
+
this.objectKey = objectKey;
|
|
11
|
+
this.assetFactory = assetFactory;
|
|
12
|
+
}
|
|
13
|
+
async resolve(request) {
|
|
14
|
+
const fileId = this.objectKey.from(request.getKey()).id();
|
|
15
|
+
const result = await this.keyValueStore.get(`FileManager/File/${fileId}/Metadata`);
|
|
16
|
+
if (result.isFail()) return;
|
|
17
|
+
const metadata = result.value;
|
|
18
|
+
const asset = this.assetFactory.create({
|
|
19
|
+
id: metadata.id,
|
|
20
|
+
tenant: metadata.tenant,
|
|
21
|
+
size: metadata.size,
|
|
22
|
+
contentType: metadata.contentType,
|
|
23
|
+
key: metadata.bucketKey
|
|
24
|
+
});
|
|
25
|
+
asset.setContentsReader(S3ContentsReader.create(this.s3, this.bucket));
|
|
26
|
+
return asset;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const S3AssetResolverImpl = AssetResolver.createImplementation({
|
|
30
|
+
implementation: S3AssetResolver,
|
|
31
|
+
dependencies: [
|
|
32
|
+
GlobalKeyValueStore,
|
|
33
|
+
S3Client,
|
|
34
|
+
S3Bucket,
|
|
35
|
+
ObjectKey,
|
|
36
|
+
AssetFactory
|
|
37
|
+
]
|
|
38
|
+
});
|
|
39
|
+
export { S3AssetResolver, S3AssetResolverImpl };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=S3AssetResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/s3/S3AssetResolver.js","sources":["../../../src/assetDelivery/s3/S3AssetResolver.ts"],"sourcesContent":["import type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport {\n AssetFactory,\n AssetResolver as AssetResolverAbstraction,\n ObjectKey\n} from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { S3ContentsReader } from \"~/assetDelivery/index.js\";\nimport { S3Client, S3Bucket } from \"~/assetDelivery/abstractions.js\";\n\ninterface AssetMetadata {\n id: string;\n tenant: string;\n size: number;\n contentType: string;\n bucketKey: string;\n}\n\nexport class S3AssetResolver implements AssetResolverAbstraction.Interface {\n constructor(\n private readonly keyValueStore: GlobalKeyValueStore.Interface,\n private readonly s3: S3,\n private readonly bucket: string,\n private readonly objectKey: ObjectKey.Interface,\n private readonly assetFactory: AssetFactory.Interface\n ) {}\n\n async resolve(\n request: AssetResolverAbstraction.Request\n ): Promise<AssetFactory.Asset | undefined> {\n const fileId = this.objectKey.from(request.getKey()).id();\n const result = await this.keyValueStore.get<AssetMetadata>(\n `FileManager/File/${fileId}/Metadata`\n );\n\n if (result.isFail()) {\n return undefined;\n }\n\n const metadata = result.value;\n\n const asset = this.assetFactory.create({\n id: metadata.id,\n tenant: metadata.tenant,\n size: metadata.size,\n contentType: metadata.contentType,\n key: metadata.bucketKey\n });\n\n asset.setContentsReader(S3ContentsReader.create(this.s3, this.bucket));\n\n return asset;\n }\n}\n\nexport const S3AssetResolverImpl = AssetResolverAbstraction.createImplementation({\n implementation: S3AssetResolver,\n dependencies: [GlobalKeyValueStore, S3Client, S3Bucket, ObjectKey, AssetFactory]\n});\n"],"names":["S3AssetResolver","keyValueStore","s3","bucket","objectKey","assetFactory","request","fileId","result","metadata","asset","S3ContentsReader","S3AssetResolverImpl","AssetResolverAbstraction","GlobalKeyValueStore","S3Client","S3Bucket","ObjectKey","AssetFactory"],"mappings":";;;;AAkBO,MAAMA;IACT,YACqBC,aAA4C,EAC5CC,EAAM,EACNC,MAAc,EACdC,SAA8B,EAC9BC,YAAoC,CACvD;aALmBJ,aAAa,GAAbA;aACAC,EAAE,GAAFA;aACAC,MAAM,GAANA;aACAC,SAAS,GAATA;aACAC,YAAY,GAAZA;IAClB;IAEH,MAAM,QACFC,OAAyC,EACF;QACvC,MAAMC,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAACD,QAAQ,MAAM,IAAI,EAAE;QACvD,MAAME,SAAS,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CACvC,CAAC,iBAAiB,EAAED,OAAO,SAAS,CAAC;QAGzC,IAAIC,OAAO,MAAM,IACb;QAGJ,MAAMC,WAAWD,OAAO,KAAK;QAE7B,MAAME,QAAQ,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;YACnC,IAAID,SAAS,EAAE;YACf,QAAQA,SAAS,MAAM;YACvB,MAAMA,SAAS,IAAI;YACnB,aAAaA,SAAS,WAAW;YACjC,KAAKA,SAAS,SAAS;QAC3B;QAEAC,MAAM,iBAAiB,CAACC,iBAAiB,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM;QAEpE,OAAOD;IACX;AACJ;AAEO,MAAME,sBAAsBC,cAAAA,oBAA6C,CAAC;IAC7E,gBAAgBb;IAChB,cAAc;QAACc;QAAqBC;QAAUC;QAAUC;QAAWC;KAAa;AACpF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
2
|
+
import { AssetContentsReader } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
3
|
+
export declare class S3ContentsReader implements AssetContentsReader.Interface {
|
|
4
|
+
private readonly s3;
|
|
5
|
+
private readonly bucket;
|
|
6
|
+
static create(s3: S3, bucket: string): S3ContentsReader;
|
|
7
|
+
private constructor();
|
|
8
|
+
read(asset: AssetContentsReader.Asset): Promise<Buffer>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class S3ContentsReader {
|
|
2
|
+
static create(s3, bucket) {
|
|
3
|
+
return new S3ContentsReader(s3, bucket);
|
|
4
|
+
}
|
|
5
|
+
constructor(s3, bucket){
|
|
6
|
+
this.s3 = s3;
|
|
7
|
+
this.bucket = bucket;
|
|
8
|
+
}
|
|
9
|
+
async read(asset) {
|
|
10
|
+
const { Body } = await this.s3.getObject({
|
|
11
|
+
Bucket: this.bucket,
|
|
12
|
+
Key: asset.getKey()
|
|
13
|
+
});
|
|
14
|
+
if (!Body) throw Error(`Unable to read ${asset.getKey()}!`);
|
|
15
|
+
return Buffer.from(await Body.transformToByteArray());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export { S3ContentsReader };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=S3ContentsReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/s3/S3ContentsReader.js","sources":["../../../src/assetDelivery/s3/S3ContentsReader.ts"],"sourcesContent":["import type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { AssetContentsReader } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\n\nexport class S3ContentsReader implements AssetContentsReader.Interface {\n private readonly s3: S3;\n private readonly bucket: string;\n\n public static create(s3: S3, bucket: string) {\n return new S3ContentsReader(s3, bucket);\n }\n\n private constructor(s3: S3, bucket: string) {\n this.s3 = s3;\n this.bucket = bucket;\n }\n\n public async read(asset: AssetContentsReader.Asset): Promise<Buffer> {\n const { Body } = await this.s3.getObject({\n Bucket: this.bucket,\n Key: asset.getKey()\n });\n\n if (!Body) {\n throw Error(`Unable to read ${asset.getKey()}!`);\n }\n\n return Buffer.from(await Body.transformToByteArray());\n }\n}\n"],"names":["S3ContentsReader","s3","bucket","asset","Body","Error","Buffer"],"mappings":"AAGO,MAAMA;IAIT,OAAc,OAAOC,EAAM,EAAEC,MAAc,EAAE;QACzC,OAAO,IAAIF,iBAAiBC,IAAIC;IACpC;IAEA,YAAoBD,EAAM,EAAEC,MAAc,CAAE;QACxC,IAAI,CAAC,EAAE,GAAGD;QACV,IAAI,CAAC,MAAM,GAAGC;IAClB;IAEA,MAAa,KAAKC,KAAgC,EAAmB;QACjE,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;YACrC,QAAQ,IAAI,CAAC,MAAM;YACnB,KAAKD,MAAM,MAAM;QACrB;QAEA,IAAI,CAACC,MACD,MAAMC,MAAM,CAAC,eAAe,EAAEF,MAAM,MAAM,GAAG,CAAC,CAAC;QAGnD,OAAOG,OAAO,IAAI,CAAC,MAAMF,KAAK,oBAAoB;IACtD;AACJ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
class S3ErrorAssetReply extends AssetReply {
|
|
3
|
+
static fromMessage(message) {
|
|
4
|
+
return new S3ErrorAssetReply(message);
|
|
5
|
+
}
|
|
6
|
+
constructor(message){
|
|
7
|
+
super({
|
|
8
|
+
code: 400,
|
|
9
|
+
body: ()=>({
|
|
10
|
+
error: message
|
|
11
|
+
})
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export { S3ErrorAssetReply };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=S3ErrorAssetReply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/s3/S3ErrorAssetReply.js","sources":["../../../src/assetDelivery/s3/S3ErrorAssetReply.ts"],"sourcesContent":["import { AssetReply } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\n\nexport class S3ErrorAssetReply extends AssetReply {\n public static fromMessage(message: string) {\n return new S3ErrorAssetReply(message);\n }\n\n private constructor(message: string) {\n super({\n code: 400,\n body: () => ({ error: message })\n });\n }\n}\n"],"names":["S3ErrorAssetReply","AssetReply","message"],"mappings":";AAEO,MAAMA,0BAA0BC;IACnC,OAAc,YAAYC,OAAe,EAAE;QACvC,OAAO,IAAIF,kBAAkBE;IACjC;IAEA,YAAoBA,OAAe,CAAE;QACjC,KAAK,CAAC;YACF,MAAM;YACN,MAAM,IAAO;oBAAE,OAAOA;gBAAQ;QAClC;IACJ;AACJ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AssetOutputStrategy as AssetOutputStrategyAbstraction } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
3
|
+
import { StreamAssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
4
|
+
import type { IS3AssetDeliveryConfig } from "../../assetDelivery/abstractions.js";
|
|
5
|
+
export declare class S3OutputStrategy implements AssetOutputStrategyAbstraction.Interface {
|
|
6
|
+
private readonly s3;
|
|
7
|
+
private readonly bucket;
|
|
8
|
+
private readonly presignedUrlTtl;
|
|
9
|
+
private readonly assetStreamingMaxSize;
|
|
10
|
+
private readonly streamAssetReply;
|
|
11
|
+
constructor(s3: S3, bucket: string, config: IS3AssetDeliveryConfig, streamAssetReply: StreamAssetReply.Interface);
|
|
12
|
+
output(asset: AssetOutputStrategyAbstraction.Asset): Promise<AssetOutputStrategyAbstraction.AssetReply>;
|
|
13
|
+
protected getPresignedUrl(asset: AssetOutputStrategyAbstraction.Asset): Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
export declare const S3OutputStrategyImpl: typeof S3OutputStrategy & {
|
|
16
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/delivery").AssetOutputStrategy>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AssetOutputStrategy, StreamAssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
import { GetObjectCommand, getSignedUrl } from "@webiny/aws-sdk/client-s3/index.js";
|
|
3
|
+
import { S3RedirectAssetReply } from "./S3RedirectAssetReply.js";
|
|
4
|
+
import { S3AssetDeliveryConfig, S3Bucket, S3Client } from "../abstractions.js";
|
|
5
|
+
class S3OutputStrategy {
|
|
6
|
+
constructor(s3, bucket, config, streamAssetReply){
|
|
7
|
+
this.s3 = s3;
|
|
8
|
+
this.bucket = bucket;
|
|
9
|
+
this.presignedUrlTtl = config.presignedUrlTtl;
|
|
10
|
+
this.assetStreamingMaxSize = config.assetStreamingMaxSize;
|
|
11
|
+
this.streamAssetReply = streamAssetReply;
|
|
12
|
+
}
|
|
13
|
+
async output(asset) {
|
|
14
|
+
if (asset.getSize() > this.assetStreamingMaxSize) {
|
|
15
|
+
console.log(`Asset size is greater than ${this.assetStreamingMaxSize}; redirecting to a presigned S3 URL.`);
|
|
16
|
+
return new S3RedirectAssetReply(await this.getPresignedUrl(asset), this.presignedUrlTtl);
|
|
17
|
+
}
|
|
18
|
+
console.log(`Asset size is smaller than ${this.assetStreamingMaxSize}; streaming directly from Lambda function.`);
|
|
19
|
+
return this.streamAssetReply.create(asset);
|
|
20
|
+
}
|
|
21
|
+
getPresignedUrl(asset) {
|
|
22
|
+
return getSignedUrl(this.s3, new GetObjectCommand({
|
|
23
|
+
Bucket: this.bucket,
|
|
24
|
+
Key: asset.getKey()
|
|
25
|
+
}), {
|
|
26
|
+
expiresIn: this.presignedUrlTtl
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const S3OutputStrategyImpl = AssetOutputStrategy.createImplementation({
|
|
31
|
+
implementation: S3OutputStrategy,
|
|
32
|
+
dependencies: [
|
|
33
|
+
S3Client,
|
|
34
|
+
S3Bucket,
|
|
35
|
+
S3AssetDeliveryConfig,
|
|
36
|
+
StreamAssetReply
|
|
37
|
+
]
|
|
38
|
+
});
|
|
39
|
+
export { S3OutputStrategy, S3OutputStrategyImpl };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=S3OutputStrategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/s3/S3OutputStrategy.js","sources":["../../../src/assetDelivery/s3/S3OutputStrategy.ts"],"sourcesContent":["import { AssetOutputStrategy as AssetOutputStrategyAbstraction } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { GetObjectCommand, getSignedUrl } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { StreamAssetReply } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { S3RedirectAssetReply } from \"~/assetDelivery/s3/S3RedirectAssetReply.js\";\nimport { S3Client, S3Bucket, S3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { IS3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\nexport class S3OutputStrategy implements AssetOutputStrategyAbstraction.Interface {\n private readonly s3: S3;\n private readonly bucket: string;\n private readonly presignedUrlTtl: number;\n private readonly assetStreamingMaxSize: number;\n private readonly streamAssetReply: StreamAssetReply.Interface;\n\n constructor(\n s3: S3,\n bucket: string,\n config: IS3AssetDeliveryConfig,\n streamAssetReply: StreamAssetReply.Interface\n ) {\n this.s3 = s3;\n this.bucket = bucket;\n this.presignedUrlTtl = config.presignedUrlTtl;\n this.assetStreamingMaxSize = config.assetStreamingMaxSize;\n this.streamAssetReply = streamAssetReply;\n }\n\n async output(\n asset: AssetOutputStrategyAbstraction.Asset\n ): Promise<AssetOutputStrategyAbstraction.AssetReply> {\n if (asset.getSize() > this.assetStreamingMaxSize) {\n console.log(\n `Asset size is greater than ${this.assetStreamingMaxSize}; redirecting to a presigned S3 URL.`\n );\n\n return new S3RedirectAssetReply(\n await this.getPresignedUrl(asset),\n this.presignedUrlTtl\n );\n }\n\n console.log(\n `Asset size is smaller than ${this.assetStreamingMaxSize}; streaming directly from Lambda function.`\n );\n return this.streamAssetReply.create(asset);\n }\n\n protected getPresignedUrl(asset: AssetOutputStrategyAbstraction.Asset) {\n return getSignedUrl(\n this.s3,\n new GetObjectCommand({\n Bucket: this.bucket,\n Key: asset.getKey()\n }),\n { expiresIn: this.presignedUrlTtl }\n );\n }\n}\n\nexport const S3OutputStrategyImpl = AssetOutputStrategyAbstraction.createImplementation({\n implementation: S3OutputStrategy,\n dependencies: [S3Client, S3Bucket, S3AssetDeliveryConfig, StreamAssetReply]\n});\n"],"names":["S3OutputStrategy","s3","bucket","config","streamAssetReply","asset","console","S3RedirectAssetReply","getSignedUrl","GetObjectCommand","S3OutputStrategyImpl","AssetOutputStrategyAbstraction","S3Client","S3Bucket","S3AssetDeliveryConfig","StreamAssetReply"],"mappings":";;;;AAQO,MAAMA;IAOT,YACIC,EAAM,EACNC,MAAc,EACdC,MAA8B,EAC9BC,gBAA4C,CAC9C;QACE,IAAI,CAAC,EAAE,GAAGH;QACV,IAAI,CAAC,MAAM,GAAGC;QACd,IAAI,CAAC,eAAe,GAAGC,OAAO,eAAe;QAC7C,IAAI,CAAC,qBAAqB,GAAGA,OAAO,qBAAqB;QACzD,IAAI,CAAC,gBAAgB,GAAGC;IAC5B;IAEA,MAAM,OACFC,KAA2C,EACO;QAClD,IAAIA,MAAM,OAAO,KAAK,IAAI,CAAC,qBAAqB,EAAE;YAC9CC,QAAQ,GAAG,CACP,CAAC,2BAA2B,EAAE,IAAI,CAAC,qBAAqB,CAAC,oCAAoC,CAAC;YAGlG,OAAO,IAAIC,qBACP,MAAM,IAAI,CAAC,eAAe,CAACF,QAC3B,IAAI,CAAC,eAAe;QAE5B;QAEAC,QAAQ,GAAG,CACP,CAAC,2BAA2B,EAAE,IAAI,CAAC,qBAAqB,CAAC,0CAA0C,CAAC;QAExG,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACD;IACxC;IAEU,gBAAgBA,KAA2C,EAAE;QACnE,OAAOG,aACH,IAAI,CAAC,EAAE,EACP,IAAIC,iBAAiB;YACjB,QAAQ,IAAI,CAAC,MAAM;YACnB,KAAKJ,MAAM,MAAM;QACrB,IACA;YAAE,WAAW,IAAI,CAAC,eAAe;QAAC;IAE1C;AACJ;AAEO,MAAMK,uBAAuBC,oBAAAA,oBAAmD,CAAC;IACpF,gBAAgBX;IAChB,cAAc;QAACY;QAAUC;QAAUC;QAAuBC;KAAiB;AAC/E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
|
|
2
|
+
import { ResponseHeaders } from "@webiny/handler";
|
|
3
|
+
class S3RedirectAssetReply extends AssetReply {
|
|
4
|
+
constructor(url, cacheDuration){
|
|
5
|
+
super({
|
|
6
|
+
code: 301,
|
|
7
|
+
headers: ResponseHeaders.create({
|
|
8
|
+
location: url,
|
|
9
|
+
"cache-control": "public, max-age=" + cacheDuration
|
|
10
|
+
}),
|
|
11
|
+
body: ()=>""
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export { S3RedirectAssetReply };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=S3RedirectAssetReply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assetDelivery/s3/S3RedirectAssetReply.js","sources":["../../../src/assetDelivery/s3/S3RedirectAssetReply.ts"],"sourcesContent":["import { AssetReply } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { ResponseHeaders } from \"@webiny/handler\";\n\nexport class S3RedirectAssetReply extends AssetReply {\n constructor(url: string, cacheDuration: number) {\n super({\n code: 301,\n headers: ResponseHeaders.create({\n location: url,\n \"cache-control\": \"public, max-age=\" + cacheDuration\n }),\n body: () => \"\"\n });\n }\n}\n"],"names":["S3RedirectAssetReply","AssetReply","url","cacheDuration","ResponseHeaders"],"mappings":";;AAGO,MAAMA,6BAA6BC;IACtC,YAAYC,GAAW,EAAEC,aAAqB,CAAE;QAC5C,KAAK,CAAC;YACF,MAAM;YACN,SAASC,gBAAgB,MAAM,CAAC;gBAC5B,UAAUF;gBACV,iBAAiB,qBAAqBC;YAC1C;YACA,MAAM,IAAM;QAChB;IACJ;AACJ"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
|
|
2
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
3
|
+
import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
|
|
4
|
+
import { ImageAssetTypeHandler } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js";
|
|
5
|
+
import type { Asset } from "@webiny/api-file-manager/delivery/AssetDelivery/Asset.js";
|
|
6
|
+
import type { AssetRequest } from "@webiny/api-file-manager/delivery/AssetDelivery/AssetRequest.js";
|
|
7
|
+
import type { IS3AssetDeliveryConfig } from "../../assetDelivery/abstractions.js";
|
|
8
|
+
export declare class SharpTransform implements ImageAssetTypeHandler.Interface {
|
|
9
|
+
private readonly s3;
|
|
10
|
+
private readonly bucket;
|
|
11
|
+
private readonly imageResizeWidths;
|
|
12
|
+
private readonly imageQuality;
|
|
13
|
+
private readonly identityContext;
|
|
14
|
+
private readonly getFile;
|
|
15
|
+
constructor(s3: S3, bucket: string, config: IS3AssetDeliveryConfig, identityContext: IdentityContext.Interface, getFile: GetFileUseCase.Interface);
|
|
16
|
+
handle(assetRequest: AssetRequest, asset: Asset): Promise<Asset>;
|
|
17
|
+
private loadAssetCrop;
|
|
18
|
+
private transformAsset;
|
|
19
|
+
private optimizeAsset;
|
|
20
|
+
private isAssetAnimated;
|
|
21
|
+
private optimizePng;
|
|
22
|
+
private optimizeJpeg;
|
|
23
|
+
}
|
|
24
|
+
export declare const SharpTransformImpl: typeof SharpTransform & {
|
|
25
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/assetDelivery/abstractions/AssetType").IAssetTypeHandler>;
|
|
26
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import sharp from "sharp";
|
|
2
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
3
|
+
import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
|
|
4
|
+
import { CallableContentsReader, DEFAULT_IMAGE_QUALITY, contentTypeForFormat } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
|
|
5
|
+
import { extractFramedRegion, transformImageBuffer } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/transformImage.js";
|
|
6
|
+
import { normalizeImageOptions } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/normalizeImageOptions.js";
|
|
7
|
+
import { AssetKeyGenerator, ImageAssetTypeHandler } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js";
|
|
8
|
+
import { S3AssetDeliveryConfig, S3Bucket, S3Client } from "../abstractions.js";
|
|
9
|
+
const hasTransform = (options)=>void 0 !== options.width || void 0 !== options.format || void 0 !== options.quality;
|
|
10
|
+
class SharpTransform {
|
|
11
|
+
constructor(s3, bucket, config, identityContext, getFile){
|
|
12
|
+
this.s3 = s3;
|
|
13
|
+
this.bucket = bucket;
|
|
14
|
+
this.imageResizeWidths = config.imageResizeWidths;
|
|
15
|
+
this.imageQuality = {
|
|
16
|
+
...DEFAULT_IMAGE_QUALITY,
|
|
17
|
+
...config.imageQuality ?? {}
|
|
18
|
+
};
|
|
19
|
+
this.identityContext = identityContext;
|
|
20
|
+
this.getFile = getFile;
|
|
21
|
+
}
|
|
22
|
+
async handle(assetRequest, asset) {
|
|
23
|
+
const rawQuery = assetRequest.getOptions();
|
|
24
|
+
const acceptHeader = assetRequest.getContext().accept;
|
|
25
|
+
const { original, crop, focal, aspectRatio, ...options } = normalizeImageOptions(rawQuery, acceptHeader);
|
|
26
|
+
const assetCrop = await this.loadAssetCrop(asset.getId());
|
|
27
|
+
const framing = {
|
|
28
|
+
crop: crop ?? assetCrop,
|
|
29
|
+
focal,
|
|
30
|
+
aspectRatio
|
|
31
|
+
};
|
|
32
|
+
const transformedAsset = asset.clone();
|
|
33
|
+
if (hasTransform(options)) return this.transformAsset(transformedAsset, options, framing);
|
|
34
|
+
return this.optimizeAsset(transformedAsset, framing);
|
|
35
|
+
}
|
|
36
|
+
async loadAssetCrop(fileId) {
|
|
37
|
+
const result = await this.identityContext.withoutAuthorization(()=>this.getFile.execute(fileId));
|
|
38
|
+
if (result.isFail()) return;
|
|
39
|
+
const imageEdit = result.value.metadata?.imageEdit;
|
|
40
|
+
return imageEdit?.crop;
|
|
41
|
+
}
|
|
42
|
+
async transformAsset(asset, options, framing) {
|
|
43
|
+
const assetKey = AssetKeyGenerator.create(asset, framing);
|
|
44
|
+
const transformedAssetKey = assetKey.getTransformedImageKey(options);
|
|
45
|
+
const contentType = options.format ? contentTypeForFormat(options.format) : asset.getContentType();
|
|
46
|
+
try {
|
|
47
|
+
const { Body } = await this.s3.getObject({
|
|
48
|
+
Bucket: this.bucket,
|
|
49
|
+
Key: transformedAssetKey
|
|
50
|
+
});
|
|
51
|
+
if (!Body) throw new Error("Missing image body!");
|
|
52
|
+
const buffer = Buffer.from(await Body.transformToByteArray());
|
|
53
|
+
const newAsset = asset.withProps({
|
|
54
|
+
size: buffer.length,
|
|
55
|
+
contentType
|
|
56
|
+
});
|
|
57
|
+
newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
|
|
58
|
+
console.log("Return a previously transformed asset", {
|
|
59
|
+
key: transformedAssetKey,
|
|
60
|
+
size: newAsset.getSize()
|
|
61
|
+
});
|
|
62
|
+
return newAsset;
|
|
63
|
+
} catch {
|
|
64
|
+
const optimizedImage = await this.optimizeAsset(asset, framing);
|
|
65
|
+
console.log("Transform the asset", options);
|
|
66
|
+
const baseBuffer = await optimizedImage.getContents();
|
|
67
|
+
const { buffer: transformedBuffer, contentType: outputContentType } = await transformImageBuffer({
|
|
68
|
+
buffer: baseBuffer,
|
|
69
|
+
animated: this.isAssetAnimated(asset),
|
|
70
|
+
sourceContentType: asset.getContentType(),
|
|
71
|
+
widths: this.imageResizeWidths,
|
|
72
|
+
options,
|
|
73
|
+
qualityDefaults: this.imageQuality
|
|
74
|
+
});
|
|
75
|
+
const newAsset = asset.withProps({
|
|
76
|
+
size: transformedBuffer.length,
|
|
77
|
+
contentType: outputContentType
|
|
78
|
+
});
|
|
79
|
+
newAsset.setContentsReader(CallableContentsReader.create(()=>transformedBuffer));
|
|
80
|
+
await this.s3.putObject({
|
|
81
|
+
Bucket: this.bucket,
|
|
82
|
+
Key: transformedAssetKey,
|
|
83
|
+
ContentType: newAsset.getContentType(),
|
|
84
|
+
Body: await newAsset.getContents()
|
|
85
|
+
});
|
|
86
|
+
console.log("Return the transformed asset", {
|
|
87
|
+
key: transformedAssetKey,
|
|
88
|
+
size: newAsset.getSize(),
|
|
89
|
+
contentType: newAsset.getContentType()
|
|
90
|
+
});
|
|
91
|
+
return newAsset;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async optimizeAsset(asset, framing) {
|
|
95
|
+
console.log("Optimize asset", {
|
|
96
|
+
id: asset.getId(),
|
|
97
|
+
key: asset.getKey(),
|
|
98
|
+
size: asset.getSize(),
|
|
99
|
+
type: asset.getContentType()
|
|
100
|
+
});
|
|
101
|
+
const assetKey = AssetKeyGenerator.create(asset, framing);
|
|
102
|
+
const optimizedAssetKey = assetKey.getOptimizedImageKey();
|
|
103
|
+
try {
|
|
104
|
+
const { Body } = await this.s3.getObject({
|
|
105
|
+
Bucket: this.bucket,
|
|
106
|
+
Key: optimizedAssetKey
|
|
107
|
+
});
|
|
108
|
+
if (!Body) throw new Error("Missing image body!");
|
|
109
|
+
console.log("Return a previously optimized asset", optimizedAssetKey);
|
|
110
|
+
const buffer = Buffer.from(await Body.transformToByteArray());
|
|
111
|
+
const newAsset = asset.withProps({
|
|
112
|
+
size: buffer.length
|
|
113
|
+
});
|
|
114
|
+
newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
|
|
115
|
+
return newAsset;
|
|
116
|
+
} catch {
|
|
117
|
+
console.log("Create an optimized version of the original asset", asset.getKey());
|
|
118
|
+
let buffer = await asset.getContents();
|
|
119
|
+
const framed = await extractFramedRegion(buffer, framing);
|
|
120
|
+
const cropped = framed !== buffer;
|
|
121
|
+
buffer = framed;
|
|
122
|
+
const optimizationMap = {
|
|
123
|
+
"image/png": (buffer)=>this.optimizePng(buffer),
|
|
124
|
+
"image/jpeg": (buffer)=>this.optimizeJpeg(buffer),
|
|
125
|
+
"image/jpg": (buffer)=>this.optimizeJpeg(buffer)
|
|
126
|
+
};
|
|
127
|
+
const optimization = optimizationMap[asset.getContentType()];
|
|
128
|
+
if (!optimization && !cropped) {
|
|
129
|
+
console.log(`No optimizations defined for ${asset.getContentType()}`);
|
|
130
|
+
return asset;
|
|
131
|
+
}
|
|
132
|
+
const finalBuffer = optimization ? await optimization(buffer).toBuffer() : buffer;
|
|
133
|
+
console.log("Optimized asset size", finalBuffer.length);
|
|
134
|
+
const newAsset = asset.withProps({
|
|
135
|
+
size: finalBuffer.length
|
|
136
|
+
});
|
|
137
|
+
newAsset.setContentsReader(CallableContentsReader.create(()=>finalBuffer));
|
|
138
|
+
await this.s3.putObject({
|
|
139
|
+
Bucket: this.bucket,
|
|
140
|
+
Key: optimizedAssetKey,
|
|
141
|
+
ContentType: newAsset.getContentType(),
|
|
142
|
+
Body: await newAsset.getContents()
|
|
143
|
+
});
|
|
144
|
+
return newAsset;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
isAssetAnimated(asset) {
|
|
148
|
+
return [
|
|
149
|
+
"gif",
|
|
150
|
+
"webp"
|
|
151
|
+
].includes(asset.getExtension());
|
|
152
|
+
}
|
|
153
|
+
optimizePng(buffer) {
|
|
154
|
+
return sharp(buffer).resize({
|
|
155
|
+
width: 2560,
|
|
156
|
+
withoutEnlargement: true,
|
|
157
|
+
fit: "inside"
|
|
158
|
+
}).png({
|
|
159
|
+
compressionLevel: 9,
|
|
160
|
+
adaptiveFiltering: true,
|
|
161
|
+
force: true
|
|
162
|
+
}).withMetadata();
|
|
163
|
+
}
|
|
164
|
+
optimizeJpeg(buffer) {
|
|
165
|
+
return sharp(buffer).resize({
|
|
166
|
+
width: 2560,
|
|
167
|
+
withoutEnlargement: true,
|
|
168
|
+
fit: "inside"
|
|
169
|
+
}).withMetadata().toFormat("jpeg", {
|
|
170
|
+
quality: 90
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const SharpTransformImpl = ImageAssetTypeHandler.createImplementation({
|
|
175
|
+
implementation: SharpTransform,
|
|
176
|
+
dependencies: [
|
|
177
|
+
S3Client,
|
|
178
|
+
S3Bucket,
|
|
179
|
+
S3AssetDeliveryConfig,
|
|
180
|
+
IdentityContext,
|
|
181
|
+
GetFileUseCase
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
export { SharpTransform, SharpTransformImpl };
|
|
185
|
+
|
|
186
|
+
//# sourceMappingURL=SharpTransform.js.map
|