@webiny/api-file-manager-s3 0.0.0-unstable.e6f0dc8ca7 → 0.0.0-unstable.eb81deee7e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/FileManagerS3Feature.d.ts +9 -0
  2. package/FileManagerS3Feature.js +27 -0
  3. package/FileManagerS3Feature.js.map +1 -0
  4. package/assetDelivery/abstractions.d.ts +11 -0
  5. package/assetDelivery/abstractions.js +7 -0
  6. package/assetDelivery/abstractions.js.map +1 -0
  7. package/assetDelivery/assetDeliveryConfig.d.ts +1 -1
  8. package/assetDelivery/assetDeliveryConfig.js +10 -44
  9. package/assetDelivery/assetDeliveryConfig.js.map +1 -1
  10. package/assetDelivery/createAssetDelivery.js +5 -19
  11. package/assetDelivery/createAssetDelivery.js.map +1 -1
  12. package/assetDelivery/feature.d.ts +5 -0
  13. package/assetDelivery/feature.js +36 -0
  14. package/assetDelivery/feature.js.map +1 -0
  15. package/assetDelivery/index.js +0 -2
  16. package/assetDelivery/s3/LazySharpTransform.d.ts +34 -0
  17. package/assetDelivery/s3/LazySharpTransform.js +34 -0
  18. package/assetDelivery/s3/LazySharpTransform.js.map +1 -0
  19. package/assetDelivery/s3/S3AssetResolver.d.ts +3 -0
  20. package/assetDelivery/s3/S3AssetResolver.js +32 -22
  21. package/assetDelivery/s3/S3AssetResolver.js.map +1 -1
  22. package/assetDelivery/s3/S3ContentsReader.js +13 -16
  23. package/assetDelivery/s3/S3ContentsReader.js.map +1 -1
  24. package/assetDelivery/s3/S3ErrorAssetReply.js +10 -9
  25. package/assetDelivery/s3/S3ErrorAssetReply.js.map +1 -1
  26. package/assetDelivery/s3/S3OutputStrategy.d.ts +5 -5
  27. package/assetDelivery/s3/S3OutputStrategy.js +33 -27
  28. package/assetDelivery/s3/S3OutputStrategy.js.map +1 -1
  29. package/assetDelivery/s3/S3RedirectAssetReply.js +12 -11
  30. package/assetDelivery/s3/S3RedirectAssetReply.js.map +1 -1
  31. package/assetDelivery/s3/S3StreamAssetReply.js +12 -11
  32. package/assetDelivery/s3/S3StreamAssetReply.js.map +1 -1
  33. package/assetDelivery/s3/SharpTransform.d.ts +21 -13
  34. package/assetDelivery/s3/SharpTransform.js +164 -173
  35. package/assetDelivery/s3/SharpTransform.js.map +1 -1
  36. package/assetDelivery/s3/transformation/AssetKeyGenerator.js +18 -17
  37. package/assetDelivery/s3/transformation/AssetKeyGenerator.js.map +1 -1
  38. package/assetDelivery/s3/transformation/CallableContentsReader.js +8 -7
  39. package/assetDelivery/s3/transformation/CallableContentsReader.js.map +1 -1
  40. package/assetDelivery/s3/transformation/WidthCollection.js +15 -16
  41. package/assetDelivery/s3/transformation/WidthCollection.js.map +1 -1
  42. package/assetDelivery/s3/transformation/utils.js +24 -30
  43. package/assetDelivery/s3/transformation/utils.js.map +1 -1
  44. package/assetDelivery/threatDetection/ObjectKey.js +15 -14
  45. package/assetDelivery/threatDetection/ObjectKey.js.map +1 -1
  46. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.d.ts +21 -1
  47. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js +46 -44
  48. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js.map +1 -1
  49. package/assetDelivery/threatDetection/createThreatDetectionPluginLoader.js +2 -3
  50. package/assetDelivery/threatDetection/createThreatDetectionPluginLoader.js.map +1 -1
  51. package/assetDelivery/threatDetection/index.js +0 -2
  52. package/assetDelivery/threatDetection/processThreatScanResult.js +51 -55
  53. package/assetDelivery/threatDetection/processThreatScanResult.js.map +1 -1
  54. package/assetDelivery/threatDetection/types.js +0 -3
  55. package/assetDelivery/types.d.ts +3 -0
  56. package/assetDelivery/types.js +0 -3
  57. package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.d.ts +3 -1
  58. package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.js +22 -13
  59. package/enterprise/ApplyThreatScanning/CreateFileWithThreatScanDecorator.js.map +1 -1
  60. package/enterprise/ApplyThreatScanning/feature.js +6 -5
  61. package/enterprise/ApplyThreatScanning/feature.js.map +1 -1
  62. package/features/DeleteFileFromBucket/DeleteFileFromBucketHandler.js +26 -27
  63. package/features/DeleteFileFromBucket/DeleteFileFromBucketHandler.js.map +1 -1
  64. package/features/DeleteFileFromBucket/DeleteS3FolderTask.d.ts +9 -4
  65. package/features/DeleteFileFromBucket/DeleteS3FolderTask.js +49 -53
  66. package/features/DeleteFileFromBucket/DeleteS3FolderTask.js.map +1 -1
  67. package/features/DeleteFileFromBucket/feature.js +7 -6
  68. package/features/DeleteFileFromBucket/feature.js.map +1 -1
  69. package/features/ExtractMetadata/ExtractMetadataHandler.js +18 -19
  70. package/features/ExtractMetadata/ExtractMetadataHandler.js.map +1 -1
  71. package/features/ExtractMetadata/ExtractMetadataTask.d.ts +11 -6
  72. package/features/ExtractMetadata/ExtractMetadataTask.js +86 -116
  73. package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
  74. package/features/ExtractMetadata/feature.js +7 -6
  75. package/features/ExtractMetadata/feature.js.map +1 -1
  76. package/features/FlushCache/FlushCacheOnFileDeleteHandler.js +20 -19
  77. package/features/FlushCache/FlushCacheOnFileDeleteHandler.js.map +1 -1
  78. package/features/FlushCache/FlushCacheOnFileUpdateHandler.js +22 -26
  79. package/features/FlushCache/FlushCacheOnFileUpdateHandler.js.map +1 -1
  80. package/features/FlushCache/InvalidateCacheTask.d.ts +11 -6
  81. package/features/FlushCache/InvalidateCacheTask.js +75 -78
  82. package/features/FlushCache/InvalidateCacheTask.js.map +1 -1
  83. package/features/FlushCache/feature.js +8 -7
  84. package/features/FlushCache/feature.js.map +1 -1
  85. package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +13 -0
  86. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +40 -0
  87. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -0
  88. package/features/{GetFileContents → GetFileContentsById}/feature.d.ts +1 -1
  89. package/features/GetFileContentsById/feature.js +11 -0
  90. package/features/GetFileContentsById/feature.js.map +1 -0
  91. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +13 -0
  92. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +40 -0
  93. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -0
  94. package/features/GetFileContentsByKey/feature.d.ts +4 -0
  95. package/features/GetFileContentsByKey/feature.js +11 -0
  96. package/features/GetFileContentsByKey/feature.js.map +1 -0
  97. package/features/WriteFileMetadata/MetadataReader.js +9 -10
  98. package/features/WriteFileMetadata/MetadataReader.js.map +1 -1
  99. package/features/WriteFileMetadata/MetadataWriter.js +25 -25
  100. package/features/WriteFileMetadata/MetadataWriter.js.map +1 -1
  101. package/features/WriteFileMetadata/WriteMetadataAfterBatchCreateHandler.js +14 -12
  102. package/features/WriteFileMetadata/WriteMetadataAfterBatchCreateHandler.js.map +1 -1
  103. package/features/WriteFileMetadata/WriteMetadataAfterCreateHandler.js +16 -12
  104. package/features/WriteFileMetadata/WriteMetadataAfterCreateHandler.js.map +1 -1
  105. package/features/WriteFileMetadata/feature.js +7 -6
  106. package/features/WriteFileMetadata/feature.js.map +1 -1
  107. package/graphql/S3GraphQLSchema.d.ts +10 -0
  108. package/graphql/S3GraphQLSchema.js +233 -0
  109. package/graphql/S3GraphQLSchema.js.map +1 -0
  110. package/graphql/checkPermissions.js +17 -32
  111. package/graphql/checkPermissions.js.map +1 -1
  112. package/index.d.ts +2 -2
  113. package/index.js +1 -25
  114. package/multiPartUpload/CompleteMultiPartUploadUseCase.js +50 -53
  115. package/multiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -1
  116. package/multiPartUpload/CreateMultiPartUploadUseCase.js +31 -38
  117. package/multiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -1
  118. package/package.json +27 -23
  119. package/types.d.ts +1 -1
  120. package/types.js +1 -3
  121. package/utils/CdnPathsGenerator.js +8 -4
  122. package/utils/CdnPathsGenerator.js.map +1 -1
  123. package/utils/FileExtension.js +12 -13
  124. package/utils/FileExtension.js.map +1 -1
  125. package/utils/FileKey.js +29 -21
  126. package/utils/FileKey.js.map +1 -1
  127. package/utils/FileKey.test.js +49 -49
  128. package/utils/FileKey.test.js.map +1 -1
  129. package/utils/FileNormalizer.js +31 -46
  130. package/utils/FileNormalizer.js.map +1 -1
  131. package/utils/FileUploadModifier.d.ts +8 -2
  132. package/utils/FileUploadModifier.js +35 -33
  133. package/utils/FileUploadModifier.js.map +1 -1
  134. package/utils/createFileNormalizerFromContext.js +5 -4
  135. package/utils/createFileNormalizerFromContext.js.map +1 -1
  136. package/utils/getPresignedPostPayload.js +36 -33
  137. package/utils/getPresignedPostPayload.js.map +1 -1
  138. package/utils/mimeTypes.js +6 -10
  139. package/utils/mimeTypes.js.map +1 -1
  140. package/utils/uploadFileToS3.d.ts +1 -1
  141. package/utils/uploadFileToS3.js +11 -10
  142. package/utils/uploadFileToS3.js.map +1 -1
  143. package/assetDelivery/index.js.map +0 -1
  144. package/assetDelivery/threatDetection/index.js.map +0 -1
  145. package/assetDelivery/threatDetection/types.js.map +0 -1
  146. package/assetDelivery/types.js.map +0 -1
  147. package/features/GetFileContents/GetFileContentsUseCase.d.ts +0 -13
  148. package/features/GetFileContents/GetFileContentsUseCase.js +0 -41
  149. package/features/GetFileContents/GetFileContentsUseCase.js.map +0 -1
  150. package/features/GetFileContents/feature.js +0 -10
  151. package/features/GetFileContents/feature.js.map +0 -1
  152. package/graphql/schema.d.ts +0 -1
  153. package/graphql/schema.js +0 -204
  154. package/graphql/schema.js.map +0 -1
  155. package/index.js.map +0 -1
  156. package/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"names":["GetObjectCommand","getSignedUrl","S3RedirectAssetReply","S3StreamAssetReply","S3OutputStrategy","constructor","s3","bucket","presignedUrlTtl","assetStreamingMaxSize","output","asset","getSize","console","log","getPresignedUrl","Bucket","Key","getKey","expiresIn"],"sources":["S3OutputStrategy.ts"],"sourcesContent":["import type { Asset, AssetOutputStrategy, AssetReply } from \"@webiny/api-file-manager\";\nimport type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { GetObjectCommand, getSignedUrl } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { S3RedirectAssetReply } from \"~/assetDelivery/s3/S3RedirectAssetReply.js\";\nimport { S3StreamAssetReply } from \"~/assetDelivery/s3/S3StreamAssetReply.js\";\n\n/**\n * This strategy outputs an asset taking into account the size of the asset contents.\n * If the asset is larger than 5MB, a presigned URL will be generated, and a redirect will happen.\n */\nexport class S3OutputStrategy implements AssetOutputStrategy {\n private readonly s3: S3;\n private readonly bucket: string;\n private readonly presignedUrlTtl: number;\n private readonly assetStreamingMaxSize: number;\n\n constructor(s3: S3, bucket: string, presignedUrlTtl: number, assetStreamingMaxSize: number) {\n this.assetStreamingMaxSize = assetStreamingMaxSize;\n this.presignedUrlTtl = presignedUrlTtl;\n this.s3 = s3;\n this.bucket = bucket;\n }\n\n async output(asset: Asset): Promise<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 new S3StreamAssetReply(asset);\n }\n\n protected getPresignedUrl(asset: 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"],"mappings":"AAEA,SAASA,gBAAgB,EAAEC,YAAY,QAAQ,oCAAoC;AACnF,SAASC,oBAAoB;AAC7B,SAASC,kBAAkB;;AAE3B;AACA;AACA;AACA;AACA,OAAO,MAAMC,gBAAgB,CAAgC;EAMzDC,WAAWA,CAACC,EAAM,EAAEC,MAAc,EAAEC,eAAuB,EAAEC,qBAA6B,EAAE;IACxF,IAAI,CAACA,qBAAqB,GAAGA,qBAAqB;IAClD,IAAI,CAACD,eAAe,GAAGA,eAAe;IACtC,IAAI,CAACF,EAAE,GAAGA,EAAE;IACZ,IAAI,CAACC,MAAM,GAAGA,MAAM;EACxB;EAEA,MAAMG,MAAMA,CAACC,KAAY,EAAuB;IAC5C,IAAIA,KAAK,CAACC,OAAO,CAAC,CAAC,GAAG,IAAI,CAACH,qBAAqB,EAAE;MAC9CI,OAAO,CAACC,GAAG,CACP,8BAA8B,IAAI,CAACL,qBAAqB,sCAC5D,CAAC;MAED,OAAO,IAAIP,oBAAoB,CAC3B,MAAM,IAAI,CAACa,eAAe,CAACJ,KAAK,CAAC,EACjC,IAAI,CAACH,eACT,CAAC;IACL;IAEAK,OAAO,CAACC,GAAG,CACP,8BAA8B,IAAI,CAACL,qBAAqB,4CAC5D,CAAC;IACD,OAAO,IAAIN,kBAAkB,CAACQ,KAAK,CAAC;EACxC;EAEUI,eAAeA,CAACJ,KAAY,EAAE;IACpC,OAAOV,YAAY,CACf,IAAI,CAACK,EAAE,EACP,IAAIN,gBAAgB,CAAC;MACjBgB,MAAM,EAAE,IAAI,CAACT,MAAM;MACnBU,GAAG,EAAEN,KAAK,CAACO,MAAM,CAAC;IACtB,CAAC,CAAC,EACF;MAAEC,SAAS,EAAE,IAAI,CAACX;IAAgB,CACtC,CAAC;EACL;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"assetDelivery/s3/S3OutputStrategy.js","sources":["../../../src/assetDelivery/s3/S3OutputStrategy.ts"],"sourcesContent":["import type { Asset, AssetOutputStrategy, AssetReply } from \"@webiny/api-file-manager\";\nimport { AssetOutputStrategy as AssetOutputStrategyAbstraction } from \"@webiny/api-file-manager/features/assetDelivery/abstractions.js\";\nimport type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { GetObjectCommand, getSignedUrl } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { S3RedirectAssetReply } from \"~/assetDelivery/s3/S3RedirectAssetReply.js\";\nimport { S3StreamAssetReply } from \"~/assetDelivery/s3/S3StreamAssetReply.js\";\nimport { S3Client, S3Bucket, S3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { IS3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\nexport class S3OutputStrategy implements AssetOutputStrategy {\n private readonly s3: S3;\n private readonly bucket: string;\n private readonly presignedUrlTtl: number;\n private readonly assetStreamingMaxSize: number;\n\n constructor(s3: S3, bucket: string, config: IS3AssetDeliveryConfig) {\n this.s3 = s3;\n this.bucket = bucket;\n this.presignedUrlTtl = config.presignedUrlTtl;\n this.assetStreamingMaxSize = config.assetStreamingMaxSize;\n }\n\n async output(asset: Asset): Promise<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 new S3StreamAssetReply(asset);\n }\n\n protected getPresignedUrl(asset: 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]\n});\n"],"names":["S3OutputStrategy","s3","bucket","config","asset","console","S3RedirectAssetReply","S3StreamAssetReply","getSignedUrl","GetObjectCommand","S3OutputStrategyImpl","AssetOutputStrategyAbstraction","S3Client","S3Bucket","S3AssetDeliveryConfig"],"mappings":";;;;;AASO,MAAMA;IAMT,YAAYC,EAAM,EAAEC,MAAc,EAAEC,MAA8B,CAAE;QAChE,IAAI,CAAC,EAAE,GAAGF;QACV,IAAI,CAAC,MAAM,GAAGC;QACd,IAAI,CAAC,eAAe,GAAGC,OAAO,eAAe;QAC7C,IAAI,CAAC,qBAAqB,GAAGA,OAAO,qBAAqB;IAC7D;IAEA,MAAM,OAAOC,KAAY,EAAuB;QAC5C,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,IAAIE,mBAAmBH;IAClC;IAEU,gBAAgBA,KAAY,EAAE;QACpC,OAAOI,aACH,IAAI,CAAC,EAAE,EACP,IAAIC,iBAAiB;YACjB,QAAQ,IAAI,CAAC,MAAM;YACnB,KAAKL,MAAM,MAAM;QACrB,IACA;YAAE,WAAW,IAAI,CAAC,eAAe;QAAC;IAE1C;AACJ;AAEO,MAAMM,uBAAuBC,oBAAAA,oBAAmD,CAAC;IACpF,gBAAgBX;IAChB,cAAc;QAACY;QAAUC;QAAUC;KAAsB;AAC7D"}
