@webiny/api-file-manager-s3 6.4.12-beta.5 → 6.5.0-beta.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 (138) hide show
  1. package/assetDelivery/abstractions.d.ts +2 -0
  2. package/assetDelivery/abstractions.js.map +1 -1
  3. package/assetDelivery/assetDeliveryConfig.d.ts +1 -1
  4. package/assetDelivery/createAssetDelivery.js +1 -1
  5. package/assetDelivery/createAssetDelivery.js.map +1 -1
  6. package/assetDelivery/feature.js +2 -1
  7. package/assetDelivery/feature.js.map +1 -1
  8. package/assetDelivery/index.d.ts +1 -2
  9. package/assetDelivery/index.js +1 -2
  10. package/assetDelivery/s3/S3AssetResolver.d.ts +10 -9
  11. package/assetDelivery/s3/S3AssetResolver.js +10 -8
  12. package/assetDelivery/s3/S3AssetResolver.js.map +1 -1
  13. package/assetDelivery/s3/S3ContentsReader.d.ts +6 -5
  14. package/assetDelivery/s3/S3ContentsReader.js +3 -0
  15. package/assetDelivery/s3/S3ContentsReader.js.map +1 -1
  16. package/assetDelivery/s3/S3ErrorAssetReply.d.ts +3 -2
  17. package/assetDelivery/s3/S3ErrorAssetReply.js +4 -1
  18. package/assetDelivery/s3/S3ErrorAssetReply.js.map +1 -1
  19. package/assetDelivery/s3/S3OutputStrategy.d.ts +8 -6
  20. package/assetDelivery/s3/S3OutputStrategy.js +6 -5
  21. package/assetDelivery/s3/S3OutputStrategy.js.map +1 -1
  22. package/assetDelivery/s3/S3RedirectAssetReply.d.ts +1 -1
  23. package/assetDelivery/s3/S3RedirectAssetReply.js +1 -1
  24. package/assetDelivery/s3/S3RedirectAssetReply.js.map +1 -1
  25. package/assetDelivery/s3/SharpTransform.d.ts +13 -5
  26. package/assetDelivery/s3/SharpTransform.js +98 -74
  27. package/assetDelivery/s3/SharpTransform.js.map +1 -1
  28. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.d.ts +1 -1
  29. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js +4 -3
  30. package/assetDelivery/threatDetection/createThreatDetectionEventHandler.js.map +1 -1
  31. package/assetDelivery/threatDetection/processThreatScanResult.js +10 -8
  32. package/assetDelivery/threatDetection/processThreatScanResult.js.map +1 -1
  33. package/assetDelivery/types.d.ts +3 -0
  34. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +8 -0
  35. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +51 -0
  36. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -0
  37. package/features/CompleteMultiPartUpload/feature.d.ts +4 -0
  38. package/features/CompleteMultiPartUpload/feature.js +11 -0
  39. package/features/CompleteMultiPartUpload/feature.js.map +1 -0
  40. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +9 -0
  41. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +40 -0
  42. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -0
  43. package/features/CreateMultiPartUpload/feature.d.ts +4 -0
  44. package/features/CreateMultiPartUpload/feature.js +11 -0
  45. package/features/CreateMultiPartUpload/feature.js.map +1 -0
  46. package/features/DeleteFileFromBucket/DeleteS3FolderTask.d.ts +1 -1
  47. package/features/ExtractMetadata/ExtractMetadataHandler.d.ts +1 -11
  48. package/features/ExtractMetadata/ExtractMetadataHandler.js +1 -25
  49. package/features/ExtractMetadata/ExtractMetadataTask.d.ts +15 -17
  50. package/features/ExtractMetadata/ExtractMetadataTask.js +8 -10
  51. package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
  52. package/features/FlushCache/InvalidateCacheTask.d.ts +2 -2
  53. package/features/FlushCache/InvalidateCacheTask.js +1 -1
  54. package/features/FlushCache/InvalidateCacheTask.js.map +1 -1
  55. package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +3 -3
  56. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +4 -5
  57. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -1
  58. package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +14 -0
  59. package/features/GetUploadPayload/GetUploadPayloadUseCase.js +54 -0
  60. package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -0
  61. package/features/{WriteFileMetadata → GetUploadPayload}/feature.d.ts +1 -1
  62. package/features/GetUploadPayload/feature.js +11 -0
  63. package/features/GetUploadPayload/feature.js.map +1 -0
  64. package/index.d.ts +2 -2
  65. package/index.js +8 -6
  66. package/index.js.map +1 -1
  67. package/package.json +18 -24
  68. package/types.d.ts +2 -20
  69. package/utils/uploadFileToS3.d.ts +1 -1
  70. package/assetDelivery/s3/S3StreamAssetReply.d.ts +0 -5
  71. package/assetDelivery/s3/S3StreamAssetReply.js +0 -17
  72. package/assetDelivery/s3/S3StreamAssetReply.js.map +0 -1
  73. package/assetDelivery/s3/transformation/AssetKeyGenerator.d.ts +0 -8
  74. package/assetDelivery/s3/transformation/AssetKeyGenerator.js +0 -21
  75. package/assetDelivery/s3/transformation/AssetKeyGenerator.js.map +0 -1
  76. package/assetDelivery/s3/transformation/CallableContentsReader.d.ts +0 -10
  77. package/assetDelivery/s3/transformation/CallableContentsReader.js +0 -11
  78. package/assetDelivery/s3/transformation/CallableContentsReader.js.map +0 -1
  79. package/assetDelivery/s3/transformation/WidthCollection.d.ts +0 -7
  80. package/assetDelivery/s3/transformation/WidthCollection.js +0 -19
  81. package/assetDelivery/s3/transformation/WidthCollection.js.map +0 -1
  82. package/assetDelivery/s3/transformation/utils.d.ts +0 -9
  83. package/assetDelivery/s3/transformation/utils.js +0 -31
  84. package/assetDelivery/s3/transformation/utils.js.map +0 -1
  85. package/assetDelivery/threatDetection/ObjectKey.d.ts +0 -7
  86. package/assetDelivery/threatDetection/ObjectKey.js +0 -18
  87. package/assetDelivery/threatDetection/ObjectKey.js.map +0 -1
  88. package/features/ExtractMetadata/ExtractMetadataHandler.js.map +0 -1
  89. package/features/WriteFileMetadata/MetadataReader.d.ts +0 -14
  90. package/features/WriteFileMetadata/MetadataReader.js +0 -13
  91. package/features/WriteFileMetadata/MetadataReader.js.map +0 -1
  92. package/features/WriteFileMetadata/MetadataWriter.d.ts +0 -10
  93. package/features/WriteFileMetadata/MetadataWriter.js +0 -26
  94. package/features/WriteFileMetadata/MetadataWriter.js.map +0 -1
  95. package/features/WriteFileMetadata/WriteMetadataAfterBatchCreateHandler.d.ts +0 -12
  96. package/features/WriteFileMetadata/WriteMetadataAfterBatchCreateHandler.js +0 -23
  97. package/features/WriteFileMetadata/WriteMetadataAfterBatchCreateHandler.js.map +0 -1
  98. package/features/WriteFileMetadata/WriteMetadataAfterCreateHandler.d.ts +0 -12
  99. package/features/WriteFileMetadata/WriteMetadataAfterCreateHandler.js +0 -25
  100. package/features/WriteFileMetadata/WriteMetadataAfterCreateHandler.js.map +0 -1
  101. package/features/WriteFileMetadata/feature.js +0 -13
  102. package/features/WriteFileMetadata/feature.js.map +0 -1
  103. package/graphql/checkPermissions.d.ts +0 -5
  104. package/graphql/checkPermissions.js +0 -22
  105. package/graphql/checkPermissions.js.map +0 -1
  106. package/graphql/schema.d.ts +0 -1
  107. package/graphql/schema.js +0 -203
  108. package/graphql/schema.js.map +0 -1
  109. package/multiPartUpload/CompleteMultiPartUploadUseCase.d.ts +0 -15
  110. package/multiPartUpload/CompleteMultiPartUploadUseCase.js +0 -55
  111. package/multiPartUpload/CompleteMultiPartUploadUseCase.js.map +0 -1
  112. package/multiPartUpload/CreateMultiPartUploadUseCase.d.ts +0 -20
  113. package/multiPartUpload/CreateMultiPartUploadUseCase.js +0 -34
  114. package/multiPartUpload/CreateMultiPartUploadUseCase.js.map +0 -1
  115. package/utils/FileExtension.d.ts +0 -6
  116. package/utils/FileExtension.js +0 -16
  117. package/utils/FileExtension.js.map +0 -1
  118. package/utils/FileKey.d.ts +0 -11
  119. package/utils/FileKey.js +0 -33
  120. package/utils/FileKey.js.map +0 -1
  121. package/utils/FileKey.test.d.ts +0 -1
  122. package/utils/FileKey.test.js +0 -59
  123. package/utils/FileKey.test.js.map +0 -1
  124. package/utils/FileNormalizer.d.ts +0 -18
  125. package/utils/FileNormalizer.js +0 -41
  126. package/utils/FileNormalizer.js.map +0 -1
  127. package/utils/FileUploadModifier.d.ts +0 -30
  128. package/utils/FileUploadModifier.js +0 -39
  129. package/utils/FileUploadModifier.js.map +0 -1
  130. package/utils/createFileNormalizerFromContext.d.ts +0 -3
  131. package/utils/createFileNormalizerFromContext.js +0 -9
  132. package/utils/createFileNormalizerFromContext.js.map +0 -1
  133. package/utils/getPresignedPostPayload.d.ts +0 -4
  134. package/utils/getPresignedPostPayload.js +0 -43
  135. package/utils/getPresignedPostPayload.js.map +0 -1
  136. package/utils/mimeTypes.d.ts +0 -5
  137. package/utils/mimeTypes.js +0 -9
  138. package/utils/mimeTypes.js.map +0 -1
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { CreateMultiPartUploadUseCaseImplementation } from "./CreateMultiPartUploadUseCase.js";
3
+ const CreateMultiPartUploadFeature = createFeature({
4
+ name: "FileManagerS3/CreateMultiPartUpload",
5
+ register (container) {
6
+ container.register(CreateMultiPartUploadUseCaseImplementation);
7
+ }
8
+ });
9
+ export { CreateMultiPartUploadFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/CreateMultiPartUpload/feature.js","sources":["../../../src/features/CreateMultiPartUpload/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CreateMultiPartUploadUseCaseImplementation } from \"./CreateMultiPartUploadUseCase.js\";\n\nexport const CreateMultiPartUploadFeature = createFeature({\n name: \"FileManagerS3/CreateMultiPartUpload\",\n register(container) {\n container.register(CreateMultiPartUploadUseCaseImplementation);\n }\n});\n"],"names":["CreateMultiPartUploadFeature","createFeature","container","CreateMultiPartUploadUseCaseImplementation"],"mappings":";;AAGO,MAAMA,+BAA+BC,cAAc;IACtD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
@@ -23,7 +23,7 @@ declare class DeleteS3FolderTask implements TaskDefinition.Interface<DeleteS3Fol
23
23
  description: string;
