@webiny/api-file-manager-server 0.0.0-unstable.9f53ea597d → 6.6.0-alpha.0

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 (90) hide show
  1. package/FileManagerServerFeature.d.ts +5 -0
  2. package/FileManagerServerFeature.js +41 -0
  3. package/FileManagerServerFeature.js.map +1 -0
  4. package/assetDelivery/LocalAssetResolver.d.ts +6 -4
  5. package/assetDelivery/LocalAssetResolver.js +9 -9
  6. package/assetDelivery/LocalAssetResolver.js.map +1 -1
  7. package/assetDelivery/LocalOutputStrategy.d.ts +3 -2
  8. package/assetDelivery/LocalOutputStrategy.js +4 -4
  9. package/assetDelivery/LocalOutputStrategy.js.map +1 -1
  10. package/assetDelivery/LocalSharpTransform.d.ts +8 -14
  11. package/assetDelivery/LocalSharpTransform.js +72 -98
  12. package/assetDelivery/LocalSharpTransform.js.map +1 -1
  13. package/assetDelivery/abstractions.d.ts +0 -3
  14. package/assetDelivery/abstractions.js +1 -2
  15. package/assetDelivery/abstractions.js.map +1 -1
  16. package/assetDelivery/assetDeliveryConfig.d.ts +1 -1
  17. package/assetDelivery/feature.js +7 -9
  18. package/assetDelivery/feature.js.map +1 -1
  19. package/assetDelivery/types.d.ts +0 -3
  20. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.d.ts +3 -0
  21. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js +18 -14
  22. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js.map +1 -1
  23. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +7 -5
  24. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +8 -5
  25. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -1
  26. package/features/CompleteMultiPartUpload/feature.js +2 -2
  27. package/features/CompleteMultiPartUpload/feature.js.map +1 -1
  28. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +7 -7
  29. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +9 -10
  30. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -1
  31. package/features/CreateMultiPartUpload/feature.js +2 -2
  32. package/features/CreateMultiPartUpload/feature.js.map +1 -1
  33. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.d.ts +3 -1
  34. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js +6 -3
  35. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js.map +1 -1
  36. package/features/ExtractMetadata/ExtractMetadataTask.d.ts +3 -1
  37. package/features/ExtractMetadata/ExtractMetadataTask.js +6 -3
  38. package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
  39. package/features/FileManagerServerConfig/FileManagerServerConfig.d.ts +12 -0
  40. package/features/FileManagerServerConfig/FileManagerServerConfig.js +28 -0
  41. package/features/FileManagerServerConfig/FileManagerServerConfig.js.map +1 -0
  42. package/features/FileManagerServerConfig/abstractions.d.ts +10 -0
  43. package/features/FileManagerServerConfig/abstractions.js +5 -0
  44. package/features/FileManagerServerConfig/abstractions.js.map +1 -0
  45. package/features/FileManagerServerConfig/feature.d.ts +4 -0
  46. package/features/FileManagerServerConfig/feature.js +11 -0
  47. package/features/FileManagerServerConfig/feature.js.map +1 -0
  48. package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +7 -5
  49. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +8 -5
  50. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -1
  51. package/features/GetFileContentsById/feature.js +2 -2
  52. package/features/GetFileContentsById/feature.js.map +1 -1
  53. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +7 -5
  54. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +8 -5
  55. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -1
  56. package/features/GetFileContentsByKey/feature.js +2 -2
  57. package/features/GetFileContentsByKey/feature.js.map +1 -1
  58. package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +6 -6
  59. package/features/GetUploadPayload/GetUploadPayloadUseCase.js +8 -9
  60. package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -1
  61. package/features/GetUploadPayload/feature.js +2 -2
  62. package/features/GetUploadPayload/feature.js.map +1 -1
  63. package/graphql/ServerGraphQLSchema.d.ts +15 -0
  64. package/graphql/ServerGraphQLSchema.js +221 -0
  65. package/graphql/ServerGraphQLSchema.js.map +1 -0
  66. package/index.d.ts +1 -2
  67. package/index.js +1 -40
  68. package/package.json +13 -13
  69. package/routes/UploadPartRoute/UploadPartRoute.d.ts +14 -0
  70. package/routes/UploadPartRoute/UploadPartRoute.js +66 -0
  71. package/routes/UploadPartRoute/UploadPartRoute.js.map +1 -0
  72. package/routes/UploadPartRoute/feature.d.ts +4 -0
  73. package/routes/UploadPartRoute/feature.js +11 -0
  74. package/routes/UploadPartRoute/feature.js.map +1 -0
  75. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.d.ts +14 -0
  76. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js +70 -0
  77. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js.map +1 -0
  78. package/routes/UploadSingleFileRoute/feature.d.ts +4 -0
  79. package/routes/UploadSingleFileRoute/feature.js +11 -0
  80. package/routes/UploadSingleFileRoute/feature.js.map +1 -0
  81. package/routes/utils.d.ts +20 -0
  82. package/routes/utils.js +62 -0
  83. package/routes/utils.js.map +1 -0
  84. package/index.js.map +0 -1
  85. package/routes/uploadRoutes.d.ts +0 -4
  86. package/routes/uploadRoutes.js +0 -130
  87. package/routes/uploadRoutes.js.map +0 -1
  88. package/utils/resolveServerUrl.d.ts +0 -2
  89. package/utils/resolveServerUrl.js +0 -10
  90. package/utils/resolveServerUrl.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ import { type Container } from "@webiny/feature/api";