@@ -1,16 +1,17 @@
1
1
  import { AssetReply } from "@webiny/api-file-manager";
2
2
  import { ResponseHeaders } from "@webiny/handler";
3
- export 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
- }
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
14
  }
15
+ export { S3RedirectAssetReply };
15
16
 
16
17
  //# sourceMappingURL=S3RedirectAssetReply.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["AssetReply","ResponseHeaders","S3RedirectAssetReply","constructor","url","cacheDuration","code","headers","create","location","body"],"sources":["S3RedirectAssetReply.ts"],"sourcesContent":["import { AssetReply } from \"@webiny/api-file-manager\";\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"],"mappings":"AAAA,SAASA,UAAU,QAAQ,0BAA0B;AACrD,SAASC,eAAe,QAAQ,iBAAiB;AAEjD,OAAO,MAAMC,oBAAoB,SAASF,UAAU,CAAC;EACjDG,WAAWA,CAACC,GAAW,EAAEC,aAAqB,EAAE;IAC5C,KAAK,CAAC;MACFC,IAAI,EAAE,GAAG;MACTC,OAAO,EAAEN,eAAe,CAACO,MAAM,CAAC;QAC5BC,QAAQ,EAAEL,GAAG;QACb,eAAe,EAAE,kBAAkB,GAAGC;MAC1C,CAAC,CAAC;MACFK,IAAI,EAAEA,CAAA,KAAM;IAChB,CAAC,CAAC;EACN;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"assetDelivery/s3/S3RedirectAssetReply.js","sources":["../../../src/assetDelivery/s3/S3RedirectAssetReply.ts"],"sourcesContent":["import { AssetReply } from \"@webiny/api-file-manager\";\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"}