24
24
  maxIterations: number;
25
25
  isPrivate: boolean;
26
- readonly selfCleanup: ("onSuccess" | "onAbort")[];
26
+ readonly selfCleanup: ("onAbort" | "onSuccess")[];
27
27
  run({ input, controller }: TaskDefinition.RunParams<DeleteS3FolderInput>): Promise<TaskDefinition.Result<DeleteS3FolderInput>>;
28
28
  }
29
29
  export declare const DeleteS3FolderTaskDefinition: typeof DeleteS3FolderTask & {
@@ -1,11 +1 @@
1
- import { FileAfterCreateEventHandler } from "@webiny/api-file-manager/features/file/CreateFile/events.js";
2
- import { TaskService } from "@webiny/api-core/features/task/TaskService/index.js";
3
- declare class ExtractMetadataHandlerImpl implements FileAfterCreateEventHandler.Interface {
4
- private taskService;
5
- constructor(taskService: TaskService.Interface);
6
- handle(event: FileAfterCreateEventHandler.Event): Promise<void>;
7
- }
8
- export declare const ExtractMetadataHandler: typeof ExtractMetadataHandlerImpl & {
9
- __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/eventPublisher/abstractions.js").IEventHandler<import("@webiny/api-file-manager/features/file/CreateFile/events.js").FileAfterCreateEvent>>;
10
- };
11
- export {};
1
+ export { ExtractMetadataHandler } from "@webiny/api-file-manager/features/extractMetadata/ExtractMetadataHandler.js";
@@ -1,25 +1 @@
1
- import { FileAfterCreateEventHandler } from "@webiny/api-file-manager/features/file/CreateFile/events.js";
2
- import { TaskService } from "@webiny/api-core/features/task/TaskService/index.js";
3
- class ExtractMetadataHandlerImpl {
4
- constructor(taskService){
5
- this.taskService = taskService;
6
- }
7
- async handle(event) {
8
- const { file } = event.payload;
9
- await this.taskService.trigger({
10
- definition: "fileManagerExtractMetadata",
11
- input: {
12
- fileId: file.id
13
- }
14
- });
15
- }
16
- }
17
- const ExtractMetadataHandler = FileAfterCreateEventHandler.createImplementation({
18
- implementation: ExtractMetadataHandlerImpl,
19
- dependencies: [
20
- TaskService
21
- ]
22
- });
23
- export { ExtractMetadataHandler };
24
-
25
- //# sourceMappingURL=ExtractMetadataHandler.js.map
1
+ export { ExtractMetadataHandler } from "@webiny/api-file-manager/features/extractMetadata/ExtractMetadataHandler.js";
@@ -1,24 +1,22 @@
1
1
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
- import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
3
2
  import { UpdateFileUseCase } from "@webiny/api-file-manager/features/file/UpdateFile/index.js";
4
- export interface ExtractMetadataInput {
5
- fileId: string;
6
- }
7
- declare class ExtractMetadataTask implements TaskDefinition.Interface<ExtractMetadataInput> {
8
- private keyValueStore;
9
- private updateFileUseCase;
10
- id: string;
11
- title: string;
12
- description: string;
13
- maxIterations: number;
14
- isPrivate: boolean;
15
- databaseLogs: boolean;
16
- selfCleanup: ("onSuccess" | "onAbort")[];
17
- constructor(keyValueStore: GlobalKeyValueStore.Interface, updateFileUseCase: UpdateFileUseCase.Interface);
3
+ import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
4
+ import type { ExtractMetadataInput } from "@webiny/api-file-manager/features/extractMetadata/ExtractMetadataInput.js";
5
+ declare class ExtractMetadataTaskImpl implements TaskDefinition.Interface<ExtractMetadataInput> {
6
+ private readonly metadataReader;
7
+ private readonly updateFileUseCase;
8
+ readonly id = "fileManagerExtractMetadata";
9
+ readonly title = "Extract image metadata (dimensions, EXIF, IPTC)";
10
+ readonly description = "A task to extract metadata from uploaded image files";
11
+ readonly maxIterations = 1;
12
+ readonly isPrivate = true;
13
+ readonly databaseLogs = false;
14
+ readonly selfCleanup: ("onAbort" | "onSuccess")[];
15
+ constructor(metadataReader: MetadataReader.Interface, updateFileUseCase: UpdateFileUseCase.Interface);
18
16
  run({ input, controller }: TaskDefinition.RunParams<ExtractMetadataInput>): Promise<TaskDefinition.Result<ExtractMetadataInput>>;
19
17
  private cleanValues;
20
18
  }
21
- export declare const ExtractMetadataTaskDefinition: typeof ExtractMetadataTask & {
22
- __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions.js").ITaskDefinition<import("@webiny/api-core/features/task/TaskDefinition/abstractions.js").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions.js").ITaskOutput>>;
19
+ export declare const ExtractMetadataTaskDefinition: typeof ExtractMetadataTaskImpl & {
20
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskDefinition<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
23
21
  };
24
22
  export {};
@@ -1,11 +1,10 @@
1
1
  import { S3 } from "@webiny/aws-sdk/client-s3/index.js";
2
2
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
3
- import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
4
3
  import { UpdateFileUseCase } from "@webiny/api-file-manager/features/file/UpdateFile/index.js";
5
- import { MetadataReader } from "../WriteFileMetadata/MetadataReader.js";
6
- class ExtractMetadataTask {
7
- constructor(keyValueStore, updateFileUseCase){
8
- this.keyValueStore = keyValueStore;
4
+ import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
5
+ class ExtractMetadataTaskImpl {
6
+ constructor(metadataReader, updateFileUseCase){
7
+ this.metadataReader = metadataReader;
9
8
  this.updateFileUseCase = updateFileUseCase;
10
9
  this.id = "fileManagerExtractMetadata";
11
10
  this.title = "Extract image metadata (dimensions, EXIF, IPTC)";
@@ -20,8 +19,7 @@ class ExtractMetadataTask {
20
19
  }
21
20
  async run({ input, controller }) {
22
21
  if (controller.runtime.isAborted()) return controller.response.aborted();
23
- const metadataReader = new MetadataReader(this.keyValueStore);
24
- const fileMetadata = await metadataReader.read(input.fileId);
22
+ const fileMetadata = await this.metadataReader.read(input.fileId);
25
23
  if (!fileMetadata) return controller.response.error({
26
24
  message: `File metadata not found for file ID: ${input.fileId}`
27
25
  });
@@ -36,9 +34,9 @@ class ExtractMetadataTask {
36
34
  if (!s3Object.Body) return controller.response.error({
37
35
  message: `S3 object body is empty for file: ${input.fileId}`
38
36
  });
37
+ const buffer = Buffer.from(await s3Object.Body.transformToByteArray());
39
38
  const sharp = await import("sharp").then((m)=>m.default);
40
39
  const ExifReader = await import("exifreader").then((m)=>m.default);
41
- const buffer = Buffer.from(await s3Object.Body.transformToByteArray());
42
40
  const sharpInstance = sharp(buffer);
43
41
  const sharpMetadata = await sharpInstance.metadata();
44
42
  const tags = ExifReader.load(buffer, {
@@ -79,9 +77,9 @@ class ExtractMetadataTask {
79
77
  }
80
78
  }
81
79
  const ExtractMetadataTaskDefinition = TaskDefinition.createImplementation({
82
- implementation: ExtractMetadataTask,
80
+ implementation: ExtractMetadataTaskImpl,
83
81
  dependencies: [
84
- GlobalKeyValueStore,
82
+ MetadataReader,
85
83
  UpdateFileUseCase
86
84
  ]
87
85
  });
@@ -1 +1 @@
1
- {"version":3,"file":"features/ExtractMetadata/ExtractMetadataTask.js","sources":["../../../src/features/ExtractMetadata/ExtractMetadataTask.ts"],"sourcesContent":["import type { ExifTags } from \"exifreader\";\nimport { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { UpdateFileUseCase } from \"@webiny/api-file-manager/features/file/UpdateFile/index.js\";\nimport { MetadataReader } from \"../WriteFileMetadata/MetadataReader.js\";\n\nexport interface ExtractMetadataInput {\n fileId: string;\n}\n\nclass ExtractMetadataTask implements TaskDefinition.Interface<ExtractMetadataInput> {\n id = \"fileManagerExtractMetadata\";\n title = \"Extract image metadata (dimensions, EXIF, IPTC)\";\n description = \"A task to extract metadata from uploaded image files\";\n maxIterations = 1;\n isPrivate = true;\n databaseLogs = false;\n\n selfCleanup = [\"onSuccess\" as const, \"onAbort\" as const];\n\n constructor(\n private keyValueStore: GlobalKeyValueStore.Interface,\n private updateFileUseCase: UpdateFileUseCase.Interface\n ) {}\n\n public async run({\n input,\n controller\n }: TaskDefinition.RunParams<ExtractMetadataInput>): Promise<\n TaskDefinition.Result<ExtractMetadataInput>\n > {\n if (controller.runtime.isAborted()) {\n return controller.response.aborted();\n }\n\n // Load file metadata\n const metadataReader = new MetadataReader(this.keyValueStore);\n const fileMetadata = await metadataReader.read(input.fileId);\n\n if (!fileMetadata) {\n return controller.response.error({\n message: `File metadata not found for file ID: ${input.fileId}`\n });\n }\n\n // Check if it's an image file\n if (!fileMetadata.contentType.startsWith(\"image/\")) {\n return controller.response.done();\n }\n\n // Fetch the image from S3\n const s3 = new S3();\n const bucket = String(process.env.S3_BUCKET);\n\n try {\n const s3Object = await s3.getObject({\n Bucket: bucket,\n Key: fileMetadata.bucketKey\n });\n\n if (!s3Object.Body) {\n return controller.response.error({\n message: `S3 object body is empty for file: ${input.fileId}`\n });\n }\n\n const sharp = await import(/* webpackChunkName: \"sharp\" */ \"sharp\").then(\n m => m.default\n );\n\n const ExifReader = await import(/* webpackChunkName: \"exifreader\" */ \"exifreader\").then(\n m => m.default\n );\n\n // Convert S3 body to buffer\n const buffer = Buffer.from(await s3Object.Body.transformToByteArray());\n\n // Extract metadata using Sharp for image dimensions\n const sharpInstance = sharp(buffer);\n const sharpMetadata = await sharpInstance.metadata();\n\n // Use ExifReader to extract EXIF and IPTC data\n const tags = ExifReader.load(buffer, { expanded: true });\n\n // Build metadata object\n const metadata: Record<string, any> = {\n image: {\n width: sharpMetadata.width,\n height: sharpMetadata.height,\n format: sharpMetadata.format,\n orientation: sharpMetadata.orientation ?? 1\n }\n };\n\n // Extract EXIF data if available\n if (tags.exif) {\n metadata.exif = this.cleanValues(tags.exif);\n }\n\n // Extract IPTC data if available\n if (tags.iptc) {\n metadata.iptc = this.cleanValues(tags.iptc);\n }\n\n // Update the file with extracted metadata\n const updateResult = await this.updateFileUseCase.execute({\n id: input.fileId,\n metadata\n });\n\n if (updateResult.isFail()) {\n return controller.response.error({\n message: `Failed to update file with metadata: ${updateResult.error.message}`\n });\n }\n\n return controller.response.done();\n } catch (error) {\n return controller.response.error({\n message: `Failed to extract metadata: ${\n error instanceof Error ? error.message : String(error)\n }`\n });\n }\n }\n\n private cleanValues(tags: ExifTags) {\n const cleaned: Record<string, any> = {};\n\n for (const [key, tag] of Object.entries(tags)) {\n if (!tag || typeof tag !== \"object\") {\n continue;\n }\n\n // Use description if available, otherwise value\n if (tag.description !== undefined && tag.description !== null) {\n cleaned[key] = tag.description;\n } else if (Array.isArray(tag.value) && tag.value.length > 20) {\n // Skip large byte arrays\n } else if (tag.value !== undefined) {\n cleaned[key] = tag.value;\n }\n }\n\n return cleaned;\n }\n}\n\nexport const ExtractMetadataTaskDefinition = TaskDefinition.createImplementation({\n implementation: ExtractMetadataTask,\n dependencies: [GlobalKeyValueStore, UpdateFileUseCase]\n});\n"],"names":["ExtractMetadataTask","keyValueStore","updateFileUseCase","input","controller","metadataReader","MetadataReader","fileMetadata","s3","S3","bucket","String","process","s3Object","sharp","m","ExifReader","buffer","Buffer","sharpInstance","sharpMetadata","tags","metadata","updateResult","error","Error","cleaned","key","tag","Object","undefined","Array","ExtractMetadataTaskDefinition","TaskDefinition","GlobalKeyValueStore","UpdateFileUseCase"],"mappings":"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"}
1
+ {"version":3,"file":"features/ExtractMetadata/ExtractMetadataTask.js","sources":["../../../src/features/ExtractMetadata/ExtractMetadataTask.ts"],"sourcesContent":["import type { ExifTags } from \"exifreader\";\nimport { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { UpdateFileUseCase } from \"@webiny/api-file-manager/features/file/UpdateFile/index.js\";\nimport { MetadataReader } from \"@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js\";\nimport type { ExtractMetadataInput } from \"@webiny/api-file-manager/features/extractMetadata/ExtractMetadataInput.js\";\n\nclass ExtractMetadataTaskImpl implements TaskDefinition.Interface<ExtractMetadataInput> {\n public readonly id = \"fileManagerExtractMetadata\";\n public readonly title = \"Extract image metadata (dimensions, EXIF, IPTC)\";\n public readonly description = \"A task to extract metadata from uploaded image files\";\n public readonly maxIterations = 1;\n public readonly isPrivate = true;\n public readonly databaseLogs = false;\n public readonly selfCleanup = [\"onSuccess\" as const, \"onAbort\" as const];\n\n public constructor(\n private readonly metadataReader: MetadataReader.Interface,\n private readonly updateFileUseCase: UpdateFileUseCase.Interface\n ) {}\n\n public async run({\n input,\n controller\n }: TaskDefinition.RunParams<ExtractMetadataInput>): Promise<\n TaskDefinition.Result<ExtractMetadataInput>\n > {\n if (controller.runtime.isAborted()) {\n return controller.response.aborted();\n }\n\n /* Load file metadata from the key-value store. */\n const fileMetadata = await this.metadataReader.read(input.fileId);\n\n if (!fileMetadata) {\n return controller.response.error({\n message: `File metadata not found for file ID: ${input.fileId}`\n });\n }\n\n /* Only process image files. */\n if (!fileMetadata.contentType.startsWith(\"image/\")) {\n return controller.response.done();\n }\n\n /* Fetch the image from S3. */\n const s3 = new S3();\n const bucket = String(process.env.S3_BUCKET);\n\n try {\n const s3Object = await s3.getObject({\n Bucket: bucket,\n Key: fileMetadata.bucketKey\n });\n\n if (!s3Object.Body) {\n return controller.response.error({\n message: `S3 object body is empty for file: ${input.fileId}`\n });\n }\n\n /* Convert S3 body to buffer. */\n const buffer = Buffer.from(await s3Object.Body.transformToByteArray());\n\n const sharp = await import(/* webpackChunkName: \"sharp\" */ \"sharp\").then(\n m => m.default\n );\n\n const ExifReader = await import(/* webpackChunkName: \"exifreader\" */ \"exifreader\").then(\n m => m.default\n );\n\n /* Extract image dimensions using Sharp. */\n const sharpInstance = sharp(buffer);\n const sharpMetadata = await sharpInstance.metadata();\n\n /* Use ExifReader to extract EXIF and IPTC data. */\n const tags = ExifReader.load(buffer, { expanded: true });\n\n /* Build metadata object. */\n const metadata: Record<string, unknown> = {\n image: {\n width: sharpMetadata.width,\n height: sharpMetadata.height,\n format: sharpMetadata.format,\n orientation: sharpMetadata.orientation ?? 1\n }\n };\n\n if (tags.exif) {\n metadata.exif = this.cleanValues(tags.exif);\n }\n\n if (tags.iptc) {\n metadata.iptc = this.cleanValues(tags.iptc);\n }\n const updateResult = await this.updateFileUseCase.execute({\n id: input.fileId,\n metadata\n });\n\n if (updateResult.isFail()) {\n return controller.response.error({\n message: `Failed to update file with metadata: ${updateResult.error.message}`\n });\n }\n\n return controller.response.done();\n } catch (error) {\n return controller.response.error({\n message: `Failed to extract metadata: ${\n error instanceof Error ? error.message : String(error)\n }`\n });\n }\n }\n\n private cleanValues(tags: ExifTags) {\n const cleaned: Record<string, unknown> = {};\n\n for (const [key, tag] of Object.entries(tags)) {\n if (!tag || typeof tag !== \"object\") {\n continue;\n }\n\n /* Use description if available, otherwise value. */\n if (tag.description !== undefined && tag.description !== null) {\n cleaned[key] = tag.description;\n } else if (Array.isArray(tag.value) && tag.value.length > 20) {\n /* Skip large byte arrays. */\n } else if (tag.value !== undefined) {\n cleaned[key] = tag.value;\n }\n }\n\n return cleaned;\n }\n}\n\nexport const ExtractMetadataTaskDefinition = TaskDefinition.createImplementation({\n implementation: ExtractMetadataTaskImpl,\n dependencies: [MetadataReader, UpdateFileUseCase]\n});\n"],"names":["ExtractMetadataTaskImpl","metadataReader","updateFileUseCase","input","controller","fileMetadata","s3","S3","bucket","String","process","s3Object","buffer","Buffer","sharp","m","ExifReader","sharpInstance","sharpMetadata","tags","metadata","updateResult","error","Error","cleaned","key","tag","Object","undefined","Array","ExtractMetadataTaskDefinition","TaskDefinition","MetadataReader","UpdateFileUseCase"],"mappings":"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"}
@@ -15,9 +15,9 @@ declare class InvalidateCloudfrontCacheTask implements TaskDefinition.Interface<
15
15
  description: string;
16
16
  maxIterations: number;
17
17
  isPrivate: boolean;
18
- selfCleanup: ("onSuccess" | "onAbort")[];
18
+ selfCleanup: ("onAbort" | "onSuccess")[];
19
19
  private continueIfCode;
20
- run({ input, controller }: TaskDefinition.RunParams<InvalidateCacheInput>): Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResultError | import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResultAborted | TaskDefinition.ResultDone<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput> | TaskDefinition.ResultContinue<InvalidateCacheInput>>;
20
+ run({ input, controller }: TaskDefinition.RunParams<InvalidateCacheInput>): Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResultAborted | import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResultError | TaskDefinition.ResultContinue<InvalidateCacheInput> | TaskDefinition.ResultDone<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
21
21
  private invalidateCache;
22
22
  }
23
23
  export declare const InvalidateCloudfrontCacheTaskDefinition: typeof InvalidateCloudfrontCacheTask & {
@@ -1,4 +1,4 @@
1
- import { ServiceDiscovery } from "@webiny/api";
1
+ import { ServiceDiscovery } from "@webiny/api-core/features/serviceDiscovery/index.js";
2
2
  import { CloudFront } from "@webiny/aws-sdk/client-cloudfront/index.js";
3
3
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
4
4
  import { executeWithRetry } from "@webiny/utils";
@@ -1 +1 @@
1
- {"version":3,"file":"features/FlushCache/InvalidateCacheTask.js","sources":["../../../src/features/FlushCache/InvalidateCacheTask.ts"],"sourcesContent":["import { ServiceDiscovery } from \"@webiny/api\";\nimport { CloudFront } from \"@webiny/aws-sdk/client-cloudfront/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { executeWithRetry } from \"@webiny/utils\";\n\nclass ReturnContinue extends Error {}\n\nexport interface InvalidateCacheInput {\n /**\n * Caller of the task (e.g., `fm-before-update`, `fm-after-delete`).\n */\n caller: string;\n /**\n * Cache paths to invalidate.\n */\n paths: string[];\n}\n\nclass InvalidateCloudfrontCacheTask implements TaskDefinition.Interface<InvalidateCacheInput> {\n id = \"cloudfrontInvalidateCache\";\n title = \"Invalidate CloudFront Cache\";\n description = \"A task to invalidate Cloudfront cache by given paths.\";\n maxIterations = 100;\n isPrivate = true;\n\n selfCleanup = [\"onSuccess\" as const, \"onAbort\" as const];\n\n private continueIfCode = [\"TooManyInvalidationsInProgress\", \"Throttling\"];\n\n public async run({ input, controller }: TaskDefinition.RunParams<InvalidateCacheInput>) {\n if (controller.runtime.isAborted()) {\n return controller.response.aborted();\n }\n\n const manifest = await ServiceDiscovery.load();\n\n if (!manifest) {\n return controller.response.error({\n message: `Unable to invalidate cache due to a missing service manifest.`,\n code: \"MISSING_SERVICE_MANIFEST\",\n data: {\n manifest: \"api\"\n }\n });\n }\n\n const { distributionId } = manifest.api.cloudfront;\n\n const invalidateCache = () => {\n return this.invalidateCache(input.caller, distributionId as string, input.paths);\n };\n\n try {\n await executeWithRetry(invalidateCache, {\n minTimeout: 2000,\n // instead of forever: true\n retries: 10000,\n onFailedAttempt: ({ error }) => {\n if (this.continueIfCode.includes(error.name)) {\n throw new ReturnContinue();\n }\n\n if (error.message.includes(\"not authorized to perform\")) {\n throw error;\n }\n\n if (controller.runtime.isCloseToTimeout()) {\n throw new ReturnContinue();\n }\n }\n });\n } catch (error) {\n if (error instanceof ReturnContinue) {\n return controller.response.continue(input);\n }\n\n return controller.response.error({\n message: error.message,\n code: \"EXECUTE_WITH_RETRY_FAILED\",\n data: input.paths\n });\n }\n\n return controller.response.done();\n }\n\n private async invalidateCache(\n caller: string,\n distributionId: string,\n paths: string[]\n ): Promise<void> {\n const cloudfront = new CloudFront();\n await cloudfront.createInvalidation({\n DistributionId: distributionId,\n InvalidationBatch: {\n CallerReference: `${new Date().getTime()}-${caller}`,\n Paths: {\n Quantity: paths.length,\n Items: paths\n }\n }\n });\n }\n}\n\nexport const InvalidateCloudfrontCacheTaskDefinition = TaskDefinition.createImplementation({\n implementation: InvalidateCloudfrontCacheTask,\n dependencies: []\n});\n"],"names":["ReturnContinue","Error","InvalidateCloudfrontCacheTask","input","controller","manifest","ServiceDiscovery","distributionId","invalidateCache","executeWithRetry","error","caller","paths","cloudfront","CloudFront","Date","InvalidateCloudfrontCacheTaskDefinition","TaskDefinition"],"mappings":";;;;AAKA,MAAMA,uBAAuBC;AAAO;AAapC,MAAMC;IAWF,MAAa,IAAI,EAAEC,KAAK,EAAEC,UAAU,EAAkD,EAAE;QACpF,IAAIA,WAAW,OAAO,CAAC,SAAS,IAC5B,OAAOA,WAAW,QAAQ,CAAC,OAAO;QAGtC,MAAMC,WAAW,MAAMC,iBAAiB,IAAI;QAE5C,IAAI,CAACD,UACD,OAAOD,WAAW,QAAQ,CAAC,KAAK,CAAC;YAC7B,SAAS;YACT,MAAM;YACN,MAAM;gBACF,UAAU;YACd;QACJ;QAGJ,MAAM,EAAEG,cAAc,EAAE,GAAGF,SAAS,GAAG,CAAC,UAAU;QAElD,MAAMG,kBAAkB,IACb,IAAI,CAAC,eAAe,CAACL,MAAM,MAAM,EAAEI,gBAA0BJ,MAAM,KAAK;QAGnF,IAAI;YACA,MAAMM,iBAAiBD,iBAAiB;gBACpC,YAAY;gBAEZ,SAAS;gBACT,iBAAiB,CAAC,EAAEE,KAAK,EAAE;oBACvB,IAAI,IAAI,CAAC,cAAc,CAAC,QAAQ,CAACA,MAAM,IAAI,GACvC,MAAM,IAAIV;oBAGd,IAAIU,MAAM,OAAO,CAAC,QAAQ,CAAC,8BACvB,MAAMA;oBAGV,IAAIN,WAAW,OAAO,CAAC,gBAAgB,IACnC,MAAM,IAAIJ;gBAElB;YACJ;QACJ,EAAE,OAAOU,OAAO;YACZ,IAAIA,iBAAiBV,gBACjB,OAAOI,WAAW,QAAQ,CAAC,QAAQ,CAACD;YAGxC,OAAOC,WAAW,QAAQ,CAAC,KAAK,CAAC;gBAC7B,SAASM,MAAM,OAAO;gBACtB,MAAM;gBACN,MAAMP,MAAM,KAAK;YACrB;QACJ;QAEA,OAAOC,WAAW,QAAQ,CAAC,IAAI;IACnC;IAEA,MAAc,gBACVO,MAAc,EACdJ,cAAsB,EACtBK,KAAe,EACF;QACb,MAAMC,aAAa,IAAIC;QACvB,MAAMD,WAAW,kBAAkB,CAAC;YAChC,gBAAgBN;YAChB,mBAAmB;gBACf,iBAAiB,GAAG,IAAIQ,OAAO,OAAO,GAAG,CAAC,EAAEJ,QAAQ;gBACpD,OAAO;oBACH,UAAUC,MAAM,MAAM;oBACtB,OAAOA;gBACX;YACJ;QACJ;IACJ;;aAnFA,EAAE,GAAG;aACL,KAAK,GAAG;aACR,WAAW,GAAG;aACd,aAAa,GAAG;aAChB,SAAS,GAAG;aAEZ,WAAW,GAAG;YAAC;YAAsB;SAAmB;aAEhD,cAAc,GAAG;YAAC;YAAkC;SAAa;;AA4E7E;AAEO,MAAMI,0CAA0CC,eAAe,oBAAoB,CAAC;IACvF,gBAAgBf;IAChB,cAAc,EAAE;AACpB"}
1
+ {"version":3,"file":"features/FlushCache/InvalidateCacheTask.js","sources":["../../../src/features/FlushCache/InvalidateCacheTask.ts"],"sourcesContent":["import { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport { CloudFront } from \"@webiny/aws-sdk/client-cloudfront/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { executeWithRetry } from \"@webiny/utils\";\n\nclass ReturnContinue extends Error {}\n\nexport interface InvalidateCacheInput {\n /**\n * Caller of the task (e.g., `fm-before-update`, `fm-after-delete`).\n */\n caller: string;\n /**\n * Cache paths to invalidate.\n */\n paths: string[];\n}\n\nclass InvalidateCloudfrontCacheTask implements TaskDefinition.Interface<InvalidateCacheInput> {\n id = \"cloudfrontInvalidateCache\";\n title = \"Invalidate CloudFront Cache\";\n description = \"A task to invalidate Cloudfront cache by given paths.\";\n maxIterations = 100;\n isPrivate = true;\n\n selfCleanup = [\"onSuccess\" as const, \"onAbort\" as const];\n\n private continueIfCode = [\"TooManyInvalidationsInProgress\", \"Throttling\"];\n\n public async run({ input, controller }: TaskDefinition.RunParams<InvalidateCacheInput>) {\n if (controller.runtime.isAborted()) {\n return controller.response.aborted();\n }\n\n const manifest = await ServiceDiscovery.load();\n\n if (!manifest) {\n return controller.response.error({\n message: `Unable to invalidate cache due to a missing service manifest.`,\n code: \"MISSING_SERVICE_MANIFEST\",\n data: {\n manifest: \"api\"\n }\n });\n }\n\n const { distributionId } = manifest.api.cloudfront;\n\n const invalidateCache = () => {\n return this.invalidateCache(input.caller, distributionId as string, input.paths);\n };\n\n try {\n await executeWithRetry(invalidateCache, {\n minTimeout: 2000,\n // instead of forever: true\n retries: 10000,\n onFailedAttempt: ({ error }) => {\n if (this.continueIfCode.includes(error.name)) {\n throw new ReturnContinue();\n }\n\n if (error.message.includes(\"not authorized to perform\")) {\n throw error;\n }\n\n if (controller.runtime.isCloseToTimeout()) {\n throw new ReturnContinue();\n }\n }\n });\n } catch (error) {\n if (error instanceof ReturnContinue) {\n return controller.response.continue(input);\n }\n\n return controller.response.error({\n message: error.message,\n code: \"EXECUTE_WITH_RETRY_FAILED\",\n data: input.paths\n });\n }\n\n return controller.response.done();\n }\n\n private async invalidateCache(\n caller: string,\n distributionId: string,\n paths: string[]\n ): Promise<void> {\n const cloudfront = new CloudFront();\n await cloudfront.createInvalidation({\n DistributionId: distributionId,\n InvalidationBatch: {\n CallerReference: `${new Date().getTime()}-${caller}`,\n Paths: {\n Quantity: paths.length,\n Items: paths\n }\n }\n });\n }\n}\n\nexport const InvalidateCloudfrontCacheTaskDefinition = TaskDefinition.createImplementation({\n implementation: InvalidateCloudfrontCacheTask,\n dependencies: []\n});\n"],"names":["ReturnContinue","Error","InvalidateCloudfrontCacheTask","input","controller","manifest","ServiceDiscovery","distributionId","invalidateCache","executeWithRetry","error","caller","paths","cloudfront","CloudFront","Date","InvalidateCloudfrontCacheTaskDefinition","TaskDefinition"],"mappings":";;;;AAKA,MAAMA,uBAAuBC;AAAO;AAapC,MAAMC;IAWF,MAAa,IAAI,EAAEC,KAAK,EAAEC,UAAU,EAAkD,EAAE;QACpF,IAAIA,WAAW,OAAO,CAAC,SAAS,IAC5B,OAAOA,WAAW,QAAQ,CAAC,OAAO;QAGtC,MAAMC,WAAW,MAAMC,iBAAiB,IAAI;QAE5C,IAAI,CAACD,UACD,OAAOD,WAAW,QAAQ,CAAC,KAAK,CAAC;YAC7B,SAAS;YACT,MAAM;YACN,MAAM;gBACF,UAAU;YACd;QACJ;QAGJ,MAAM,EAAEG,cAAc,EAAE,GAAGF,SAAS,GAAG,CAAC,UAAU;QAElD,MAAMG,kBAAkB,IACb,IAAI,CAAC,eAAe,CAACL,MAAM,MAAM,EAAEI,gBAA0BJ,MAAM,KAAK;QAGnF,IAAI;YACA,MAAMM,iBAAiBD,iBAAiB;gBACpC,YAAY;gBAEZ,SAAS;gBACT,iBAAiB,CAAC,EAAEE,KAAK,EAAE;oBACvB,IAAI,IAAI,CAAC,cAAc,CAAC,QAAQ,CAACA,MAAM,IAAI,GACvC,MAAM,IAAIV;oBAGd,IAAIU,MAAM,OAAO,CAAC,QAAQ,CAAC,8BACvB,MAAMA;oBAGV,IAAIN,WAAW,OAAO,CAAC,gBAAgB,IACnC,MAAM,IAAIJ;gBAElB;YACJ;QACJ,EAAE,OAAOU,OAAO;YACZ,IAAIA,iBAAiBV,gBACjB,OAAOI,WAAW,QAAQ,CAAC,QAAQ,CAACD;YAGxC,OAAOC,WAAW,QAAQ,CAAC,KAAK,CAAC;gBAC7B,SAASM,MAAM,OAAO;gBACtB,MAAM;gBACN,MAAMP,MAAM,KAAK;YACrB;QACJ;QAEA,OAAOC,WAAW,QAAQ,CAAC,IAAI;IACnC;IAEA,MAAc,gBACVO,MAAc,EACdJ,cAAsB,EACtBK,KAAe,EACF;QACb,MAAMC,aAAa,IAAIC;QACvB,MAAMD,WAAW,kBAAkB,CAAC;YAChC,gBAAgBN;YAChB,mBAAmB;gBACf,iBAAiB,GAAG,IAAIQ,OAAO,OAAO,GAAG,CAAC,EAAEJ,QAAQ;gBACpD,OAAO;oBACH,UAAUC,MAAM,MAAM;oBACtB,OAAOA;gBACX;YACJ;QACJ;IACJ;;aAnFA,EAAE,GAAG;aACL,KAAK,GAAG;aACR,WAAW,GAAG;aACd,aAAa,GAAG;aAChB,SAAS,GAAG;aAEZ,WAAW,GAAG;YAAC;YAAsB;SAAmB;aAEhD,cAAc,GAAG;YAAC;YAAkC;SAAa;;AA4E7E;AAEO,MAAMI,0CAA0CC,eAAe,oBAAoB,CAAC;IACvF,gBAAgBf;IAChB,cAAc,EAAE;AACpB"}
@@ -1,10 +1,10 @@
1
1
  import { Result } from "@webiny/feature/api";
2
- import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
3
2
  import { GetFileContentsByIdUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
4
3
  import type { FileContents } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
4
+ import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
5
5
  declare class GetFileContentsByIdUseCaseImpl implements GetFileContentsByIdUseCase.Interface {
6
- private metadataReader;
7
- constructor(keyValueStore: GlobalKeyValueStore.Interface);
6
+ private readonly metadataReader;
7
+ constructor(metadataReader: MetadataReader.Interface);
8
8
  execute(fileId: string): Promise<Result<FileContents, GetFileContentsByIdUseCase.Error>>;
9
9
  }
10
10
  export declare const GetFileContentsByIdUseCaseImplementation: typeof GetFileContentsByIdUseCaseImpl & {
@@ -1,12 +1,11 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import { S3 } from "@webiny/aws-sdk/client-s3/index.js";
3
- import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
4
3
  import { GetFileContentsByIdUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
5
4
  import { FileNotFoundError, FilePersistenceError } from "@webiny/api-file-manager/domain/file/errors.js";
6
- import { MetadataReader } from "../WriteFileMetadata/MetadataReader.js";
5
+ import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
7
6
  class GetFileContentsByIdUseCaseImpl {
8
- constructor(keyValueStore){
9
- this.metadataReader = new MetadataReader(keyValueStore);
7
+ constructor(metadataReader){
8
+ this.metadataReader = metadataReader;
10
9
  }
11
10
  async execute(fileId) {
12
11
  const metadata = await this.metadataReader.read(fileId);
@@ -32,7 +31,7 @@ class GetFileContentsByIdUseCaseImpl {
32
31
  const GetFileContentsByIdUseCaseImplementation = GetFileContentsByIdUseCase.createImplementation({
33
32
  implementation: GetFileContentsByIdUseCaseImpl,
34
33
  dependencies: [
35
- GlobalKeyValueStore
34
+ MetadataReader
36
35
  ]
37
36
  });
38
37
  export { GetFileContentsByIdUseCaseImplementation };
@@ -1 +1 @@
1
- {"version":3,"file":"features/GetFileContentsById/GetFileContentsByIdUseCase.js","sources":["../../../src/features/GetFileContentsById/GetFileContentsByIdUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { GetFileContentsByIdUseCase } from \"@webiny/api-file-manager/features/file/GetFileContentsById/index.js\";\nimport type { FileContents } from \"@webiny/api-file-manager/features/file/GetFileContentsById/index.js\";\nimport {\n FileNotFoundError,\n FilePersistenceError\n} from \"@webiny/api-file-manager/domain/file/errors.js\";\nimport { MetadataReader } from \"~/features/WriteFileMetadata/MetadataReader.js\";\n\nclass GetFileContentsByIdUseCaseImpl implements GetFileContentsByIdUseCase.Interface {\n private metadataReader: MetadataReader;\n\n constructor(keyValueStore: GlobalKeyValueStore.Interface) {\n this.metadataReader = new MetadataReader(keyValueStore);\n }\n\n async execute(fileId: string): Promise<Result<FileContents, GetFileContentsByIdUseCase.Error>> {\n const metadata = await this.metadataReader.read(fileId);\n if (!metadata) {\n return Result.fail(new FileNotFoundError(fileId));\n }\n\n try {\n const s3 = new S3();\n const bucket = String(process.env.S3_BUCKET);\n const response = await s3.getObject({ Bucket: bucket, Key: metadata.bucketKey });\n\n if (!response.Body) {\n return Result.fail(new FileNotFoundError(fileId));\n }\n\n const buffer = Buffer.from(await response.Body.transformToByteArray());\n return Result.ok({ buffer, contentType: metadata.contentType });\n } catch (error) {\n return Result.fail(\n new FilePersistenceError(error instanceof Error ? error : new Error(String(error)))\n );\n }\n }\n}\n\nexport const GetFileContentsByIdUseCaseImplementation =\n GetFileContentsByIdUseCase.createImplementation({\n implementation: GetFileContentsByIdUseCaseImpl,\n dependencies: [GlobalKeyValueStore]\n });\n"],"names":["GetFileContentsByIdUseCaseImpl","keyValueStore","MetadataReader","fileId","metadata","Result","FileNotFoundError","s3","S3","bucket","String","process","response","buffer","Buffer","error","FilePersistenceError","Error","GetFileContentsByIdUseCaseImplementation","GetFileContentsByIdUseCase","GlobalKeyValueStore"],"mappings":";;;;;;AAWA,MAAMA;IAGF,YAAYC,aAA4C,CAAE;QACtD,IAAI,CAAC,cAAc,GAAG,IAAIC,eAAeD;IAC7C;IAEA,MAAM,QAAQE,MAAc,EAAmE;QAC3F,MAAMC,WAAW,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAACD;QAChD,IAAI,CAACC,UACD,OAAOC,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;QAG7C,IAAI;YACA,MAAMI,KAAK,IAAIC;YACf,MAAMC,SAASC,OAAOC,QAAQ,GAAG,CAAC,SAAS;YAC3C,MAAMC,WAAW,MAAML,GAAG,SAAS,CAAC;gBAAE,QAAQE;gBAAQ,KAAKL,SAAS,SAAS;YAAC;YAE9E,IAAI,CAACQ,SAAS,IAAI,EACd,OAAOP,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;YAG7C,MAAMU,SAASC,OAAO,IAAI,CAAC,MAAMF,SAAS,IAAI,CAAC,oBAAoB;YACnE,OAAOP,OAAO,EAAE,CAAC;gBAAEQ;gBAAQ,aAAaT,SAAS,WAAW;YAAC;QACjE,EAAE,OAAOW,OAAO;YACZ,OAAOV,OAAO,IAAI,CACd,IAAIW,qBAAqBD,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMP,OAAOK;QAEnF;IACJ;AACJ;AAEO,MAAMG,2CACTC,2BAA2B,oBAAoB,CAAC;IAC5C,gBAAgBnB;IAChB,cAAc;QAACoB;KAAoB;AACvC"}
1
+ {"version":3,"file":"features/GetFileContentsById/GetFileContentsByIdUseCase.js","sources":["../../../src/features/GetFileContentsById/GetFileContentsByIdUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { S3 } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { GetFileContentsByIdUseCase } from \"@webiny/api-file-manager/features/file/GetFileContentsById/index.js\";\nimport type { FileContents } from \"@webiny/api-file-manager/features/file/GetFileContentsById/index.js\";\nimport {\n FileNotFoundError,\n FilePersistenceError\n} from \"@webiny/api-file-manager/domain/file/errors.js\";\nimport { MetadataReader } from \"@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js\";\n\nclass GetFileContentsByIdUseCaseImpl implements GetFileContentsByIdUseCase.Interface {\n private readonly metadataReader: MetadataReader.Interface;\n\n public constructor(metadataReader: MetadataReader.Interface) {\n this.metadataReader = metadataReader;\n }\n\n public async execute(\n fileId: string\n ): Promise<Result<FileContents, GetFileContentsByIdUseCase.Error>> {\n const metadata = await this.metadataReader.read(fileId);\n if (!metadata) {\n return Result.fail(new FileNotFoundError(fileId));\n }\n\n try {\n const s3 = new S3();\n const bucket = String(process.env.S3_BUCKET);\n const response = await s3.getObject({ Bucket: bucket, Key: metadata.bucketKey });\n\n if (!response.Body) {\n return Result.fail(new FileNotFoundError(fileId));\n }\n\n const buffer = Buffer.from(await response.Body.transformToByteArray());\n return Result.ok({ buffer, contentType: metadata.contentType });\n } catch (error) {\n return Result.fail(\n new FilePersistenceError(error instanceof Error ? error : new Error(String(error)))\n );\n }\n }\n}\n\nexport const GetFileContentsByIdUseCaseImplementation =\n GetFileContentsByIdUseCase.createImplementation({\n implementation: GetFileContentsByIdUseCaseImpl,\n dependencies: [MetadataReader]\n });\n"],"names":["GetFileContentsByIdUseCaseImpl","metadataReader","fileId","metadata","Result","FileNotFoundError","s3","S3","bucket","String","process","response","buffer","Buffer","error","FilePersistenceError","Error","GetFileContentsByIdUseCaseImplementation","GetFileContentsByIdUseCase","MetadataReader"],"mappings":";;;;;AAUA,MAAMA;IAGF,YAAmBC,cAAwC,CAAE;QACzD,IAAI,CAAC,cAAc,GAAGA;IAC1B;IAEA,MAAa,QACTC,MAAc,EACiD;QAC/D,MAAMC,WAAW,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAACD;QAChD,IAAI,CAACC,UACD,OAAOC,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;QAG7C,IAAI;YACA,MAAMI,KAAK,IAAIC;YACf,MAAMC,SAASC,OAAOC,QAAQ,GAAG,CAAC,SAAS;YAC3C,MAAMC,WAAW,MAAML,GAAG,SAAS,CAAC;gBAAE,QAAQE;gBAAQ,KAAKL,SAAS,SAAS;YAAC;YAE9E,IAAI,CAACQ,SAAS,IAAI,EACd,OAAOP,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;YAG7C,MAAMU,SAASC,OAAO,IAAI,CAAC,MAAMF,SAAS,IAAI,CAAC,oBAAoB;YACnE,OAAOP,OAAO,EAAE,CAAC;gBAAEQ;gBAAQ,aAAaT,SAAS,WAAW;YAAC;QACjE,EAAE,OAAOW,OAAO;YACZ,OAAOV,OAAO,IAAI,CACd,IAAIW,qBAAqBD,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMP,OAAOK;QAEnF;IACJ;AACJ;AAEO,MAAMG,2CACTC,2BAA2B,oBAAoB,CAAC;IAC5C,gBAAgBlB;IAChB,cAAc;QAACmB;KAAe;AAClC"}
@@ -0,0 +1,14 @@
1
+ import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
2
+ import { GetUploadPayloadUseCase } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
3
+ import type { FileData } from "@webiny/api-file-manager/features/upload/types.js";
4
+ import type { UploadPayloadResponse } from "@webiny/api-file-manager/features/upload/types.js";
5
+ import type { FileManagerSettings } from "@webiny/api-file-manager/domain/settings/types.js";
6
+ declare class GetUploadPayloadUseCaseImpl implements GetUploadPayloadUseCase.Interface {
7
+ private readonly tenantContext;
8
+ constructor(tenantContext: TenantContext.Interface);
9
+ execute(file: FileData, settings: FileManagerSettings): Promise<UploadPayloadResponse>;
10
+ }
11
+ export declare const GetUploadPayloadUseCaseImplementation: typeof GetUploadPayloadUseCaseImpl & {
12
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/upload/GetUploadPayload/abstractions").IGetUploadPayloadUseCase>;
13
+ };
14
+ export {};
@@ -0,0 +1,54 @@
1
+ import { S3Client, createPresignedPost } from "@webiny/aws-sdk/client-s3/index.js";
2
+ import { validation } from "@webiny/validation";
3
+ import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
4
+ import { GetUploadPayloadUseCase } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
5
+ const UPLOAD_MAX_FILE_SIZE_DEFAULT = 1099511627776;
6
+ const sanitizeFileSizeValue = (value, defaultValue)=>{
7
+ try {
8
+ validation.validateSync(value, "required,numeric,gte:0");
9
+ return value;
10
+ } catch {
11
+ return defaultValue;
12
+ }
13
+ };
14
+ class GetUploadPayloadUseCaseImpl {
15
+ constructor(tenantContext){
16
+ this.tenantContext = tenantContext;
17
+ }
18
+ async execute(file, settings) {
19
+ const uploadMinFileSize = sanitizeFileSizeValue(settings.uploadMinFileSize, 0);
20
+ const uploadMaxFileSize = sanitizeFileSizeValue(settings.uploadMaxFileSize, UPLOAD_MAX_FILE_SIZE_DEFAULT);
21
+ const tenant = this.tenantContext.getTenant();
22
+ const storageKey = `tenants/${tenant.id}/files/${file.key}`;
23
+ const params = {
24
+ Key: storageKey.startsWith("/") ? storageKey.slice(1) : storageKey,
25
+ Expires: 60,
26
+ Bucket: String(process.env.S3_BUCKET),
27
+ Conditions: [
28
+ [
29
+ "content-length-range",
30
+ uploadMinFileSize,
31
+ uploadMaxFileSize
32
+ ]
33
+ ],
34
+ Fields: {
35
+ "Content-Type": file.type
36
+ }
37
+ };
38
+ const s3 = new S3Client();
39
+ const payload = await createPresignedPost(s3, params);
40
+ return {
41
+ data: payload,
42
+ file
43
+ };
44
+ }
45
+ }
46
+ const GetUploadPayloadUseCaseImplementation = GetUploadPayloadUseCase.createImplementation({
47
+ implementation: GetUploadPayloadUseCaseImpl,
48
+ dependencies: [
49
+ TenantContext
50
+ ]
51
+ });
52
+ export { GetUploadPayloadUseCaseImplementation };
53
+
54
+ //# sourceMappingURL=GetUploadPayloadUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/GetUploadPayload/GetUploadPayloadUseCase.js","sources":["../../../src/features/GetUploadPayload/GetUploadPayloadUseCase.ts"],"sourcesContent":["import type { PresignedPostOptions } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { S3Client } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { createPresignedPost } from \"@webiny/aws-sdk/client-s3/index.js\";\nimport { validation } from \"@webiny/validation\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { GetUploadPayloadUseCase } from \"@webiny/api-file-manager/features/upload/GetUploadPayload/index.js\";\nimport type { FileData } from \"@webiny/api-file-manager/features/upload/types.js\";\nimport type { UploadPayloadResponse } from \"@webiny/api-file-manager/features/upload/types.js\";\nimport type { FileManagerSettings } from \"@webiny/api-file-manager/domain/settings/types.js\";\n\nconst UPLOAD_MAX_FILE_SIZE_DEFAULT = 1099511627776; /* 1TB */\n\nconst sanitizeFileSizeValue = (value: number, defaultValue: number): number => {\n try {\n validation.validateSync(value, \"required,numeric,gte:0\");\n return value;\n } catch {\n return defaultValue;\n }\n};\n\nclass GetUploadPayloadUseCaseImpl implements GetUploadPayloadUseCase.Interface {\n public constructor(private readonly tenantContext: TenantContext.Interface) {}\n\n public async execute(\n file: FileData,\n settings: FileManagerSettings\n ): Promise<UploadPayloadResponse> {\n const uploadMinFileSize = sanitizeFileSizeValue(settings.uploadMinFileSize, 0);\n const uploadMaxFileSize = sanitizeFileSizeValue(\n settings.uploadMaxFileSize,\n UPLOAD_MAX_FILE_SIZE_DEFAULT\n );\n\n const tenant = this.tenantContext.getTenant();\n const storageKey = `tenants/${tenant.id}/files/${file.key}`;\n\n const params = {\n Key: storageKey.startsWith(\"/\") ? storageKey.slice(1) : storageKey,\n Expires: 60,\n Bucket: String(process.env.S3_BUCKET),\n Conditions: [\n [\"content-length-range\", uploadMinFileSize, uploadMaxFileSize]\n ] as PresignedPostOptions[\"Conditions\"],\n Fields: {\n \"Content-Type\": file.type\n }\n };\n\n const s3 = new S3Client();\n const payload = await createPresignedPost(s3, params);\n\n return {\n data: payload as unknown as Record<string, unknown>,\n file\n };\n }\n}\n\nexport const GetUploadPayloadUseCaseImplementation = GetUploadPayloadUseCase.createImplementation({\n implementation: GetUploadPayloadUseCaseImpl,\n dependencies: [TenantContext]\n});\n"],"names":["UPLOAD_MAX_FILE_SIZE_DEFAULT","sanitizeFileSizeValue","value","defaultValue","validation","GetUploadPayloadUseCaseImpl","tenantContext","file","settings","uploadMinFileSize","uploadMaxFileSize","tenant","storageKey","params","String","process","s3","S3Client","payload","createPresignedPost","GetUploadPayloadUseCaseImplementation","GetUploadPayloadUseCase","TenantContext"],"mappings":";;;;AAUA,MAAMA,+BAA+B;AAErC,MAAMC,wBAAwB,CAACC,OAAeC;IAC1C,IAAI;QACAC,WAAW,YAAY,CAACF,OAAO;QAC/B,OAAOA;IACX,EAAE,OAAM;QACJ,OAAOC;IACX;AACJ;AAEA,MAAME;IACF,YAAoCC,aAAsC,CAAE;aAAxCA,aAAa,GAAbA;IAAyC;IAE7E,MAAa,QACTC,IAAc,EACdC,QAA6B,EACC;QAC9B,MAAMC,oBAAoBR,sBAAsBO,SAAS,iBAAiB,EAAE;QAC5E,MAAME,oBAAoBT,sBACtBO,SAAS,iBAAiB,EAC1BR;QAGJ,MAAMW,SAAS,IAAI,CAAC,aAAa,CAAC,SAAS;QAC3C,MAAMC,aAAa,CAAC,QAAQ,EAAED,OAAO,EAAE,CAAC,OAAO,EAAEJ,KAAK,GAAG,EAAE;QAE3D,MAAMM,SAAS;YACX,KAAKD,WAAW,UAAU,CAAC,OAAOA,WAAW,KAAK,CAAC,KAAKA;YACxD,SAAS;YACT,QAAQE,OAAOC,QAAQ,GAAG,CAAC,SAAS;YACpC,YAAY;gBACR;oBAAC;oBAAwBN;oBAAmBC;iBAAkB;aACjE;YACD,QAAQ;gBACJ,gBAAgBH,KAAK,IAAI;YAC7B;QACJ;QAEA,MAAMS,KAAK,IAAIC;QACf,MAAMC,UAAU,MAAMC,oBAAoBH,IAAIH;QAE9C,OAAO;YACH,MAAMK;YACNX;QACJ;IACJ;AACJ;AAEO,MAAMa,wCAAwCC,wBAAwB,oBAAoB,CAAC;IAC9F,gBAAgBhB;IAChB,cAAc;QAACiB;KAAc;AACjC"}
@@ -1,4 +1,4 @@
1
- export declare const WriteFileMetadataFeature: {
1
+ export declare const GetUploadPayloadFeature: {
2
2
  name: string;
3
3
  register(container: import("@webiny/di").Container): void;
4
4
  };
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { GetUploadPayloadUseCaseImplementation } from "./GetUploadPayloadUseCase.js";
3
+ const GetUploadPayloadFeature = createFeature({
4
+ name: "FileManagerS3/GetUploadPayload",
5
+ register (container) {
6
+ container.register(GetUploadPayloadUseCaseImplementation);
7
+ }
8
+ });
9
+ export { GetUploadPayloadFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/GetUploadPayload/feature.js","sources":["../../../src/features/GetUploadPayload/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { GetUploadPayloadUseCaseImplementation } from \"./GetUploadPayloadUseCase.js\";\n\nexport const GetUploadPayloadFeature = createFeature({\n name: \"FileManagerS3/GetUploadPayload\",\n register(container) {\n container.register(GetUploadPayloadUseCaseImplementation);\n }\n});\n"],"names":["GetUploadPayloadFeature","createFeature","container","GetUploadPayloadUseCaseImplementation"],"mappings":";;AAGO,MAAMA,0BAA0BC,cAAc;IACjD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { ContextPlugin } from "@webiny/api";
2
- export { createFileUploadModifier } from "./utils/FileUploadModifier.js";
2
+ export { createFileUploadModifier } from "@webiny/api-file-manager/features/upload/index.js";
3
3
  export { createAssetDelivery } from "./assetDelivery/createAssetDelivery.js";
4
- export declare const createFileManagerS3: () => (import("@webiny/handler-graphql/index.js").GraphQLSchemaPlugin<import("@webiny/api/types.js").Context> | ContextPlugin<import("@webiny/api/types.js").Context>)[];
4
+ export declare const createFileManagerS3: () => ContextPlugin<import("@webiny/api/types.js").Context>[];
package/index.js CHANGED
@@ -1,30 +1,32 @@
1
1
  import { ContextPlugin } from "@webiny/api";
2
2
  import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/index.js";
3
- import { createS3GraphQLSchema } from "./graphql/schema.js";
4
3
  import { DeleteFileFromBucketFeature } from "./features/DeleteFileFromBucket/feature.js";
5
- import { WriteFileMetadataFeature } from "./features/WriteFileMetadata/feature.js";
6
4
  import { ApplyThreatScanningFeature } from "./enterprise/ApplyThreatScanning/feature.js";
7
5
  import { FlushCacheFeature } from "./features/FlushCache/feature.js";
8
6
  import { ExtractMetadataFeature } from "./features/ExtractMetadata/feature.js";
9
7
  import { GetFileContentsByIdFeature } from "./features/GetFileContentsById/feature.js";
10
8
  import { GetFileContentsByKeyFeature } from "./features/GetFileContentsByKey/feature.js";
9
+ import { GetUploadPayloadFeature } from "./features/GetUploadPayload/feature.js";
10
+ import { CreateMultiPartUploadFeature } from "./features/CreateMultiPartUpload/feature.js";
11
+ import { CompleteMultiPartUploadFeature } from "./features/CompleteMultiPartUpload/feature.js";
11
12
  const contextPlugin = new ContextPlugin((context)=>{
12
13
  const container = context.container;
13
14
  FlushCacheFeature.register(container);
14
15
  DeleteFileFromBucketFeature.register(container);
15
16
  ExtractMetadataFeature.register(container);
16
- WriteFileMetadataFeature.register(container);
17
17
  GetFileContentsByIdFeature.register(container);
18
18
  GetFileContentsByKeyFeature.register(container);
19
+ GetUploadPayloadFeature.register(container);
20
+ CreateMultiPartUploadFeature.register(container);
21
+ CompleteMultiPartUploadFeature.register(container);
19
22
  const wcp = container.resolve(WcpContext);
20
23
  if (wcp.canUseFileManagerThreatDetection()) ApplyThreatScanningFeature.register(container);
21
24
  });
22
25
  contextPlugin.name = "fileManagerS3.context";
23
26
  const createFileManagerS3 = ()=>[
24
- contextPlugin,
25
- createS3GraphQLSchema()
27
+ contextPlugin
26
28
  ];
27
- export { createFileUploadModifier } from "./utils/FileUploadModifier.js";
29
+ export { createFileUploadModifier } from "@webiny/api-file-manager/features/upload/index.js";
28
30
  export { createAssetDelivery } from "./assetDelivery/createAssetDelivery.js";
29
31
  export { createFileManagerS3 };
30
32
 
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { ContextPlugin } from \"@webiny/api\";\nimport { WcpContext } from \"@webiny/api-core/features/wcp/WcpContext/index.js\";\nimport { createS3GraphQLSchema } from \"./graphql/schema.js\";\nimport { DeleteFileFromBucketFeature } from \"~/features/DeleteFileFromBucket/feature.js\";\nimport { WriteFileMetadataFeature } from \"~/features/WriteFileMetadata/feature.js\";\nimport { ApplyThreatScanningFeature } from \"~/enterprise/ApplyThreatScanning/feature.js\";\nimport { FlushCacheFeature } from \"~/features/FlushCache/feature.js\";\nimport { ExtractMetadataFeature } from \"~/features/ExtractMetadata/feature.js\";\nimport { GetFileContentsByIdFeature } from \"~/features/GetFileContentsById/feature.js\";\nimport { GetFileContentsByKeyFeature } from \"~/features/GetFileContentsByKey/feature.js\";\nexport { createFileUploadModifier } from \"./utils/FileUploadModifier.js\";\nexport { createAssetDelivery } from \"./assetDelivery/createAssetDelivery.js\";\n\nconst contextPlugin = new ContextPlugin(context => {\n const container = context.container;\n\n FlushCacheFeature.register(container);\n DeleteFileFromBucketFeature.register(container);\n ExtractMetadataFeature.register(container);\n WriteFileMetadataFeature.register(container);\n GetFileContentsByIdFeature.register(container);\n GetFileContentsByKeyFeature.register(container);\n\n const wcp = container.resolve(WcpContext);\n if (wcp.canUseFileManagerThreatDetection()) {\n ApplyThreatScanningFeature.register(container);\n }\n});\n\ncontextPlugin.name = `fileManagerS3.context`;\n\nexport const createFileManagerS3 = () => [contextPlugin, createS3GraphQLSchema()];\n"],"names":["contextPlugin","ContextPlugin","context","container","FlushCacheFeature","DeleteFileFromBucketFeature","ExtractMetadataFeature","WriteFileMetadataFeature","GetFileContentsByIdFeature","GetFileContentsByKeyFeature","wcp","WcpContext","ApplyThreatScanningFeature","createFileManagerS3","createS3GraphQLSchema"],"mappings":";;;;;;;;;;AAaA,MAAMA,gBAAgB,IAAIC,cAAcC,CAAAA;IACpC,MAAMC,YAAYD,QAAQ,SAAS;IAEnCE,kBAAkB,QAAQ,CAACD;IAC3BE,4BAA4B,QAAQ,CAACF;IACrCG,uBAAuB,QAAQ,CAACH;IAChCI,yBAAyB,QAAQ,CAACJ;IAClCK,2BAA2B,QAAQ,CAACL;IACpCM,4BAA4B,QAAQ,CAACN;IAErC,MAAMO,MAAMP,UAAU,OAAO,CAACQ;IAC9B,IAAID,IAAI,gCAAgC,IACpCE,2BAA2B,QAAQ,CAACT;AAE5C;AAEAH,cAAc,IAAI,GAAG;AAEd,MAAMa,sBAAsB,IAAM;QAACb;QAAec;KAAwB"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { ContextPlugin } from \"@webiny/api\";\nimport { WcpContext } from \"@webiny/api-core/features/wcp/WcpContext/index.js\";\nimport { DeleteFileFromBucketFeature } from \"~/features/DeleteFileFromBucket/feature.js\";\nimport { ApplyThreatScanningFeature } from \"~/enterprise/ApplyThreatScanning/feature.js\";\nimport { FlushCacheFeature } from \"~/features/FlushCache/feature.js\";\nimport { ExtractMetadataFeature } from \"~/features/ExtractMetadata/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\";\nexport { createFileUploadModifier } from \"@webiny/api-file-manager/features/upload/index.js\";\nexport { createAssetDelivery } from \"./assetDelivery/createAssetDelivery.js\";\n\nconst contextPlugin = new ContextPlugin(context => {\n const container = context.container;\n\n FlushCacheFeature.register(container);\n DeleteFileFromBucketFeature.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\n const wcp = container.resolve(WcpContext);\n if (wcp.canUseFileManagerThreatDetection()) {\n ApplyThreatScanningFeature.register(container);\n }\n});\n\ncontextPlugin.name = `fileManagerS3.context`;\n\nexport const createFileManagerS3 = () => [contextPlugin];\n"],"names":["contextPlugin","ContextPlugin","context","container","FlushCacheFeature","DeleteFileFromBucketFeature","ExtractMetadataFeature","GetFileContentsByIdFeature","GetFileContentsByKeyFeature","GetUploadPayloadFeature","CreateMultiPartUploadFeature","CompleteMultiPartUploadFeature","wcp","WcpContext","ApplyThreatScanningFeature","createFileManagerS3"],"mappings":";;;;;;;;;;;AAcA,MAAMA,gBAAgB,IAAIC,cAAcC,CAAAA;IACpC,MAAMC,YAAYD,QAAQ,SAAS;IAEnCE,kBAAkB,QAAQ,CAACD;IAC3BE,4BAA4B,QAAQ,CAACF;IACrCG,uBAAuB,QAAQ,CAACH;IAChCI,2BAA2B,QAAQ,CAACJ;IACpCK,4BAA4B,QAAQ,CAACL;IACrCM,wBAAwB,QAAQ,CAACN;IACjCO,6BAA6B,QAAQ,CAACP;IACtCQ,+BAA+B,QAAQ,CAACR;IAExC,MAAMS,MAAMT,UAAU,OAAO,CAACU;IAC9B,IAAID,IAAI,gCAAgC,IACpCE,2BAA2B,QAAQ,CAACX;AAE5C;AAEAH,cAAc,IAAI,GAAG;AAEd,MAAMe,sBAAsB,IAAM;QAACf;KAAc"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-file-manager-s3",
3
- "version": "6.4.12-beta.5",
3
+ "version": "6.5.0-beta.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -14,32 +14,26 @@
14
14
  "author": "Webiny Ltd",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@webiny/api": "6.4.12-beta.5",
18
- "@webiny/api-core": "6.4.12-beta.5",
19
- "@webiny/api-file-manager": "6.4.12-beta.5",
20
- "@webiny/api-websockets": "6.4.12-beta.5",
21
- "@webiny/aws-sdk": "6.4.12-beta.5",
22
- "@webiny/background-tasks": "6.4.12-beta.5",
23
- "@webiny/feature": "6.4.12-beta.5",
24
- "@webiny/handler": "6.4.12-beta.5",
25
- "@webiny/handler-aws": "6.4.12-beta.5",
26
- "@webiny/handler-graphql": "6.4.12-beta.5",
27
- "@webiny/plugins": "6.4.12-beta.5",
28
- "@webiny/utils": "6.4.12-beta.5",
29
- "@webiny/validation": "6.4.12-beta.5",
30
- "exifreader": "4.45.1",
31
- "mime": "4.1.0",
32
- "object-hash": "3.0.0",
33
- "p-map": "7.0.8",
34
- "p-reduce": "3.0.0",
35
- "sanitize-filename": "1.6.4",
36
- "sharp": "0.35.4"
17
+ "@webiny/api": "6.5.0-beta.0",
18
+ "@webiny/api-core": "6.5.0-beta.0",
19
+ "@webiny/api-file-manager": "6.5.0-beta.0",
20
+ "@webiny/api-websockets": "6.5.0-beta.0",
21
+ "@webiny/aws-sdk": "6.5.0-beta.0",
22
+ "@webiny/background-tasks": "6.5.0-beta.0",
23
+ "@webiny/feature": "6.5.0-beta.0",
24
+ "@webiny/handler": "6.5.0-beta.0",
25
+ "@webiny/handler-aws": "6.5.0-beta.0",
26
+ "@webiny/plugins": "6.5.0-beta.0",
27
+ "@webiny/utils": "6.5.0-beta.0",
28
+ "@webiny/validation": "6.5.0-beta.0",
29
+ "exifreader": "4.41.3",
30
+ "sharp": "0.35.3"
37
31
  },
38
32
  "devDependencies": {
39
- "@webiny/build-tools": "6.4.12-beta.5",
33
+ "@webiny/build-tools": "6.5.0-beta.0",
40
34
  "rimraf": "6.1.3",
41
- "typescript": "6.0.3",
42
- "vitest": "5.0.1"
35
+ "typescript": "7.0.2",
36
+ "vitest": "4.1.10"
43
37
  },
44
38
  "publishConfig": {
45
39
  "access": "public"
package/types.d.ts CHANGED
@@ -1,21 +1,3 @@
1
- import type { PresignedPost } from "@webiny/aws-sdk/client-s3/index.js";
2
1
  import "@webiny/background-tasks/api/features/TaskController/augmentation.js";
3
- export interface PresignedPostPayloadData {
4
- name: string;
5
- type: string;
6
- size: number;
7
- id?: string;
8
- key?: string;
9
- keyPrefix?: string;
10
- }
11
- export interface FileData {
12
- id: string;
13
- key: string;
14
- name: string;
15
- size: number;
16
- type: string;
17
- }
18
- export interface PresignedPostPayloadDataResponse {
19
- data: PresignedPost;
20
- file: FileData;
21
- }
2
+ export type { PresignedPostPayloadData } from "@webiny/api-file-manager/features/upload/index.js";
3
+ export type { FileData } from "@webiny/api-file-manager/features/upload/index.js";
@@ -1,3 +1,3 @@
1
1
  import type { PresignedPost } from "@webiny/aws-sdk/client-s3/index.js";
2
- declare const _default: (buffer: Buffer, preSignedPostPayload: PresignedPost) => Promise<Response>;
3
2
  export default _default;
3
+ declare function _default(buffer: Buffer, preSignedPostPayload: PresignedPost): Promise<Response>;
@@ -1,5 +0,0 @@
1
- import type { Asset } from "@webiny/api-file-manager";
2
- import { AssetReply } from "@webiny/api-file-manager";
3
- export declare class S3StreamAssetReply extends AssetReply {
4
- constructor(asset: Asset);
5
- }