2
+ export declare const FileManagerServerFeature: {
3
+ name: string;
4
+ register(container: Container): void;
5
+ };
@@ -0,0 +1,41 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { ReadFileMetadataFeature } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/feature.js";
3
+ import { WriteFileMetadataFeature } from "@webiny/api-file-manager/features/upload/WriteFileMetadata/feature.js";
4
+ import { createLocalAssetDeliveryFeature } from "./assetDelivery/feature.js";
5
+ import { ServerGraphQLSchema } from "./graphql/ServerGraphQLSchema.js";
6
+ import { FileManagerServerConfigFeature } from "./features/FileManagerServerConfig/feature.js";
7
+ import { UploadSingleFileRouteFeature } from "./routes/UploadSingleFileRoute/feature.js";
8
+ import { UploadPartRouteFeature } from "./routes/UploadPartRoute/feature.js";
9
+ import { CleanupStaleMultipartUploadsFeature } from "./features/CleanupStaleMultipartUploads/feature.js";
10
+ import { DeleteFileFromDiskFeature } from "./features/DeleteFileFromDisk/feature.js";
11
+ import { ExtractMetadataFeature } from "./features/ExtractMetadata/feature.js";
12
+ import { FlushCacheFeature } from "./features/FlushCache/feature.js";
13
+ import { GetFileContentsByIdFeature } from "./features/GetFileContentsById/feature.js";
14
+ import { GetFileContentsByKeyFeature } from "./features/GetFileContentsByKey/feature.js";
15
+ import { GetUploadPayloadFeature } from "./features/GetUploadPayload/feature.js";
16
+ import { CreateMultiPartUploadFeature } from "./features/CreateMultiPartUpload/feature.js";
17
+ import { CompleteMultiPartUploadFeature } from "./features/CompleteMultiPartUpload/feature.js";
18
+ const FileManagerServerFeature = createFeature({
19
+ name: "FileManagerServer",
20
+ register (container) {
21
+ FileManagerServerConfigFeature.register(container);
22
+ createLocalAssetDeliveryFeature().register(container);
23
+ ReadFileMetadataFeature.register(container);
24
+ WriteFileMetadataFeature.register(container);
25
+ FlushCacheFeature.register(container);
26
+ DeleteFileFromDiskFeature.register(container);
27
+ ExtractMetadataFeature.register(container);
28
+ GetFileContentsByIdFeature.register(container);
29
+ GetFileContentsByKeyFeature.register(container);
30
+ GetUploadPayloadFeature.register(container);
31
+ CreateMultiPartUploadFeature.register(container);
32
+ CompleteMultiPartUploadFeature.register(container);
33
+ CleanupStaleMultipartUploadsFeature.register(container);
34
+ UploadSingleFileRouteFeature.register(container);
35
+ UploadPartRouteFeature.register(container);
36
+ container.register(ServerGraphQLSchema);
37
+ }
38
+ });
39
+ export { FileManagerServerFeature };
40
+
41
+ //# sourceMappingURL=FileManagerServerFeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileManagerServerFeature.js","sources":["../src/FileManagerServerFeature.ts"],"sourcesContent":["import { type Container, createFeature } from \"@webiny/feature/api\";\nimport { ReadFileMetadataFeature } from \"@webiny/api-file-manager/features/upload/ReadFileMetadata/feature.js\";\nimport { WriteFileMetadataFeature } from \"@webiny/api-file-manager/features/upload/WriteFileMetadata/feature.js\";\nimport { createLocalAssetDeliveryFeature } from \"~/assetDelivery/feature.js\";\nimport { ServerGraphQLSchema } from \"~/graphql/ServerGraphQLSchema.js\";\nimport { FileManagerServerConfigFeature } from \"~/features/FileManagerServerConfig/feature.js\";\nimport { UploadSingleFileRouteFeature } from \"~/routes/UploadSingleFileRoute/feature.js\";\nimport { UploadPartRouteFeature } from \"~/routes/UploadPartRoute/feature.js\";\nimport { CleanupStaleMultipartUploadsFeature } from \"~/features/CleanupStaleMultipartUploads/feature.js\";\nimport { DeleteFileFromDiskFeature } from \"~/features/DeleteFileFromDisk/feature.js\";\nimport { ExtractMetadataFeature } from \"~/features/ExtractMetadata/feature.js\";\nimport { FlushCacheFeature } from \"~/features/FlushCache/feature.js\";\nimport { GetFileContentsByIdFeature } from \"~/features/GetFileContentsById/feature.js\";\nimport { GetFileContentsByKeyFeature } from \"~/features/GetFileContentsByKey/feature.js\";\nimport { GetUploadPayloadFeature } from \"~/features/GetUploadPayload/feature.js\";\nimport { CreateMultiPartUploadFeature } from \"~/features/CreateMultiPartUpload/feature.js\";\nimport { CompleteMultiPartUploadFeature } from \"~/features/CompleteMultiPartUpload/feature.js\";\n\nexport const FileManagerServerFeature = createFeature({\n name: \"FileManagerServer\",\n register(container: Container) {\n // NOTE: do NOT resolve FileManagerServerConfig here. This runs at the file-manager transport\n // hook, BEFORE project extensions (which register the WEBINY_LOCAL_STORAGE_PATH /\n // WEBINY_UPLOAD_SECRET build params) are applied later in the request stack. Config is resolved\n // lazily at request time by the routes/use-cases below; it also ensures its storage dir on\n // construction. Resolving it eagerly here would read the build params before they exist.\n FileManagerServerConfigFeature.register(container);\n\n // Local (disk) asset-delivery implementations (LocalAssetResolver/OutputStrategy/SharpTransform)\n // override the null delivery registered by AssetDeliveryFeature in FileManagerAppFeature — the\n // same seam FileManagerS3Feature uses with createS3AssetDeliveryFeature. Without this the domain\n // AssetDeliveryRoute resolves the null impls and serves nothing.\n createLocalAssetDeliveryFeature().register(container);\n\n // Metadata reader (FileManager/Upload/MetadataReader) — the generic domain impl backed by the\n // GlobalKeyValueStore. Required by the server's ExtractMetadata task + GetFileContentsById use\n // cases; without it createFile fails with \"No registration found for FileManager/Upload/MetadataReader\".\n ReadFileMetadataFeature.register(container);\n\n // Metadata writer — the generic domain WriteMetadataAfterCreate/BatchCreate event handlers write\n // the asset metadata (id/tenant/size/contentType/bucketKey) to the GlobalKeyValueStore on file\n // create. Asset delivery (LocalAssetResolver) reads that metadata to locate the file on disk;\n // without it every delivered file 404s (\"asset not found\"). Mirrors S3's WriteFileMetadataFeature.\n WriteFileMetadataFeature.register(container);\n\n FlushCacheFeature.register(container);\n DeleteFileFromDiskFeature.register(container);\n ExtractMetadataFeature.register(container);\n GetFileContentsByIdFeature.register(container);\n GetFileContentsByKeyFeature.register(container);\n GetUploadPayloadFeature.register(container);\n CreateMultiPartUploadFeature.register(container);\n CompleteMultiPartUploadFeature.register(container);\n CleanupStaleMultipartUploadsFeature.register(container);\n UploadSingleFileRouteFeature.register(container);\n UploadPartRouteFeature.register(container);\n\n // Upload GraphQL (getPreSignedPostPayload/getPreSignedPostPayloads + create/completeMultiPartUpload).\n // Mirrors how FileManagerS3Feature contributes its schema — same query/mutation names so the SDK\n // works unchanged; resolvers delegate to the server upload use cases registered above.\n container.register(ServerGraphQLSchema);\n }\n});\n"],"names":["FileManagerServerFeature","createFeature","container","FileManagerServerConfigFeature","createLocalAssetDeliveryFeature","ReadFileMetadataFeature","WriteFileMetadataFeature","FlushCacheFeature","DeleteFileFromDiskFeature","ExtractMetadataFeature","GetFileContentsByIdFeature","GetFileContentsByKeyFeature","GetUploadPayloadFeature","CreateMultiPartUploadFeature","CompleteMultiPartUploadFeature","CleanupStaleMultipartUploadsFeature","UploadSingleFileRouteFeature","UploadPartRouteFeature","ServerGraphQLSchema"],"mappings":";;;;;;;;;;;;;;;;;AAkBO,MAAMA,2BAA2BC,cAAc;IAClD,MAAM;IACN,UAASC,SAAoB;QAMzBC,+BAA+B,QAAQ,CAACD;QAMxCE,kCAAkC,QAAQ,CAACF;QAK3CG,wBAAwB,QAAQ,CAACH;QAMjCI,yBAAyB,QAAQ,CAACJ;QAElCK,kBAAkB,QAAQ,CAACL;QAC3BM,0BAA0B,QAAQ,CAACN;QACnCO,uBAAuB,QAAQ,CAACP;QAChCQ,2BAA2B,QAAQ,CAACR;QACpCS,4BAA4B,QAAQ,CAACT;QACrCU,wBAAwB,QAAQ,CAACV;QACjCW,6BAA6B,QAAQ,CAACX;QACtCY,+BAA+B,QAAQ,CAACZ;QACxCa,oCAAoC,QAAQ,CAACb;QAC7Cc,6BAA6B,QAAQ,CAACd;QACtCe,uBAAuB,QAAQ,CAACf;QAKhCA,UAAU,QAAQ,CAACgB;IACvB;AACJ"}
@@ -1,13 +1,15 @@
1
1
  import { AssetFactory, AssetResolver as AssetResolverAbstraction, ObjectKey } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