@@ -1,16 +1,17 @@
1
1
  import { AssetReply } from "@webiny/api-file-manager";
2
2
  import { ResponseHeaders } from "@webiny/handler";
3
- export class S3StreamAssetReply extends AssetReply {
4
- constructor(asset) {
5
- super({
6
- code: 200,
7
- headers: ResponseHeaders.create({
8
- "cache-control": `public, max-age=${86400 * 365}`,
9
- "content-type": asset.getContentType()
10
- }),
11
- body: () => asset.getContents()
12
- });
13
- }
3
+ class S3StreamAssetReply extends AssetReply {
4
+ constructor(asset){
5
+ super({
6
+ code: 200,
7
+ headers: ResponseHeaders.create({
8
+ "cache-control": "public, max-age=31536000",
9
+ "content-type": asset.getContentType()
10
+ }),
11
+ body: ()=>asset.getContents()
12
+ });
13
+ }
14
14
  }
15
+ export { S3StreamAssetReply };
15
16
 
16
17
  //# sourceMappingURL=S3StreamAssetReply.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["AssetReply","ResponseHeaders","S3StreamAssetReply","constructor","asset","code","headers","create","getContentType","body","getContents"],"sources":["S3StreamAssetReply.ts"],"sourcesContent":["import type { Asset } from \"@webiny/api-file-manager\";\nimport { AssetReply } from \"@webiny/api-file-manager\";\nimport { ResponseHeaders } from \"@webiny/handler\";\n\nexport class S3StreamAssetReply extends AssetReply {\n constructor(asset: Asset) {\n super({\n code: 200,\n headers: ResponseHeaders.create({\n \"cache-control\": `public, max-age=${86400 * 365}`,\n \"content-type\": asset.getContentType()\n }),\n body: () => asset.getContents()\n });\n }\n}\n"],"mappings":"AACA,SAASA,UAAU,QAAQ,0BAA0B;AACrD,SAASC,eAAe,QAAQ,iBAAiB;AAEjD,OAAO,MAAMC,kBAAkB,SAASF,UAAU,CAAC;EAC/CG,WAAWA,CAACC,KAAY,EAAE;IACtB,KAAK,CAAC;MACFC,IAAI,EAAE,GAAG;MACTC,OAAO,EAAEL,eAAe,CAACM,MAAM,CAAC;QAC5B,eAAe,EAAE,mBAAmB,KAAK,GAAG,GAAG,EAAE;QACjD,cAAc,EAAEH,KAAK,CAACI,cAAc,CAAC;MACzC,CAAC,CAAC;MACFC,IAAI,EAAEA,CAAA,KAAML,KAAK,CAACM,WAAW,CAAC;IAClC,CAAC,CAAC;EACN;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"assetDelivery/s3/S3StreamAssetReply.js","sources":["../../../src/assetDelivery/s3/S3StreamAssetReply.ts"],"sourcesContent":["import type { Asset } from \"@webiny/api-file-manager\";\nimport { AssetReply } from \"@webiny/api-file-manager\";\nimport { ResponseHeaders } from \"@webiny/handler\";\n\nexport class S3StreamAssetReply extends AssetReply {\n constructor(asset: Asset) {\n super({\n code: 200,\n headers: ResponseHeaders.create({\n \"cache-control\": `public, max-age=${86400 * 365}`,\n \"content-type\": asset.getContentType()\n }),\n body: () => asset.getContents()\n });\n }\n}\n"],"names":["S3StreamAssetReply","AssetReply","asset","ResponseHeaders"],"mappings":";;AAIO,MAAMA,2BAA2BC;IACpC,YAAYC,KAAY,CAAE;QACtB,KAAK,CAAC;YACF,MAAM;YACN,SAASC,gBAAgB,MAAM,CAAC;gBAC5B,iBAAiB;gBACjB,gBAAgBD,MAAM,cAAc;YACxC;YACA,MAAM,IAAMA,MAAM,WAAW;QACjC;IACJ;AACJ"}
@@ -1,18 +1,26 @@
1
1
  import type { S3 } from "@webiny/aws-sdk/client-s3/index.js";
2
- import type { Asset, AssetRequest, AssetTransformationStrategy } from "@webiny/api-file-manager";
3
- interface SharpTransformationParams {
4
- s3: S3;
5
- bucket: string;
6
- imageResizeWidths: number[];
7
- }
8
- export declare class SharpTransform implements AssetTransformationStrategy {
9
- private readonly params;
10
- constructor(params: SharpTransformationParams);
11
- transform(assetRequest: AssetRequest, asset: Asset): Promise<Asset>;
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
+ private transformer?;
16
+ constructor(s3: S3, bucket: string, config: IS3AssetDeliveryConfig, identityContext: IdentityContext.Interface, getFile: GetFileUseCase.Interface);
17
+ private getTransformer;
18
+ handle(assetRequest: AssetRequest, asset: Asset): Promise<Asset>;
19
+ private loadAssetCrop;
12
20
  private transformAsset;
13
21
  private optimizeAsset;
14
22
  private isAssetAnimated;
15
- private optimizePng;
16
- private optimizeJpeg;
17
23
  }
18
- export {};
24
+ export declare const SharpTransformImpl: typeof SharpTransform & {
25
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/assetDelivery/abstractions/AssetType").IAssetTypeHandler>;
26
+ };
@@ -1,182 +1,173 @@
1
- import sharp from "sharp";
2
- import { WidthCollection } from "./transformation/WidthCollection.js";
3
- import * as utils from "./transformation/utils.js";
4
- import { CallableContentsReader } from "./transformation/CallableContentsReader.js";
5
- import { AssetKeyGenerator } from "./transformation/AssetKeyGenerator.js";
6
- export class SharpTransform {
7
- constructor(params) {
8
- this.params = params;
9
- }
10
- async transform(assetRequest, asset) {
11
- if (!utils.SUPPORTED_TRANSFORMABLE_IMAGES.includes(asset.getExtension())) {
12
- console.log(`Transformations/optimizations of ${asset.getContentType()} assets are not supported. Skipping.`);
13
- return asset;
1
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
2
+ import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
3
+ import { CallableContentsReader, DEFAULT_IMAGE_QUALITY, contentTypeForFormat } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
4
+ import { normalizeImageOptions } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/normalizeImageOptions.js";
5
+ import { AssetKeyGenerator, ImageAssetTypeHandler } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js";
6
+ import { S3AssetDeliveryConfig, S3Bucket, S3Client } from "../abstractions.js";
7
+ const hasTransform = (options)=>void 0 !== options.width || void 0 !== options.format || void 0 !== options.quality;
8
+ class SharpTransform {
9
+ constructor(s3, bucket, config, identityContext, getFile){
10
+ this.s3 = s3;
11
+ this.bucket = bucket;
12
+ this.imageResizeWidths = config.imageResizeWidths;
13
+ this.imageQuality = {
14
+ ...DEFAULT_IMAGE_QUALITY,
15
+ ...config.imageQuality ?? {}
16
+ };
17
+ this.identityContext = identityContext;
18
+ this.getFile = getFile;
14
19
  }
15
-
16
- // `original` is part of the request, but it won't even get to this point in the execution.
17
- // oxlint-disable-next-line typescript/no-unused-vars
18
- const {
19
- original,
20
- ...options
21
- } = assetRequest.getOptions();
22
- const transformedAsset = asset.clone();
23
- if (Object.keys(options).length > 0) {
24
- // Transformations were requested.
25
- return this.transformAsset(transformedAsset, options);
20
+ async getTransformer() {
21
+ if (!this.transformer) {
22
+ const { SharpTransformer } = await import("@webiny/api-file-manager/features/assetDelivery/assetTypes/image/SharpTransformer.js");
23
+ this.transformer = new SharpTransformer();
24
+ }
25
+ return this.transformer;
26
26
  }
27
-
28
- // Return an optimized asset.
29
- return this.optimizeAsset(transformedAsset);
30
- }
31
- async transformAsset(asset, options) {
32
- if (options.width) {
33
- const {
34
- s3,
35
- bucket
36
- } = this.params;
37
- const assetKey = new AssetKeyGenerator(asset);
38
- const transformedAssetKey = assetKey.getTransformedImageKey(options);
39
- try {
40
- const {
41
- Body
42
- } = await s3.getObject({
43
- Bucket: bucket,
44
- Key: transformedAssetKey
45
- });
46
- if (!Body) {
47
- throw new Error(`Missing image body!`);
27
+ async handle(assetRequest, asset) {
28
+ const rawQuery = assetRequest.getOptions();
29
+ const acceptHeader = assetRequest.getContext().accept;
30
+ const { original, crop, focal, aspectRatio, ...options } = normalizeImageOptions(rawQuery, acceptHeader);
31
+ const assetCrop = await this.loadAssetCrop(asset.getId());
32
+ const framing = {
33
+ crop: crop ?? assetCrop,
34
+ focal,
35
+ aspectRatio
36
+ };
37
+ const transformedAsset = asset.clone();
38
+ if (hasTransform(options)) return this.transformAsset(transformedAsset, options, framing);
39
+ return this.optimizeAsset(transformedAsset, framing);
40
+ }
41
+ async loadAssetCrop(fileId) {
42
+ const result = await this.identityContext.withoutAuthorization(()=>this.getFile.execute(fileId));
43
+ if (result.isFail()) return;
44
+ const imageEdit = result.value.metadata?.image;
45
+ return imageEdit?.crop;
46
+ }
47
+ async transformAsset(asset, options, framing) {
48
+ const assetKey = AssetKeyGenerator.create(asset, framing);
49
+ const transformedAssetKey = assetKey.getTransformedImageKey(options);
50
+ const contentType = options.format ? contentTypeForFormat(options.format) : asset.getContentType();
51
+ try {
52
+ const { Body } = await this.s3.getObject({
53
+ Bucket: this.bucket,
54
+ Key: transformedAssetKey
55
+ });
56
+ if (!Body) throw new Error("Missing image body!");
57
+ const buffer = Buffer.from(await Body.transformToByteArray());
58
+ const newAsset = asset.withProps({
59
+ size: buffer.length,
60
+ contentType
61
+ });
62
+ newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
63
+ console.log("Return a previously transformed asset", {
64
+ key: transformedAssetKey,
65
+ size: newAsset.getSize()
66
+ });
67
+ return newAsset;
68
+ } catch {
69
+ const optimizedImage = await this.optimizeAsset(asset, framing);
70
+ console.log("Transform the asset", options);
71
+ const baseBuffer = await optimizedImage.getContents();
72
+ const transformer = await this.getTransformer();
73
+ const { buffer: transformedBuffer, contentType: outputContentType } = await transformer.transformBuffer({
74
+ buffer: baseBuffer,
75
+ animated: this.isAssetAnimated(asset),
76
+ sourceContentType: asset.getContentType(),
77
+ widths: this.imageResizeWidths,
78
+ options,
79
+ qualityDefaults: this.imageQuality
80
+ });
81
+ const newAsset = asset.withProps({
82
+ size: transformedBuffer.length,
83
+ contentType: outputContentType
84
+ });
85
+ newAsset.setContentsReader(CallableContentsReader.create(()=>transformedBuffer));
86
+ await this.s3.putObject({
87
+ Bucket: this.bucket,
88
+ Key: transformedAssetKey,
89
+ ContentType: newAsset.getContentType(),
90
+ Body: await newAsset.getContents()
91
+ });
92
+ console.log("Return the transformed asset", {
93
+ key: transformedAssetKey,
94
+ size: newAsset.getSize(),
95
+ contentType: newAsset.getContentType()
96
+ });
97
+ return newAsset;
48
98
  }
49
- const buffer = Buffer.from(await Body.transformToByteArray());
50
- const newAsset = asset.withProps({
51
- size: buffer.length
52
- });
53
- newAsset.setContentsReader(new CallableContentsReader(() => buffer));
54
- console.log(`Return a previously transformed asset`, {
55
- key: transformedAssetKey,
56
- size: newAsset.getSize()
57
- });
58
- return newAsset;
59
- } catch {
60
- const optimizedImage = await this.optimizeAsset(asset);
61
- const widths = new WidthCollection(this.params.imageResizeWidths);
62
- const width = widths.getClosestOrMax(options.width);
63
-
64
- /**
65
- * `width` is the only transformation we currently support.
66
- */
67
- console.log(`Resize the asset (width: ${width})`);
68
- const buffer = await optimizedImage.getContents();
69
- const transformedBuffer = await sharp(buffer, {
70
- animated: this.isAssetAnimated(asset)
71
- }).withMetadata().resize({
72
- width,
73
- withoutEnlargement: true
74
- }).toBuffer();
75
-
76
- /**
77
- * Transformations are applied to the optimized image.
78
- */
79
- const newAsset = asset.withProps({
80
- size: transformedBuffer.length
81
- });
82
- newAsset.setContentsReader(new CallableContentsReader(() => transformedBuffer));
83
- await s3.putObject({
84
- Bucket: bucket,
85
- Key: transformedAssetKey,
86
- ContentType: newAsset.getContentType(),
87
- Body: await newAsset.getContents()
88
- });
89
- console.log(`Return the resized asset`, {
90
- key: transformedAssetKey,
91
- size: newAsset.getSize()
99
+ }
100
+ async optimizeAsset(asset, framing) {
101
+ console.log("Optimize asset", {
102
+ id: asset.getId(),
103
+ key: asset.getKey(),
104
+ size: asset.getSize(),
105
+ type: asset.getContentType()
92
106
  });
93
- return newAsset;
94
- }
107
+ const assetKey = AssetKeyGenerator.create(asset, framing);
108
+ const optimizedAssetKey = assetKey.getOptimizedImageKey();
109
+ try {
110
+ const { Body } = await this.s3.getObject({
111
+ Bucket: this.bucket,
112
+ Key: optimizedAssetKey
113
+ });
114
+ if (!Body) throw new Error("Missing image body!");
115
+ console.log("Return a previously optimized asset", optimizedAssetKey);
116
+ const buffer = Buffer.from(await Body.transformToByteArray());
117
+ const newAsset = asset.withProps({
118
+ size: buffer.length
119
+ });
120
+ newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
121
+ return newAsset;
122
+ } catch {
123
+ console.log("Create an optimized version of the original asset", asset.getKey());
124
+ let buffer = await asset.getContents();
125
+ const transformer = await this.getTransformer();
126
+ const framed = await transformer.extractFramedRegion(buffer, framing);
127
+ const cropped = framed !== buffer;
128
+ buffer = framed;
129
+ const contentType = asset.getContentType();
130
+ const canOptimize = "image/png" === contentType || "image/jpeg" === contentType || "image/jpg" === contentType;
131
+ if (!canOptimize && !cropped) {
132
+ console.log(`No optimizations defined for ${contentType}`);
133
+ return asset;
134
+ }
135
+ let finalBuffer = buffer;
136
+ if (canOptimize) {
137
+ const pipeline = "image/png" === contentType ? await transformer.optimizePng(buffer) : await transformer.optimizeJpeg(buffer);
138
+ finalBuffer = await pipeline.toBuffer();
139
+ }
140
+ console.log("Optimized asset size", finalBuffer.length);
141
+ const newAsset = asset.withProps({
142
+ size: finalBuffer.length
143
+ });
144
+ newAsset.setContentsReader(CallableContentsReader.create(()=>finalBuffer));
145
+ await this.s3.putObject({
146
+ Bucket: this.bucket,
147
+ Key: optimizedAssetKey,
148
+ ContentType: newAsset.getContentType(),
149
+ Body: await newAsset.getContents()
150
+ });
151
+ return newAsset;
152
+ }
95
153
  }
96
- return asset;
97
- }
98
- async optimizeAsset(asset) {
99
- const {
100
- s3,
101
- bucket
102
- } = this.params;
103
- console.log("Optimize asset", {
104
- id: asset.getId(),
105
- key: asset.getKey(),
106
- size: asset.getSize(),
107
- type: asset.getContentType()
108
- });
109
- const assetKey = new AssetKeyGenerator(asset);
110
- const optimizedAssetKey = assetKey.getOptimizedImageKey();
111
- try {
112
- const {
113
- Body
114
- } = await s3.getObject({
115
- Bucket: bucket,
116
- Key: optimizedAssetKey
117
- });
118
- if (!Body) {
119
- throw new Error(`Missing image body!`);
120
- }
121
- console.log("Return a previously optimized asset", optimizedAssetKey);
122
- const buffer = Buffer.from(await Body.transformToByteArray());
123
- const newAsset = asset.withProps({
124
- size: buffer.length
125
- });
126
- newAsset.setContentsReader(new CallableContentsReader(() => buffer));
127
- return newAsset;
128
- } catch {
129
- console.log("Create an optimized version of the original asset", asset.getKey());
130
- // If not found, create an optimized version of the original asset.
131
- const buffer = await asset.getContents();
132
- const optimizationMap = {
133
- "image/png": buffer => this.optimizePng(buffer),
134
- "image/jpeg": buffer => this.optimizeJpeg(buffer),
135
- "image/jpg": buffer => this.optimizeJpeg(buffer)
136
- };
137
- const optimization = optimizationMap[asset.getContentType()];
138
- if (!optimization) {
139
- console.log(`No optimizations defined for ${asset.getContentType()}`);
140
- return asset;
141
- }
142
- const optimizedBuffer = await optimization(buffer).toBuffer();
143
- console.log("Optimized asset size", optimizedBuffer.length);
144
- const newAsset = asset.withProps({
145
- size: optimizedBuffer.length
146
- });
147
- newAsset.setContentsReader(new CallableContentsReader(() => optimizedBuffer));
148
- await s3.putObject({
149
- Bucket: bucket,
150
- Key: optimizedAssetKey,
151
- ContentType: newAsset.getContentType(),
152
- Body: await newAsset.getContents()
153
- });
154
- return newAsset;
154
+ isAssetAnimated(asset) {
155
+ return [
156
+ "gif",
157
+ "webp"
158
+ ].includes(asset.getExtension());
155
159
  }
156
- }
157
- isAssetAnimated(asset) {
158
- return ["gif", "webp"].includes(asset.getExtension());
159
- }
160
- optimizePng(buffer) {
161
- return sharp(buffer).resize({
162
- width: 2560,
163
- withoutEnlargement: true,
164
- fit: "inside"
165
- }).png({
166
- compressionLevel: 9,
167
- adaptiveFiltering: true,
168
- force: true
169
- }).withMetadata();
170
- }
171
- optimizeJpeg(buffer) {
172
- return sharp(buffer).resize({
173
- width: 2560,
174
- withoutEnlargement: true,
175
- fit: "inside"
176
- }).withMetadata().toFormat("jpeg", {
177
- quality: 90
178
- });
179
- }
180
160
  }
161
+ const SharpTransformImpl = ImageAssetTypeHandler.createImplementation({
162
+ implementation: SharpTransform,
163
+ dependencies: [
164
+ S3Client,
165
+ S3Bucket,
166
+ S3AssetDeliveryConfig,
167
+ IdentityContext,
168
+ GetFileUseCase
169
+ ]
170
+ });
171
+ export { SharpTransform, SharpTransformImpl };
181
172
 
182
173
  //# sourceMappingURL=SharpTransform.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["sharp","WidthCollection","utils","CallableContentsReader","AssetKeyGenerator","SharpTransform","constructor","params","transform","assetRequest","asset","SUPPORTED_TRANSFORMABLE_IMAGES","includes","getExtension","console","log","getContentType","original","options","getOptions","transformedAsset","clone","Object","keys","length","transformAsset","optimizeAsset","width","s3","bucket","assetKey","transformedAssetKey","getTransformedImageKey","Body","getObject","Bucket","Key","Error","buffer","Buffer","from","transformToByteArray","newAsset","withProps","size","setContentsReader","key","getSize","optimizedImage","widths","imageResizeWidths","getClosestOrMax","getContents","transformedBuffer","animated","isAssetAnimated","withMetadata","resize","withoutEnlargement","toBuffer","putObject","ContentType","id","getId","getKey","type","optimizedAssetKey","getOptimizedImageKey","optimizationMap","optimizePng","optimizeJpeg","optimization","optimizedBuffer","fit","png","compressionLevel","adaptiveFiltering","force","toFormat","quality"],"sources":["SharpTransform.ts"],"sourcesContent":["import sharp from \"sharp\";\nimport type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport type {\n Asset,\n AssetRequest,\n AssetRequestOptions,\n AssetTransformationStrategy\n} from \"@webiny/api-file-manager\";\nimport { WidthCollection } from \"./transformation/WidthCollection.js\";\nimport * as utils from \"./transformation/utils.js\";\nimport { CallableContentsReader } from \"./transformation/CallableContentsReader.js\";\nimport { AssetKeyGenerator } from \"./transformation/AssetKeyGenerator.js\";\n\ninterface SharpTransformationParams {\n s3: S3;\n bucket: string;\n imageResizeWidths: number[];\n}\n\nexport class SharpTransform implements AssetTransformationStrategy {\n private readonly params: SharpTransformationParams;\n\n constructor(params: SharpTransformationParams) {\n this.params = params;\n }\n\n async transform(assetRequest: AssetRequest, asset: Asset): Promise<Asset> {\n if (!utils.SUPPORTED_TRANSFORMABLE_IMAGES.includes(asset.getExtension())) {\n console.log(\n `Transformations/optimizations of ${asset.getContentType()} assets are not supported. Skipping.`\n );\n return asset;\n }\n\n // `original` is part of the request, but it won't even get to this point in the execution.\n // oxlint-disable-next-line typescript/no-unused-vars\n const { original, ...options } = assetRequest.getOptions();\n\n const transformedAsset = asset.clone();\n\n if (Object.keys(options).length > 0) {\n // Transformations were requested.\n return this.transformAsset(transformedAsset, options);\n }\n\n // Return an optimized asset.\n return this.optimizeAsset(transformedAsset);\n }\n\n private async transformAsset(asset: Asset, options: Omit<AssetRequestOptions, \"original\">) {\n if (options.width) {\n const { s3, bucket } = this.params;\n\n const assetKey = new AssetKeyGenerator(asset);\n const transformedAssetKey = assetKey.getTransformedImageKey(options);\n\n try {\n const { Body } = await s3.getObject({\n Bucket: bucket,\n Key: transformedAssetKey\n });\n\n if (!Body) {\n throw new Error(`Missing image body!`);\n }\n\n const buffer = Buffer.from(await Body.transformToByteArray());\n\n const newAsset = asset.withProps({ size: buffer.length });\n newAsset.setContentsReader(new CallableContentsReader(() => buffer));\n\n console.log(`Return a previously transformed asset`, {\n key: transformedAssetKey,\n size: newAsset.getSize()\n });\n\n return newAsset;\n } catch {\n const optimizedImage = await this.optimizeAsset(asset);\n\n const widths = new WidthCollection(this.params.imageResizeWidths);\n const width = widths.getClosestOrMax(options.width);\n\n /**\n * `width` is the only transformation we currently support.\n */\n console.log(`Resize the asset (width: ${width})`);\n const buffer = await optimizedImage.getContents();\n const transformedBuffer = await sharp(buffer, {\n animated: this.isAssetAnimated(asset)\n })\n .withMetadata()\n .resize({ width, withoutEnlargement: true })\n .toBuffer();\n\n /**\n * Transformations are applied to the optimized image.\n */\n const newAsset = asset.withProps({ size: transformedBuffer.length });\n newAsset.setContentsReader(new CallableContentsReader(() => transformedBuffer));\n\n await s3.putObject({\n Bucket: bucket,\n Key: transformedAssetKey,\n ContentType: newAsset.getContentType(),\n Body: await newAsset.getContents()\n });\n\n console.log(`Return the resized asset`, {\n key: transformedAssetKey,\n size: newAsset.getSize()\n });\n\n return newAsset;\n }\n }\n\n return asset;\n }\n\n private async optimizeAsset(asset: Asset) {\n const { s3, bucket } = this.params;\n\n console.log(\"Optimize asset\", {\n id: asset.getId(),\n key: asset.getKey(),\n size: asset.getSize(),\n type: asset.getContentType()\n });\n\n const assetKey = new AssetKeyGenerator(asset);\n const optimizedAssetKey = assetKey.getOptimizedImageKey();\n\n try {\n const { Body } = await s3.getObject({\n Bucket: bucket,\n Key: optimizedAssetKey\n });\n\n if (!Body) {\n throw new Error(`Missing image body!`);\n }\n\n console.log(\"Return a previously optimized asset\", optimizedAssetKey);\n\n const buffer = Buffer.from(await Body.transformToByteArray());\n\n const newAsset = asset.withProps({ size: buffer.length });\n newAsset.setContentsReader(new CallableContentsReader(() => buffer));\n\n return newAsset;\n } catch {\n console.log(\"Create an optimized version of the original asset\", asset.getKey());\n // If not found, create an optimized version of the original asset.\n const buffer = await asset.getContents();\n\n const optimizationMap: Record<string, ((buffer: Buffer) => sharp.Sharp) | undefined> = {\n \"image/png\": (buffer: Buffer) => this.optimizePng(buffer),\n \"image/jpeg\": (buffer: Buffer) => this.optimizeJpeg(buffer),\n \"image/jpg\": (buffer: Buffer) => this.optimizeJpeg(buffer)\n };\n\n const optimization = optimizationMap[asset.getContentType()];\n\n if (!optimization) {\n console.log(`No optimizations defined for ${asset.getContentType()}`);\n return asset;\n }\n\n const optimizedBuffer = await optimization(buffer).toBuffer();\n\n console.log(\"Optimized asset size\", optimizedBuffer.length);\n\n const newAsset = asset.withProps({ size: optimizedBuffer.length });\n newAsset.setContentsReader(new CallableContentsReader(() => optimizedBuffer));\n\n await s3.putObject({\n Bucket: bucket,\n Key: optimizedAssetKey,\n ContentType: newAsset.getContentType(),\n Body: await newAsset.getContents()\n });\n\n return newAsset;\n }\n }\n\n private isAssetAnimated(asset: Asset) {\n return [\"gif\", \"webp\"].includes(asset.getExtension());\n }\n\n private optimizePng(buffer: Buffer) {\n return sharp(buffer)\n .resize({ width: 2560, withoutEnlargement: true, fit: \"inside\" })\n .png({ compressionLevel: 9, adaptiveFiltering: true, force: true })\n .withMetadata();\n }\n\n private optimizeJpeg(buffer: Buffer) {\n return sharp(buffer)\n .resize({ width: 2560, withoutEnlargement: true, fit: \"inside\" })\n .withMetadata()\n .toFormat(\"jpeg\", { quality: 90 });\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"assetDelivery/s3/SharpTransform.js","sources":["../../../src/assetDelivery/s3/SharpTransform.ts"],"sourcesContent":["import type { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { GetFileUseCase } from \"@webiny/api-file-manager/features/file/GetFile/index.js\";\nimport {\n contentTypeForFormat,\n DEFAULT_IMAGE_QUALITY,\n type ImageFormat\n} from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport type {\n AssetImageEdit,\n Framing,\n ImageRequestOptions\n} from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/imageTypes.js\";\nimport { normalizeImageOptions } from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/normalizeImageOptions.js\";\nimport { CallableContentsReader } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport { AssetKeyGenerator } from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js\";\nimport { ImageAssetTypeHandler } from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js\";\nimport type { Asset } from \"@webiny/api-file-manager/delivery/AssetDelivery/Asset.js\";\nimport type { AssetRequest } from \"@webiny/api-file-manager/delivery/AssetDelivery/AssetRequest.js\";\nimport type { SharpTransformer } from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/SharpTransformer.js\";\nimport { S3Client, S3Bucket, S3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { IS3AssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\ntype TransformOptions = Omit<ImageRequestOptions, \"original\" | \"crop\" | \"focal\" | \"aspectRatio\">;\n\nconst hasTransform = (options: TransformOptions): boolean => {\n return (\n options.width !== undefined || options.format !== undefined || options.quality !== undefined\n );\n};\n\nexport class SharpTransform implements ImageAssetTypeHandler.Interface {\n private readonly s3: S3;\n private readonly bucket: string;\n private readonly imageResizeWidths: number[];\n private readonly imageQuality: Record<ImageFormat, number>;\n private readonly identityContext: IdentityContext.Interface;\n private readonly getFile: GetFileUseCase.Interface;\n private transformer?: SharpTransformer;\n\n constructor(\n s3: S3,\n bucket: string,\n config: IS3AssetDeliveryConfig,\n identityContext: IdentityContext.Interface,\n getFile: GetFileUseCase.Interface\n ) {\n this.s3 = s3;\n this.bucket = bucket;\n this.imageResizeWidths = config.imageResizeWidths;\n this.imageQuality = { ...DEFAULT_IMAGE_QUALITY, ...(config.imageQuality ?? {}) };\n this.identityContext = identityContext;\n this.getFile = getFile;\n }\n\n private async getTransformer(): Promise<SharpTransformer> {\n if (!this.transformer) {\n const { SharpTransformer } =\n await import(\"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/SharpTransformer.js\");\n this.transformer = new SharpTransformer();\n }\n return this.transformer;\n }\n\n async handle(assetRequest: AssetRequest, asset: Asset): Promise<Asset> {\n const rawQuery = assetRequest.getOptions() as Record<string, any>;\n const acceptHeader = assetRequest.getContext<{ accept?: string }>().accept;\n // oxlint-disable-next-line typescript/no-unused-vars\n const { original, crop, focal, aspectRatio, ...options } = normalizeImageOptions(\n rawQuery,\n acceptHeader\n );\n\n const assetCrop = await this.loadAssetCrop(asset.getId());\n const framing: Framing = {\n crop: crop ?? assetCrop,\n focal,\n aspectRatio\n };\n\n const transformedAsset = asset.clone();\n\n if (hasTransform(options)) {\n return this.transformAsset(transformedAsset, options, framing);\n }\n\n return this.optimizeAsset(transformedAsset, framing);\n }\n\n private async loadAssetCrop(fileId: string) {\n const result = await this.identityContext.withoutAuthorization(() =>\n this.getFile.execute(fileId)\n );\n\n if (result.isFail()) {\n return undefined;\n }\n\n const imageEdit = result.value.metadata?.image as AssetImageEdit | undefined;\n return imageEdit?.crop;\n }\n\n private async transformAsset(asset: Asset, options: TransformOptions, framing: Framing) {\n const assetKey = AssetKeyGenerator.create(asset, framing);\n const transformedAssetKey = assetKey.getTransformedImageKey(options);\n\n const contentType = options.format\n ? contentTypeForFormat(options.format)\n : asset.getContentType();\n\n try {\n const { Body } = await this.s3.getObject({\n Bucket: this.bucket,\n Key: transformedAssetKey\n });\n\n if (!Body) {\n throw new Error(`Missing image body!`);\n }\n\n const buffer = Buffer.from(await Body.transformToByteArray());\n\n const newAsset = asset.withProps({ size: buffer.length, contentType });\n newAsset.setContentsReader(CallableContentsReader.create(() => buffer));\n\n console.log(`Return a previously transformed asset`, {\n key: transformedAssetKey,\n size: newAsset.getSize()\n });\n\n return newAsset;\n } catch {\n const optimizedImage = await this.optimizeAsset(asset, framing);\n\n console.log(`Transform the asset`, options);\n const baseBuffer = await optimizedImage.getContents();\n const transformer = await this.getTransformer();\n const { buffer: transformedBuffer, contentType: outputContentType } =\n await transformer.transformBuffer({\n buffer: baseBuffer,\n animated: this.isAssetAnimated(asset),\n sourceContentType: asset.getContentType(),\n widths: this.imageResizeWidths,\n options,\n qualityDefaults: this.imageQuality\n });\n\n const newAsset = asset.withProps({\n size: transformedBuffer.length,\n contentType: outputContentType\n });\n newAsset.setContentsReader(CallableContentsReader.create(() => transformedBuffer));\n\n await this.s3.putObject({\n Bucket: this.bucket,\n Key: transformedAssetKey,\n ContentType: newAsset.getContentType(),\n Body: await newAsset.getContents()\n });\n\n console.log(`Return the transformed asset`, {\n key: transformedAssetKey,\n size: newAsset.getSize(),\n contentType: newAsset.getContentType()\n });\n\n return newAsset;\n }\n }\n\n private async optimizeAsset(asset: Asset, framing: Framing) {\n console.log(\"Optimize asset\", {\n id: asset.getId(),\n key: asset.getKey(),\n size: asset.getSize(),\n type: asset.getContentType()\n });\n\n const assetKey = AssetKeyGenerator.create(asset, framing);\n const optimizedAssetKey = assetKey.getOptimizedImageKey();\n\n try {\n const { Body } = await this.s3.getObject({\n Bucket: this.bucket,\n Key: optimizedAssetKey\n });\n\n if (!Body) {\n throw new Error(`Missing image body!`);\n }\n\n console.log(\"Return a previously optimized asset\", optimizedAssetKey);\n\n const buffer = Buffer.from(await Body.transformToByteArray());\n\n const newAsset = asset.withProps({ size: buffer.length });\n newAsset.setContentsReader(CallableContentsReader.create(() => buffer));\n\n return newAsset;\n } catch {\n console.log(\"Create an optimized version of the original asset\", asset.getKey());\n let buffer = await asset.getContents();\n\n const transformer = await this.getTransformer();\n const framed = await transformer.extractFramedRegion(buffer, framing);\n const cropped = framed !== buffer;\n buffer = framed;\n\n const contentType = asset.getContentType();\n const canOptimize =\n contentType === \"image/png\" ||\n contentType === \"image/jpeg\" ||\n contentType === \"image/jpg\";\n\n if (!canOptimize && !cropped) {\n console.log(`No optimizations defined for ${contentType}`);\n return asset;\n }\n\n let finalBuffer = buffer;\n if (canOptimize) {\n const pipeline =\n contentType === \"image/png\"\n ? await transformer.optimizePng(buffer)\n : await transformer.optimizeJpeg(buffer);\n finalBuffer = await pipeline.toBuffer();\n }\n\n console.log(\"Optimized asset size\", finalBuffer.length);\n\n const newAsset = asset.withProps({ size: finalBuffer.length });\n newAsset.setContentsReader(CallableContentsReader.create(() => finalBuffer));\n\n await this.s3.putObject({\n Bucket: this.bucket,\n Key: optimizedAssetKey,\n ContentType: newAsset.getContentType(),\n Body: await newAsset.getContents()\n });\n\n return newAsset;\n }\n }\n\n private isAssetAnimated(asset: Asset) {\n return [\"gif\", \"webp\"].includes(asset.getExtension());\n }\n}\n\nexport const SharpTransformImpl = ImageAssetTypeHandler.createImplementation({\n implementation: SharpTransform,\n dependencies: [S3Client, S3Bucket, S3AssetDeliveryConfig, IdentityContext, GetFileUseCase]\n});\n"],"names":["hasTransform","options","undefined","SharpTransform","s3","bucket","config","identityContext","getFile","DEFAULT_IMAGE_QUALITY","SharpTransformer","assetRequest","asset","rawQuery","acceptHeader","original","crop","focal","aspectRatio","normalizeImageOptions","assetCrop","framing","transformedAsset","fileId","result","imageEdit","assetKey","AssetKeyGenerator","transformedAssetKey","contentType","contentTypeForFormat","Body","Error","buffer","Buffer","newAsset","CallableContentsReader","console","optimizedImage","baseBuffer","transformer","transformedBuffer","outputContentType","optimizedAssetKey","framed","cropped","canOptimize","finalBuffer","pipeline","SharpTransformImpl","ImageAssetTypeHandler","S3Client","S3Bucket","S3AssetDeliveryConfig","IdentityContext","GetFileUseCase"],"mappings":"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"}
@@ -1,20 +1,21 @@
1
- import * as newUtils from "./utils.js";
2
- export class AssetKeyGenerator {
3
- constructor(asset) {
4
- this.asset = asset;
5
- this.utils = newUtils;
6
- }
7
- getOptimizedImageKey() {
8
- return this.utils.getImageKey({
9
- key: this.asset.getKey()
10
- });
11
- }
12
- getTransformedImageKey(transformations) {
13
- return this.utils.getImageKey({
14
- key: this.asset.getKey(),
15
- transformations
16
- });
17
- }
1
+ import * as __rspack_external__utils_js_a9c81ddd from "./utils.js";
2
+ class AssetKeyGenerator {
3
+ constructor(asset){
4
+ this.asset = asset;
5
+ this.utils = __rspack_external__utils_js_a9c81ddd;
6
+ }
7
+ getOptimizedImageKey() {
8
+ return this.utils.getImageKey({
9
+ key: this.asset.getKey()
10
+ });
11
+ }
12
+ getTransformedImageKey(transformations) {
13
+ return this.utils.getImageKey({
14
+ key: this.asset.getKey(),
15
+ transformations
16
+ });
17
+ }
18
18
  }
19
+ export { AssetKeyGenerator };
19
20
 
20
21
  //# sourceMappingURL=AssetKeyGenerator.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["newUtils","AssetKeyGenerator","constructor","asset","utils","getOptimizedImageKey","getImageKey","key","getKey","getTransformedImageKey","transformations"],"sources":["AssetKeyGenerator.ts"],"sourcesContent":["import type { Asset } from \"@webiny/api-file-manager\";\nimport * as newUtils from \"./utils.js\";\n\nexport class AssetKeyGenerator {\n private utils: typeof newUtils;\n private asset: Asset;\n\n constructor(asset: Asset) {\n this.asset = asset;\n this.utils = newUtils;\n }\n\n getOptimizedImageKey() {\n return this.utils.getImageKey({ key: this.asset.getKey() });\n }\n getTransformedImageKey(transformations: Record<string, any>) {\n return this.utils.getImageKey({ key: this.asset.getKey(), transformations });\n }\n}\n"],"mappings":"AACA,OAAO,KAAKA,QAAQ;AAEpB,OAAO,MAAMC,iBAAiB,CAAC;EAI3BC,WAAWA,CAACC,KAAY,EAAE;IACtB,IAAI,CAACA,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACC,KAAK,GAAGJ,QAAQ;EACzB;EAEAK,oBAAoBA,CAAA,EAAG;IACnB,OAAO,IAAI,CAACD,KAAK,CAACE,WAAW,CAAC;MAAEC,GAAG,EAAE,IAAI,CAACJ,KAAK,CAACK,MAAM,CAAC;IAAE,CAAC,CAAC;EAC/D;EACAC,sBAAsBA,CAACC,eAAoC,EAAE;IACzD,OAAO,IAAI,CAACN,KAAK,CAACE,WAAW,CAAC;MAAEC,GAAG,EAAE,IAAI,CAACJ,KAAK,CAACK,MAAM,CAAC,CAAC;MAAEE;IAAgB,CAAC,CAAC;EAChF;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"assetDelivery/s3/transformation/AssetKeyGenerator.js","sources":["../../../../src/assetDelivery/s3/transformation/AssetKeyGenerator.ts"],"sourcesContent":["import type { Asset } from \"@webiny/api-file-manager\";\nimport * as newUtils from \"./utils.js\";\n\nexport class AssetKeyGenerator {\n private utils: typeof newUtils;\n private asset: Asset;\n\n constructor(asset: Asset) {\n this.asset = asset;\n this.utils = newUtils;\n }\n\n getOptimizedImageKey() {\n return this.utils.getImageKey({ key: this.asset.getKey() });\n }\n getTransformedImageKey(transformations: Record<string, any>) {\n return this.utils.getImageKey({ key: this.asset.getKey(), transformations });\n }\n}\n"],"names":["AssetKeyGenerator","asset","newUtils","transformations"],"mappings":";AAGO,MAAMA;IAIT,YAAYC,KAAY,CAAE;QACtB,IAAI,CAAC,KAAK,GAAGA;QACb,IAAI,CAAC,KAAK,GAAGC;IACjB;IAEA,uBAAuB;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YAAE,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM;QAAG;IAC7D;IACA,uBAAuBC,eAAoC,EAAE;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YAAE,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM;YAAIA;QAAgB;IAC9E;AACJ"}