2
2
  import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
3
- export declare class LocalAssetResolver implements AssetResolverAbstraction.Interface {
3
+ import { FileManagerServerConfig } from "../features/FileManagerServerConfig/abstractions.js";
4
+ declare class AssetResolverImpl implements AssetResolverAbstraction.Interface {
4
5
  private readonly keyValueStore;
5
- private readonly storagePath;
6
+ private readonly config;
6
7
  private readonly objectKey;
7
8
  private readonly assetFactory;
8
- constructor(keyValueStore: GlobalKeyValueStore.Interface, storagePath: string, objectKey: ObjectKey.Interface, assetFactory: AssetFactory.Interface);
9
+ constructor(keyValueStore: GlobalKeyValueStore.Interface, config: FileManagerServerConfig.Interface, objectKey: ObjectKey.Interface, assetFactory: AssetFactory.Interface);
9
10
  resolve(request: AssetResolverAbstraction.Request): Promise<AssetFactory.Asset | undefined>;
10
11
  }
11
- export declare const LocalAssetResolverImpl: typeof LocalAssetResolver & {
12
+ export declare const LocalAssetResolver: typeof AssetResolverImpl & {
12
13
  __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/delivery").AssetResolver>;
13
14
  };
15
+ export {};
@@ -1,11 +1,11 @@
1
1
  import { AssetFactory, AssetResolver, ObjectKey } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
2
2
  import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
3
3
  import { LocalContentsReader } from "./LocalContentsReader.js";
4
- import { LocalStoragePath } from "./abstractions.js";
5
- class LocalAssetResolver {
6
- constructor(keyValueStore, storagePath, objectKey, assetFactory){
4
+ import { FileManagerServerConfig } from "../features/FileManagerServerConfig/abstractions.js";
5
+ class AssetResolverImpl {
6
+ constructor(keyValueStore, config, objectKey, assetFactory){
7
7
  this.keyValueStore = keyValueStore;
8
- this.storagePath = storagePath;
8
+ this.config = config;
9
9
  this.objectKey = objectKey;
10
10
  this.assetFactory = assetFactory;
11
11
  }
@@ -22,19 +22,19 @@ class LocalAssetResolver {
22
22
  contentType: metadata.contentType,
23
23
  key: metadata.bucketKey
24
24
  });
25
- asset.setContentsReader(LocalContentsReader.create(this.storagePath));
25
+ asset.setContentsReader(LocalContentsReader.create(this.config.storagePath));
26
26
  return asset;
27
27
  }
28
28
  }
29
- const LocalAssetResolverImpl = AssetResolver.createImplementation({
30
- implementation: LocalAssetResolver,
29
+ const LocalAssetResolver = AssetResolver.createImplementation({
30
+ implementation: AssetResolverImpl,
31
31
  dependencies: [
32
32
  GlobalKeyValueStore,
33
- LocalStoragePath,
33
+ FileManagerServerConfig,
34
34
  ObjectKey,
35
35
  AssetFactory
36
36
  ]
37
37
  });
38
- export { LocalAssetResolver, LocalAssetResolverImpl };
38
+ export { LocalAssetResolver };
39
39
 
40
40
  //# sourceMappingURL=LocalAssetResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assetDelivery/LocalAssetResolver.js","sources":["../../src/assetDelivery/LocalAssetResolver.ts"],"sourcesContent":["import {\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 { LocalContentsReader } from \"~/assetDelivery/LocalContentsReader.js\";\nimport { LocalStoragePath } 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 LocalAssetResolver implements AssetResolverAbstraction.Interface {\n constructor(\n private readonly keyValueStore: GlobalKeyValueStore.Interface,\n private readonly storagePath: 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 objectKey = this.objectKey.from(request.getKey());\n const fileId = objectKey.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(LocalContentsReader.create(this.storagePath));\n\n return asset;\n }\n}\n\nexport const LocalAssetResolverImpl = AssetResolverAbstraction.createImplementation({\n implementation: LocalAssetResolver,\n dependencies: [GlobalKeyValueStore, LocalStoragePath, ObjectKey, AssetFactory]\n});\n"],"names":["LocalAssetResolver","keyValueStore","storagePath","objectKey","assetFactory","request","fileId","result","metadata","asset","LocalContentsReader","LocalAssetResolverImpl","AssetResolverAbstraction","GlobalKeyValueStore","LocalStoragePath","ObjectKey","AssetFactory"],"mappings":";;;;AAiBO,MAAMA;IACT,YACqBC,aAA4C,EAC5CC,WAAmB,EACnBC,SAA8B,EAC9BC,YAAoC,CACvD;aAJmBH,aAAa,GAAbA;aACAC,WAAW,GAAXA;aACAC,SAAS,GAATA;aACAC,YAAY,GAAZA;IAClB;IAEH,MAAM,QACFC,OAAyC,EACF;QACvC,MAAMF,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,CAACE,QAAQ,MAAM;QACpD,MAAMC,SAASH,UAAU,EAAE;QAC3B,MAAMI,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,oBAAoB,MAAM,CAAC,IAAI,CAAC,WAAW;QAEnE,OAAOD;IACX;AACJ;AAEO,MAAME,yBAAyBC,cAAAA,oBAA6C,CAAC;IAChF,gBAAgBZ;IAChB,cAAc;QAACa;QAAqBC;QAAkBC;QAAWC;KAAa;AAClF"}
1
+ {"version":3,"file":"assetDelivery/LocalAssetResolver.js","sources":["../../src/assetDelivery/LocalAssetResolver.ts"],"sourcesContent":["import {\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 { LocalContentsReader } from \"~/assetDelivery/LocalContentsReader.js\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\n\ninterface AssetMetadata {\n id: string;\n tenant: string;\n size: number;\n contentType: string;\n bucketKey: string;\n}\n\nclass AssetResolverImpl implements AssetResolverAbstraction.Interface {\n constructor(\n private readonly keyValueStore: GlobalKeyValueStore.Interface,\n private readonly config: FileManagerServerConfig.Interface,\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 objectKey = this.objectKey.from(request.getKey());\n const fileId = objectKey.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(LocalContentsReader.create(this.config.storagePath));\n\n return asset;\n }\n}\n\nexport const LocalAssetResolver = AssetResolverAbstraction.createImplementation({\n implementation: AssetResolverImpl,\n dependencies: [GlobalKeyValueStore, FileManagerServerConfig, ObjectKey, AssetFactory]\n});\n"],"names":["AssetResolverImpl","keyValueStore","config","objectKey","assetFactory","request","fileId","result","metadata","asset","LocalContentsReader","LocalAssetResolver","AssetResolverAbstraction","GlobalKeyValueStore","FileManagerServerConfig","ObjectKey","AssetFactory"],"mappings":";;;;AAiBA,MAAMA;IACF,YACqBC,aAA4C,EAC5CC,MAAyC,EACzCC,SAA8B,EAC9BC,YAAoC,CACvD;aAJmBH,aAAa,GAAbA;aACAC,MAAM,GAANA;aACAC,SAAS,GAATA;aACAC,YAAY,GAAZA;IAClB;IAEH,MAAM,QACFC,OAAyC,EACF;QACvC,MAAMF,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,CAACE,QAAQ,MAAM;QACpD,MAAMC,SAASH,UAAU,EAAE;QAC3B,MAAMI,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,oBAAoB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW;QAE1E,OAAOD;IACX;AACJ;AAEO,MAAME,qBAAqBC,cAAAA,oBAA6C,CAAC;IAC5E,gBAAgBZ;IAChB,cAAc;QAACa;QAAqBC;QAAyBC;QAAWC;KAAa;AACzF"}
@@ -1,11 +1,12 @@
1
1
  import { AssetOutputStrategy as AssetOutputStrategyAbstraction, StreamAssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
2
2
  import type { ILocalAssetDeliveryConfig } from "../assetDelivery/abstractions.js";
3
- export declare class LocalOutputStrategy implements AssetOutputStrategyAbstraction.Interface {
3
+ declare class AssetOutputStrategyImpl implements AssetOutputStrategyAbstraction.Interface {
4
4
  private readonly assetStreamingMaxSize;
5
5
  private readonly streamAssetReply;
6
6
  constructor(config: ILocalAssetDeliveryConfig, streamAssetReply: StreamAssetReply.Interface);
7
7
  output(asset: AssetOutputStrategyAbstraction.Asset): Promise<AssetOutputStrategyAbstraction.AssetReply>;
8
8
  }
9
- export declare const LocalOutputStrategyImpl: typeof LocalOutputStrategy & {
9
+ export declare const LocalOutputStrategy: typeof AssetOutputStrategyImpl & {
10
10
  __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/delivery").AssetOutputStrategy>;
11
11
  };
12
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { AssetOutputStrategy, StreamAssetReply } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
2
2
  import { LocalAssetDeliveryConfig } from "./abstractions.js";
3
- class LocalOutputStrategy {
3
+ class AssetOutputStrategyImpl {
4
4
  constructor(config, streamAssetReply){
5
5
  this.assetStreamingMaxSize = config.assetStreamingMaxSize;
6
6
  this.streamAssetReply = streamAssetReply;
@@ -9,13 +9,13 @@ class LocalOutputStrategy {
9
9
  return this.streamAssetReply.create(asset);
10
10
  }
11
11
  }
12
- const LocalOutputStrategyImpl = AssetOutputStrategy.createImplementation({
13
- implementation: LocalOutputStrategy,
12
+ const LocalOutputStrategy = AssetOutputStrategy.createImplementation({
13
+ implementation: AssetOutputStrategyImpl,
14
14
  dependencies: [
15
15
  LocalAssetDeliveryConfig,
16
16
  StreamAssetReply
17
17
  ]
18
18
  });
19
- export { LocalOutputStrategy, LocalOutputStrategyImpl };
19
+ export { LocalOutputStrategy };
20
20
 
21
21
  //# sourceMappingURL=LocalOutputStrategy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assetDelivery/LocalOutputStrategy.js","sources":["../../src/assetDelivery/LocalOutputStrategy.ts"],"sourcesContent":["import {\n AssetOutputStrategy as AssetOutputStrategyAbstraction,\n StreamAssetReply\n} from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { LocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { ILocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\nexport class LocalOutputStrategy implements AssetOutputStrategyAbstraction.Interface {\n private readonly assetStreamingMaxSize: number;\n private readonly streamAssetReply: StreamAssetReply.Interface;\n\n constructor(config: ILocalAssetDeliveryConfig, streamAssetReply: StreamAssetReply.Interface) {\n this.assetStreamingMaxSize = config.assetStreamingMaxSize;\n this.streamAssetReply = streamAssetReply;\n }\n\n async output(\n asset: AssetOutputStrategyAbstraction.Asset\n ): Promise<AssetOutputStrategyAbstraction.AssetReply> {\n return this.streamAssetReply.create(asset);\n }\n}\n\nexport const LocalOutputStrategyImpl = AssetOutputStrategyAbstraction.createImplementation({\n implementation: LocalOutputStrategy,\n dependencies: [LocalAssetDeliveryConfig, StreamAssetReply]\n});\n"],"names":["LocalOutputStrategy","config","streamAssetReply","asset","LocalOutputStrategyImpl","AssetOutputStrategyAbstraction","LocalAssetDeliveryConfig","StreamAssetReply"],"mappings":";;AAOO,MAAMA;IAIT,YAAYC,MAAiC,EAAEC,gBAA4C,CAAE;QACzF,IAAI,CAAC,qBAAqB,GAAGD,OAAO,qBAAqB;QACzD,IAAI,CAAC,gBAAgB,GAAGC;IAC5B;IAEA,MAAM,OACFC,KAA2C,EACO;QAClD,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACA;IACxC;AACJ;AAEO,MAAMC,0BAA0BC,oBAAAA,oBAAmD,CAAC;IACvF,gBAAgBL;IAChB,cAAc;QAACM;QAA0BC;KAAiB;AAC9D"}
1
+ {"version":3,"file":"assetDelivery/LocalOutputStrategy.js","sources":["../../src/assetDelivery/LocalOutputStrategy.ts"],"sourcesContent":["import {\n AssetOutputStrategy as AssetOutputStrategyAbstraction,\n StreamAssetReply\n} from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { LocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { ILocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\nclass AssetOutputStrategyImpl implements AssetOutputStrategyAbstraction.Interface {\n private readonly assetStreamingMaxSize: number;\n private readonly streamAssetReply: StreamAssetReply.Interface;\n\n constructor(config: ILocalAssetDeliveryConfig, streamAssetReply: StreamAssetReply.Interface) {\n this.assetStreamingMaxSize = config.assetStreamingMaxSize;\n this.streamAssetReply = streamAssetReply;\n }\n\n async output(\n asset: AssetOutputStrategyAbstraction.Asset\n ): Promise<AssetOutputStrategyAbstraction.AssetReply> {\n return this.streamAssetReply.create(asset);\n }\n}\n\nexport const LocalOutputStrategy = AssetOutputStrategyAbstraction.createImplementation({\n implementation: AssetOutputStrategyImpl,\n dependencies: [LocalAssetDeliveryConfig, StreamAssetReply]\n});\n"],"names":["AssetOutputStrategyImpl","config","streamAssetReply","asset","LocalOutputStrategy","AssetOutputStrategyAbstraction","LocalAssetDeliveryConfig","StreamAssetReply"],"mappings":";;AAOA,MAAMA;IAIF,YAAYC,MAAiC,EAAEC,gBAA4C,CAAE;QACzF,IAAI,CAAC,qBAAqB,GAAGD,OAAO,qBAAqB;QACzD,IAAI,CAAC,gBAAgB,GAAGC;IAC5B;IAEA,MAAM,OACFC,KAA2C,EACO;QAClD,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACA;IACxC;AACJ;AAEO,MAAMC,sBAAsBC,oBAAAA,oBAAmD,CAAC;IACnF,gBAAgBL;IAChB,cAAc;QAACM;QAA0BC;KAAiB;AAC9D"}
@@ -1,24 +1,18 @@
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 type { IAssetTypeHandler } from "@webiny/api-file-manager/features/assetDelivery/abstractions/AssetType.js";
4
- import type { Asset } from "@webiny/api-file-manager/delivery/AssetDelivery/Asset.js";
5
- import type { AssetRequest } from "@webiny/api-file-manager/delivery/AssetDelivery/AssetRequest.js";
1
+ import { AssetTransformationStrategy as AssetTransformationStrategyAbstraction } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
2
+ import { FileManagerServerConfig } from "../features/FileManagerServerConfig/abstractions.js";
6
3
  import type { ILocalAssetDeliveryConfig } from "../assetDelivery/abstractions.js";
7
- export declare class LocalSharpTransform implements IAssetTypeHandler {
4
+ declare class AssetTransformationStrategyImpl implements AssetTransformationStrategyAbstraction.Interface {
8
5
  private readonly storagePath;
9
6
  private readonly imageResizeWidths;
10
- private readonly imageQuality;
11
- private readonly identityContext;
12
- private readonly getFile;
13
- constructor(storagePath: string, config: ILocalAssetDeliveryConfig, identityContext: IdentityContext.Interface, getFile: GetFileUseCase.Interface);
14
- handle(assetRequest: AssetRequest, asset: Asset): Promise<Asset>;
15
- private loadAssetCrop;
7
+ constructor(serverConfig: FileManagerServerConfig.Interface, config: ILocalAssetDeliveryConfig);
8
+ transform(assetRequest: AssetTransformationStrategyAbstraction.AssetRequest, asset: AssetTransformationStrategyAbstraction.Asset): Promise<AssetTransformationStrategyAbstraction.Asset>;
16
9
  private transformAsset;
17
10
  private optimizeAsset;
18
11
  private isAssetAnimated;
19
12
  private optimizePng;
20
13
  private optimizeJpeg;
21
14
  }
22
- export declare const LocalSharpTransformImpl: typeof LocalSharpTransform & {
23
- __abstraction: import("@webiny/di").Abstraction<IAssetTypeHandler>;
15
+ export declare const LocalSharpTransform: typeof AssetTransformationStrategyImpl & {
16
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/delivery").AssetTransformationStrategy>;
24
17
  };
18
+ export {};
@@ -1,99 +1,78 @@
1
1
  import sharp from "sharp";
2
2
  import promises from "node:fs/promises";
3
3
  import node_path from "node:path";
4
- import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
5
- import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
6
- import { CallableContentsReader, DEFAULT_IMAGE_QUALITY, contentTypeForFormat } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
7
- import { extractFramedRegion, transformImageBuffer } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/transformImage.js";
8
- import { normalizeImageOptions } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/normalizeImageOptions.js";
9
- import { AssetKeyGenerator, ImageAssetTypeHandler } from "@webiny/api-file-manager/features/assetDelivery/assetTypes/image/index.js";
10
- import { LocalAssetDeliveryConfig, LocalStoragePath } from "./abstractions.js";
11
- const hasTransform = (options)=>void 0 !== options.width || void 0 !== options.format || void 0 !== options.quality;
12
- class LocalSharpTransform {
13
- constructor(storagePath, config, identityContext, getFile){
14
- this.storagePath = storagePath;
4
+ import { AssetTransformationStrategy } from "@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js";
5
+ import { LocalAssetDeliveryConfig } from "./abstractions.js";
6
+ import { FileManagerServerConfig } from "../features/FileManagerServerConfig/abstractions.js";
7
+ import * as __rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114 from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
8
+ class AssetTransformationStrategyImpl {
9
+ constructor(serverConfig, config){
10
+ this.storagePath = serverConfig.storagePath;
15
11
  this.imageResizeWidths = config.imageResizeWidths;
16
- this.imageQuality = {
17
- ...DEFAULT_IMAGE_QUALITY,
18
- ...config.imageQuality ?? {}
19
- };
20
- this.identityContext = identityContext;
21
- this.getFile = getFile;
22
12
  }
23
- async handle(assetRequest, asset) {
24
- const rawQuery = assetRequest.getOptions();
25
- const acceptHeader = assetRequest.getContext().accept;
26
- const { original, crop, focal, aspectRatio, ...options } = normalizeImageOptions(rawQuery, acceptHeader);
27
- const assetCrop = await this.loadAssetCrop(asset.getId());
28
- const framing = {
29
- crop: crop ?? assetCrop,
30
- focal,
31
- aspectRatio
32
- };
13
+ async transform(assetRequest, asset) {
14
+ if (!__rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.SUPPORTED_TRANSFORMABLE_IMAGES.includes(asset.getExtension())) {
15
+ console.log(`Transformations/optimizations of ${asset.getContentType()} assets are not supported. Skipping.`);
16
+ return asset;
17
+ }
18
+ const { original, ...options } = assetRequest.getOptions();
33
19
  const transformedAsset = asset.clone();
34
- if (hasTransform(options)) return this.transformAsset(transformedAsset, options, framing);
35
- return this.optimizeAsset(transformedAsset, framing);
36
- }
37
- async loadAssetCrop(fileId) {
38
- const result = await this.identityContext.withoutAuthorization(()=>this.getFile.execute(fileId));
39
- if (result.isFail()) return;
40
- const imageEdit = result.value.metadata?.imageEdit;
41
- return imageEdit?.crop;
20
+ if (Object.keys(options).length > 0) return this.transformAsset(transformedAsset, options);
21
+ return this.optimizeAsset(transformedAsset);
42
22
  }
43
- async transformAsset(asset, options, framing) {
44
- const assetKey = AssetKeyGenerator.create(asset, framing);
45
- const transformedAssetKey = assetKey.getTransformedImageKey(options);
46
- const transformedFilePath = node_path.join(this.storagePath, transformedAssetKey);
47
- const contentType = options.format ? contentTypeForFormat(options.format) : asset.getContentType();
48
- try {
49
- const buffer = await promises.readFile(transformedFilePath);
50
- const newAsset = asset.withProps({
51
- size: buffer.length,
52
- contentType
53
- });
54
- newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
55
- console.log("Return a previously transformed asset", {
56
- key: transformedAssetKey,
57
- size: newAsset.getSize()
58
- });
59
- return newAsset;
60
- } catch {
61
- const optimizedImage = await this.optimizeAsset(asset, framing);
62
- console.log("Transform the asset", options);
63
- const baseBuffer = await optimizedImage.getContents();
64
- const { buffer: transformedBuffer, contentType: outputContentType } = await transformImageBuffer({
65
- buffer: baseBuffer,
66
- animated: this.isAssetAnimated(asset),
67
- sourceContentType: asset.getContentType(),
68
- widths: this.imageResizeWidths,
69
- options,
70
- qualityDefaults: this.imageQuality
71
- });
72
- const newAsset = asset.withProps({
73
- size: transformedBuffer.length,
74
- contentType: outputContentType
75
- });
76
- newAsset.setContentsReader(CallableContentsReader.create(()=>transformedBuffer));
77
- await promises.mkdir(node_path.dirname(transformedFilePath), {
78
- recursive: true
79
- });
80
- await promises.writeFile(transformedFilePath, await newAsset.getContents());
81
- console.log("Return the transformed asset", {
82
- key: transformedAssetKey,
83
- size: newAsset.getSize(),
84
- contentType: newAsset.getContentType()
85
- });
86
- return newAsset;
23
+ async transformAsset(asset, options) {
24
+ if (options.width) {
25
+ const assetKey = __rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.AssetKeyGenerator.create(asset);
26
+ const transformedAssetKey = assetKey.getTransformedImageKey(options);
27
+ const transformedFilePath = node_path.join(this.storagePath, transformedAssetKey);
28
+ try {
29
+ const buffer = await promises.readFile(transformedFilePath);
30
+ const newAsset = asset.withProps({
31
+ size: buffer.length
32
+ });
33
+ newAsset.setContentsReader(__rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.CallableContentsReader.create(()=>buffer));
34
+ console.log("Return a previously transformed asset", {
35
+ key: transformedAssetKey,
36
+ size: newAsset.getSize()
37
+ });
38
+ return newAsset;
39
+ } catch {
40
+ const optimizedImage = await this.optimizeAsset(asset);
41
+ const widths = __rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.WidthCollection.create(this.imageResizeWidths);
42
+ const width = widths.getClosestOrMax(options.width);
43
+ console.log(`Resize the asset (width: ${width})`);
44
+ const buffer = await optimizedImage.getContents();
45
+ const transformedBuffer = await sharp(buffer, {
46
+ animated: this.isAssetAnimated(asset)
47
+ }).withMetadata().resize({
48
+ width,
49
+ withoutEnlargement: true
50
+ }).toBuffer();
51
+ const newAsset = asset.withProps({
52
+ size: transformedBuffer.length
53
+ });
54
+ newAsset.setContentsReader(__rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.CallableContentsReader.create(()=>transformedBuffer));
55
+ await promises.mkdir(node_path.dirname(transformedFilePath), {
56
+ recursive: true
57
+ });
58
+ await promises.writeFile(transformedFilePath, await newAsset.getContents());
59
+ console.log("Return the resized asset", {
60
+ key: transformedAssetKey,
61
+ size: newAsset.getSize()
62
+ });
63
+ return newAsset;
64
+ }
87
65
  }
66
+ return asset;
88
67
  }
89
- async optimizeAsset(asset, framing) {
68
+ async optimizeAsset(asset) {
90
69
  console.log("Optimize asset", {
91
70
  id: asset.getId(),
92
71
  key: asset.getKey(),
93
72
  size: asset.getSize(),
94
73
  type: asset.getContentType()
95
74
  });
96
- const assetKey = AssetKeyGenerator.create(asset, framing);
75
+ const assetKey = __rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.AssetKeyGenerator.create(asset);
97
76
  const optimizedAssetKey = assetKey.getOptimizedImageKey();
98
77
  const optimizedFilePath = node_path.join(this.storagePath, optimizedAssetKey);
99
78
  try {
@@ -102,30 +81,27 @@ class LocalSharpTransform {
102
81
  const newAsset = asset.withProps({
103
82
  size: buffer.length
104
83
  });
105
- newAsset.setContentsReader(CallableContentsReader.create(()=>buffer));
84
+ newAsset.setContentsReader(__rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.CallableContentsReader.create(()=>buffer));
106
85
  return newAsset;
107
86
  } catch {
108
87
  console.log("Create an optimized version of the original asset", asset.getKey());
109
- let buffer = await asset.getContents();
110
- const framed = await extractFramedRegion(buffer, framing);
111
- const cropped = framed !== buffer;
112
- buffer = framed;
88
+ const buffer = await asset.getContents();
113
89
  const optimizationMap = {
114
90
  "image/png": (buffer)=>this.optimizePng(buffer),
115
91
  "image/jpeg": (buffer)=>this.optimizeJpeg(buffer),
116
92
  "image/jpg": (buffer)=>this.optimizeJpeg(buffer)
117
93
  };
118
94
  const optimization = optimizationMap[asset.getContentType()];
119
- if (!optimization && !cropped) {
95
+ if (!optimization) {
120
96
  console.log(`No optimizations defined for ${asset.getContentType()}`);
121
97
  return asset;
122
98
  }
123
- const finalBuffer = optimization ? await optimization(buffer).toBuffer() : buffer;
124
- console.log("Optimized asset size", finalBuffer.length);
99
+ const optimizedBuffer = await optimization(buffer).toBuffer();
100
+ console.log("Optimized asset size", optimizedBuffer.length);
125
101
  const newAsset = asset.withProps({
126
- size: finalBuffer.length
102
+ size: optimizedBuffer.length
127
103
  });
128
- newAsset.setContentsReader(CallableContentsReader.create(()=>finalBuffer));
104
+ newAsset.setContentsReader(__rspack_external__webiny_api_file_manager_features_assetDelivery_transformation_index_js_08a35114.CallableContentsReader.create(()=>optimizedBuffer));
129
105
  await promises.mkdir(node_path.dirname(optimizedFilePath), {
130
106
  recursive: true
131
107
  });
@@ -160,15 +136,13 @@ class LocalSharpTransform {
160
136
  });
161
137
  }
162
138
  }
163
- const LocalSharpTransformImpl = ImageAssetTypeHandler.createImplementation({
164
- implementation: LocalSharpTransform,
139
+ const LocalSharpTransform = AssetTransformationStrategy.createImplementation({
140
+ implementation: AssetTransformationStrategyImpl,
165
141
  dependencies: [
166
- LocalStoragePath,
167
- LocalAssetDeliveryConfig,
168
- IdentityContext,
169
- GetFileUseCase
142
+ FileManagerServerConfig,
143
+ LocalAssetDeliveryConfig
170
144
  ]
171
145
  });
172
- export { LocalSharpTransform, LocalSharpTransformImpl };
146
+ export { LocalSharpTransform };
173
147
 
174
148
  //# sourceMappingURL=LocalSharpTransform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assetDelivery/LocalSharpTransform.js","sources":["../../src/assetDelivery/LocalSharpTransform.ts"],"sourcesContent":["import sharp from \"sharp\";\nimport type { Sharp } from \"sharp\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\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 {\n extractFramedRegion,\n transformImageBuffer\n} from \"@webiny/api-file-manager/features/assetDelivery/assetTypes/image/transformImage.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 { IAssetTypeHandler } from \"@webiny/api-file-manager/features/assetDelivery/abstractions/AssetType.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 { LocalStoragePath } from \"~/assetDelivery/abstractions.js\";\nimport { LocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport type { ILocalAssetDeliveryConfig } 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 LocalSharpTransform implements IAssetTypeHandler {\n private readonly storagePath: 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\n constructor(\n storagePath: string,\n config: ILocalAssetDeliveryConfig,\n identityContext: IdentityContext.Interface,\n getFile: GetFileUseCase.Interface\n ) {\n this.storagePath = storagePath;\n this.imageResizeWidths = config.imageResizeWidths;\n this.imageQuality = { ...DEFAULT_IMAGE_QUALITY, ...(config.imageQuality ?? {}) };\n this.identityContext = identityContext;\n this.getFile = getFile;\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?.imageEdit 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 const transformedFilePath = path.join(this.storagePath, transformedAssetKey);\n\n const contentType = options.format\n ? contentTypeForFormat(options.format)\n : asset.getContentType();\n\n try {\n const buffer = await fs.readFile(transformedFilePath);\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 { buffer: transformedBuffer, contentType: outputContentType } =\n await transformImageBuffer({\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 fs.mkdir(path.dirname(transformedFilePath), { recursive: true });\n await fs.writeFile(transformedFilePath, await newAsset.getContents());\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 const optimizedFilePath = path.join(this.storagePath, optimizedAssetKey);\n\n try {\n const buffer = await fs.readFile(optimizedFilePath);\n\n console.log(\"Return a previously optimized asset\", optimizedAssetKey);\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 framed = await extractFramedRegion(buffer, framing);\n const cropped = framed !== buffer;\n buffer = framed;\n\n const optimizationMap: Record<string, ((buffer: Buffer) => 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 && !cropped) {\n console.log(`No optimizations defined for ${asset.getContentType()}`);\n return asset;\n }\n\n const finalBuffer = optimization ? await optimization(buffer).toBuffer() : buffer;\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 fs.mkdir(path.dirname(optimizedFilePath), { recursive: true });\n await fs.writeFile(optimizedFilePath, await newAsset.getContents());\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\nexport const LocalSharpTransformImpl = ImageAssetTypeHandler.createImplementation({\n implementation: LocalSharpTransform,\n dependencies: [LocalStoragePath, LocalAssetDeliveryConfig, IdentityContext, GetFileUseCase]\n});\n"],"names":["hasTransform","options","undefined","LocalSharpTransform","storagePath","config","identityContext","getFile","DEFAULT_IMAGE_QUALITY","assetRequest","asset","rawQuery","acceptHeader","original","crop","focal","aspectRatio","normalizeImageOptions","assetCrop","framing","transformedAsset","fileId","result","imageEdit","assetKey","AssetKeyGenerator","transformedAssetKey","transformedFilePath","path","contentType","contentTypeForFormat","buffer","fs","newAsset","CallableContentsReader","console","optimizedImage","baseBuffer","transformedBuffer","outputContentType","transformImageBuffer","optimizedAssetKey","optimizedFilePath","framed","extractFramedRegion","cropped","optimizationMap","optimization","finalBuffer","sharp","LocalSharpTransformImpl","ImageAssetTypeHandler","LocalStoragePath","LocalAssetDeliveryConfig","IdentityContext","GetFileUseCase"],"mappings":"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"}
1
+ {"version":3,"file":"assetDelivery/LocalSharpTransform.js","sources":["../../src/assetDelivery/LocalSharpTransform.ts"],"sourcesContent":["import sharp from \"sharp\";\nimport type { Sharp } from \"sharp\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AssetRequestOptions } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { AssetTransformationStrategy as AssetTransformationStrategyAbstraction } from \"@webiny/api-file-manager/exports/api/file-manager/assetDelivery.js\";\nimport { WidthCollection } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport * as utils from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport { CallableContentsReader } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport { AssetKeyGenerator } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\nimport { LocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\nimport type { ILocalAssetDeliveryConfig } from \"~/assetDelivery/abstractions.js\";\n\nclass AssetTransformationStrategyImpl implements AssetTransformationStrategyAbstraction.Interface {\n private readonly storagePath: string;\n private readonly imageResizeWidths: number[];\n\n constructor(\n serverConfig: FileManagerServerConfig.Interface,\n config: ILocalAssetDeliveryConfig\n ) {\n this.storagePath = serverConfig.storagePath;\n this.imageResizeWidths = config.imageResizeWidths;\n }\n\n async transform(\n assetRequest: AssetTransformationStrategyAbstraction.AssetRequest,\n asset: AssetTransformationStrategyAbstraction.Asset\n ): Promise<AssetTransformationStrategyAbstraction.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 // 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 return this.transformAsset(transformedAsset, options);\n }\n\n return this.optimizeAsset(transformedAsset);\n }\n\n private async transformAsset(\n asset: AssetTransformationStrategyAbstraction.Asset,\n options: Omit<AssetRequestOptions, \"original\">\n ) {\n if (options.width) {\n const assetKey = AssetKeyGenerator.create(asset);\n const transformedAssetKey = assetKey.getTransformedImageKey(options);\n const transformedFilePath = path.join(this.storagePath, transformedAssetKey);\n\n try {\n const buffer = await fs.readFile(transformedFilePath);\n\n const newAsset = asset.withProps({ size: buffer.length });\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);\n\n const widths = WidthCollection.create(this.imageResizeWidths);\n const width = widths.getClosestOrMax(options.width);\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 const newAsset = asset.withProps({ size: transformedBuffer.length });\n newAsset.setContentsReader(CallableContentsReader.create(() => transformedBuffer));\n\n await fs.mkdir(path.dirname(transformedFilePath), { recursive: true });\n await fs.writeFile(transformedFilePath, await newAsset.getContents());\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: AssetTransformationStrategyAbstraction.Asset) {\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);\n const optimizedAssetKey = assetKey.getOptimizedImageKey();\n const optimizedFilePath = path.join(this.storagePath, optimizedAssetKey);\n\n try {\n const buffer = await fs.readFile(optimizedFilePath);\n\n console.log(\"Return a previously optimized asset\", optimizedAssetKey);\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 const buffer = await asset.getContents();\n\n const optimizationMap: Record<string, ((buffer: Buffer) => 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(CallableContentsReader.create(() => optimizedBuffer));\n\n await fs.mkdir(path.dirname(optimizedFilePath), { recursive: true });\n await fs.writeFile(optimizedFilePath, await newAsset.getContents());\n\n return newAsset;\n }\n }\n\n private isAssetAnimated(asset: AssetTransformationStrategyAbstraction.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\nexport const LocalSharpTransform = AssetTransformationStrategyAbstraction.createImplementation({\n implementation: AssetTransformationStrategyImpl,\n dependencies: [FileManagerServerConfig, LocalAssetDeliveryConfig]\n});\n"],"names":["AssetTransformationStrategyImpl","serverConfig","config","assetRequest","asset","utils","console","original","options","transformedAsset","Object","assetKey","AssetKeyGenerator","transformedAssetKey","transformedFilePath","path","buffer","fs","newAsset","CallableContentsReader","optimizedImage","widths","WidthCollection","width","transformedBuffer","sharp","optimizedAssetKey","optimizedFilePath","optimizationMap","optimization","optimizedBuffer","LocalSharpTransform","AssetTransformationStrategyAbstraction","FileManagerServerConfig","LocalAssetDeliveryConfig"],"mappings":"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"}
@@ -1,8 +1,5 @@
1
- import type { ImageFormat } from "@webiny/api-file-manager/features/assetDelivery/transformation/index.js";
2
1
  export interface ILocalAssetDeliveryConfig {
3
2
  imageResizeWidths: number[];
4
- imageQuality?: Partial<Record<ImageFormat, number>>;
5
3
  assetStreamingMaxSize: number;
6
4
  }
7
5
  export declare const LocalAssetDeliveryConfig: import("@webiny/di").Abstraction<ILocalAssetDeliveryConfig>;
8
- export declare const LocalStoragePath: import("@webiny/di").Abstraction<string>;
@@ -1,6 +1,5 @@
1
1
  import { createAbstraction } from "@webiny/feature/api";
2
2
  const LocalAssetDeliveryConfig = createAbstraction("AssetDelivery/LocalConfig");
3
- const LocalStoragePath = createAbstraction("AssetDelivery/LocalStoragePath");
4
- export { LocalAssetDeliveryConfig, LocalStoragePath };
3
+ export { LocalAssetDeliveryConfig };
5
4
 
6
5
  //# sourceMappingURL=abstractions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assetDelivery/abstractions.js","sources":["../../src/assetDelivery/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { ImageFormat } from \"@webiny/api-file-manager/features/assetDelivery/transformation/index.js\";\n\nexport interface ILocalAssetDeliveryConfig {\n imageResizeWidths: number[];\n imageQuality?: Partial<Record<ImageFormat, number>>;\n assetStreamingMaxSize: number;\n}\n\nexport const LocalAssetDeliveryConfig = createAbstraction<ILocalAssetDeliveryConfig>(\n \"AssetDelivery/LocalConfig\"\n);\n\nexport const LocalStoragePath = createAbstraction<string>(\"AssetDelivery/LocalStoragePath\");\n"],"names":["LocalAssetDeliveryConfig","createAbstraction","LocalStoragePath"],"mappings":";AASO,MAAMA,2BAA2BC,kBACpC;AAGG,MAAMC,mBAAmBD,kBAA0B"}
1
+ {"version":3,"file":"assetDelivery/abstractions.js","sources":["../../src/assetDelivery/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\n\nexport interface ILocalAssetDeliveryConfig {\n imageResizeWidths: number[];\n assetStreamingMaxSize: number;\n}\n\nexport const LocalAssetDeliveryConfig = createAbstraction<ILocalAssetDeliveryConfig>(\n \"AssetDelivery/LocalConfig\"\n);\n"],"names":["LocalAssetDeliveryConfig","createAbstraction"],"mappings":";AAOO,MAAMA,2BAA2BC,kBACpC"}
@@ -1,2 +1,2 @@
1
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>)[];
2
+ export declare const assetDeliveryConfig: (params: AssetDeliveryParams) => (import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types").Context>[] | import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types").Context>)[];
@@ -1,12 +1,11 @@
1
1
  import { createFeature } from "@webiny/feature/api";
2
- import { LocalAssetDeliveryConfig, LocalStoragePath } from "./abstractions.js";
3
- import { LocalAssetResolverImpl } from "./LocalAssetResolver.js";
4
- import { LocalOutputStrategyImpl } from "./LocalOutputStrategy.js";
5
- import { LocalSharpTransformImpl } from "./LocalSharpTransform.js";
2
+ import { LocalAssetDeliveryConfig } from "./abstractions.js";
3
+ import { LocalAssetResolver } from "./LocalAssetResolver.js";
4
+ import { LocalOutputStrategy } from "./LocalOutputStrategy.js";
5
+ import { LocalSharpTransform } from "./LocalSharpTransform.js";
6
6
  const createLocalAssetDeliveryFeature = (params = {})=>createFeature({
7
7
  name: "AssetDelivery/Local",
8
8
  register (container) {
9
- container.registerInstance(LocalStoragePath, process.env.WEBINY_LOCAL_STORAGE_PATH);
10
9
  container.registerInstance(LocalAssetDeliveryConfig, {
11
10
  imageResizeWidths: params.imageResizeWidths ?? [
12
11
  128,
@@ -20,12 +19,11 @@ const createLocalAssetDeliveryFeature = (params = {})=>createFeature({
20
19
  2048,
21
20
  3840
22
21
  ],
23
- imageQuality: params.imageQuality ?? {},
24
22
  assetStreamingMaxSize: params.assetStreamingMaxSize ?? 4718592
25
23
  });
26
- container.register(LocalAssetResolverImpl);
27
- container.register(LocalOutputStrategyImpl);
28
- container.register(LocalSharpTransformImpl).inSingletonScope();
24
+ container.register(LocalAssetResolver);
25
+ container.register(LocalOutputStrategy);
26
+ container.register(LocalSharpTransform);
29
27
  }
30
28
  });
31
29
  export { createLocalAssetDeliveryFeature };
@@ -1 +1 @@
1
- {"version":3,"file":"assetDelivery/feature.js","sources":["../../src/assetDelivery/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { LocalStoragePath } from \"./abstractions.js\";\nimport { LocalAssetDeliveryConfig } from \"./abstractions.js\";\nimport type { AssetDeliveryParams } from \"./types.js\";\nimport { LocalAssetResolverImpl } from \"./LocalAssetResolver.js\";\nimport { LocalOutputStrategyImpl } from \"./LocalOutputStrategy.js\";\nimport { LocalSharpTransformImpl } from \"./LocalSharpTransform.js\";\n\nexport const createLocalAssetDeliveryFeature = (params: AssetDeliveryParams = {}) => {\n return createFeature({\n name: \"AssetDelivery/Local\",\n register(container) {\n container.registerInstance(\n LocalStoragePath,\n process.env.WEBINY_LOCAL_STORAGE_PATH as string\n );\n container.registerInstance(LocalAssetDeliveryConfig, {\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(LocalAssetResolverImpl);\n container.register(LocalOutputStrategyImpl);\n container.register(LocalSharpTransformImpl).inSingletonScope();\n }\n });\n};\n"],"names":["createLocalAssetDeliveryFeature","params","createFeature","container","LocalStoragePath","process","LocalAssetDeliveryConfig","LocalAssetResolverImpl","LocalOutputStrategyImpl","LocalSharpTransformImpl"],"mappings":";;;;;AAQO,MAAMA,kCAAkC,CAACC,SAA8B,CAAC,CAAC,GACrEC,cAAc;QACjB,MAAM;QACN,UAASC,SAAS;YACdA,UAAU,gBAAgB,CACtBC,kBACAC,QAAQ,GAAG,CAAC,yBAAyB;YAEzCF,UAAU,gBAAgB,CAACG,0BAA0B;gBACjD,mBAAmBL,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,CAACI;YACnBJ,UAAU,QAAQ,CAACK;YACnBL,UAAU,QAAQ,CAACM,yBAAyB,gBAAgB;QAChE;IACJ"}
1
+ {"version":3,"file":"assetDelivery/feature.js","sources":["../../src/assetDelivery/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { LocalAssetDeliveryConfig } from \"./abstractions.js\";\nimport type { AssetDeliveryParams } from \"./types.js\";\nimport { LocalAssetResolver } from \"./LocalAssetResolver.js\";\nimport { LocalOutputStrategy } from \"./LocalOutputStrategy.js\";\nimport { LocalSharpTransform } from \"./LocalSharpTransform.js\";\n\nexport const createLocalAssetDeliveryFeature = (params: AssetDeliveryParams = {}) => {\n return createFeature({\n name: \"AssetDelivery/Local\",\n register(container) {\n container.registerInstance(LocalAssetDeliveryConfig, {\n imageResizeWidths: params.imageResizeWidths ?? [\n 128, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840\n ],\n assetStreamingMaxSize: params.assetStreamingMaxSize ?? 4718592\n });\n\n container.register(LocalAssetResolver);\n container.register(LocalOutputStrategy);\n container.register(LocalSharpTransform);\n }\n });\n};\n"],"names":["createLocalAssetDeliveryFeature","params","createFeature","container","LocalAssetDeliveryConfig","LocalAssetResolver","LocalOutputStrategy","LocalSharpTransform"],"mappings":";;;;;AAOO,MAAMA,kCAAkC,CAACC,SAA8B,CAAC,CAAC,GACrEC,cAAc;QACjB,MAAM;QACN,UAASC,SAAS;YACdA,UAAU,gBAAgB,CAACC,0BAA0B;gBACjD,mBAAmBH,OAAO,iBAAiB,IAAI;oBAC3C;oBAAK;oBAAK;oBAAK;oBAAK;oBAAK;oBAAM;oBAAM;oBAAM;oBAAM;iBACpD;gBACD,uBAAuBA,OAAO,qBAAqB,IAAI;YAC3D;YAEAE,UAAU,QAAQ,CAACE;YACnBF,UAAU,QAAQ,CAACG;YACnBH,UAAU,QAAQ,CAACI;QACvB;IACJ"}