@webiny/api-file-manager-server 6.6.0-alpha.1 → 6.6.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.d.ts +8 -3
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js +23 -14
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js.map +1 -1
- package/features/ExtractMetadata/ExtractMetadataTask.d.ts +10 -5
- package/features/ExtractMetadata/ExtractMetadataTask.js +23 -14
- package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
- package/package.json +12 -12
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
1
|
+
import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
2
2
|
import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
|
|
3
3
|
export interface CleanupStaleMultipartUploadsInput {
|
|
4
4
|
noop?: boolean;
|
|
5
5
|
}
|
|
6
|
-
declare class
|
|
6
|
+
declare class CleanupStaleMultipartUploadsTaskHandlerImpl implements TaskHandler.Interface<CleanupStaleMultipartUploadsInput> {
|
|
7
7
|
private readonly config;
|
|
8
8
|
constructor(config: FileManagerServerConfig.Interface);
|
|
9
|
+
run({ controller }: TaskHandler.RunParams<CleanupStaleMultipartUploadsInput>): Promise<TaskDefinition.Result<CleanupStaleMultipartUploadsInput>>;
|
|
10
|
+
}
|
|
11
|
+
declare class CleanupStaleMultipartUploadsTaskImpl implements TaskDefinition.Interface {
|
|
9
12
|
readonly id = "fileManagerCleanupStaleMultipartUploads";
|
|
10
13
|
readonly title = "Clean up stale multipart upload directories";
|
|
11
14
|
readonly description = "Removes multipart upload directories that are older than 24 hours.";
|
|
@@ -13,7 +16,9 @@ declare class CleanupStaleMultipartUploadsTaskImpl implements TaskDefinition.Int
|
|
|
13
16
|
readonly isPrivate = true;
|
|
14
17
|
readonly databaseLogs = false;
|
|
15
18
|
readonly selfCleanup: ("onAbort" | "onSuccess")[];
|
|
16
|
-
|
|
19
|
+
handler: typeof CleanupStaleMultipartUploadsTaskHandlerImpl & {
|
|
20
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
23
|
export declare const CleanupStaleMultipartUploadsTaskDefinition: typeof CleanupStaleMultipartUploadsTaskImpl & {
|
|
19
24
|
__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>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises } from "node:fs";
|
|
2
2
|
import node_path from "node:path";
|
|
3
|
-
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
3
|
+
import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
4
4
|
import { FileManagerServerConfig } from "../FileManagerServerConfig/abstractions.js";
|
|
5
5
|
const STALE_THRESHOLD_MS = 86400000;
|
|
6
6
|
async function readdirSafe(dirPath) {
|
|
@@ -11,19 +11,9 @@ async function readdirSafe(dirPath) {
|
|
|
11
11
|
throw err;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
class
|
|
14
|
+
class CleanupStaleMultipartUploadsTaskHandlerImpl {
|
|
15
15
|
constructor(config){
|
|
16
16
|
this.config = config;
|
|
17
|
-
this.id = "fileManagerCleanupStaleMultipartUploads";
|
|
18
|
-
this.title = "Clean up stale multipart upload directories";
|
|
19
|
-
this.description = "Removes multipart upload directories that are older than 24 hours.";
|
|
20
|
-
this.maxIterations = 1;
|
|
21
|
-
this.isPrivate = true;
|
|
22
|
-
this.databaseLogs = false;
|
|
23
|
-
this.selfCleanup = [
|
|
24
|
-
"onSuccess",
|
|
25
|
-
"onAbort"
|
|
26
|
-
];
|
|
27
17
|
}
|
|
28
18
|
async run({ controller }) {
|
|
29
19
|
if (controller.runtime.isAborted()) return controller.response.aborted();
|
|
@@ -51,12 +41,31 @@ class CleanupStaleMultipartUploadsTaskImpl {
|
|
|
51
41
|
return controller.response.done();
|
|
52
42
|
}
|
|
53
43
|
}
|
|
54
|
-
const
|
|
55
|
-
implementation:
|
|
44
|
+
const CleanupStaleMultipartUploadsTaskHandler = TaskHandler.createImplementation({
|
|
45
|
+
implementation: CleanupStaleMultipartUploadsTaskHandlerImpl,
|
|
56
46
|
dependencies: [
|
|
57
47
|
FileManagerServerConfig
|
|
58
48
|
]
|
|
59
49
|
});
|
|
50
|
+
class CleanupStaleMultipartUploadsTaskImpl {
|
|
51
|
+
constructor(){
|
|
52
|
+
this.id = "fileManagerCleanupStaleMultipartUploads";
|
|
53
|
+
this.title = "Clean up stale multipart upload directories";
|
|
54
|
+
this.description = "Removes multipart upload directories that are older than 24 hours.";
|
|
55
|
+
this.maxIterations = 1;
|
|
56
|
+
this.isPrivate = true;
|
|
57
|
+
this.databaseLogs = false;
|
|
58
|
+
this.selfCleanup = [
|
|
59
|
+
"onSuccess",
|
|
60
|
+
"onAbort"
|
|
61
|
+
];
|
|
62
|
+
this.handler = CleanupStaleMultipartUploadsTaskHandler;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const CleanupStaleMultipartUploadsTaskDefinition = TaskDefinition.createImplementation({
|
|
66
|
+
implementation: CleanupStaleMultipartUploadsTaskImpl,
|
|
67
|
+
dependencies: []
|
|
68
|
+
});
|
|
60
69
|
export { CleanupStaleMultipartUploadsTaskDefinition };
|
|
61
70
|
|
|
62
71
|
//# sourceMappingURL=CleanupStaleMultipartUploadsTask.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js","sources":["../../../src/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js","sources":["../../../src/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n TaskDefinition,\n TaskHandler\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\n\nexport interface CleanupStaleMultipartUploadsInput {\n /* Reserved for future use. */\n noop?: boolean;\n}\n\nconst STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000;\n\n/* Returns directory entries or an empty array if the path does not exist. */\nasync function readdirSafe(dirPath: string): Promise<string[]> {\n try {\n return await fs.readdir(dirPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return [];\n }\n throw err;\n }\n}\n\nclass CleanupStaleMultipartUploadsTaskHandlerImpl implements TaskHandler.Interface<CleanupStaleMultipartUploadsInput> {\n public constructor(private readonly config: FileManagerServerConfig.Interface) {}\n\n public async run({\n controller\n }: TaskHandler.RunParams<CleanupStaleMultipartUploadsInput>): Promise<\n TaskDefinition.Result<CleanupStaleMultipartUploadsInput>\n > {\n if (controller.runtime.isAborted()) {\n return controller.response.aborted();\n }\n\n const storagePath = this.config.storagePath;\n const tenantsDir = path.join(storagePath, \"tenants\");\n const now = Date.now();\n\n const tenantDirs = await readdirSafe(tenantsDir);\n\n for (const tenantId of tenantDirs) {\n const multipartDir = path.join(tenantsDir, tenantId, \"multipart\");\n const uploadDirs = await readdirSafe(multipartDir);\n\n for (const uploadId of uploadDirs) {\n const uploadPath = path.join(multipartDir, uploadId);\n\n try {\n const stat = await fs.stat(uploadPath);\n const ageMs = now - stat.mtimeMs;\n\n if (ageMs > STALE_THRESHOLD_MS) {\n await fs.rm(uploadPath, { recursive: true, force: true });\n }\n } catch (err) {\n /* Skip entries that have already been removed or cannot be accessed. */\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n }\n }\n\n return controller.response.done();\n }\n}\n\nconst CleanupStaleMultipartUploadsTaskHandler = TaskHandler.createImplementation({\n implementation: CleanupStaleMultipartUploadsTaskHandlerImpl,\n dependencies: [FileManagerServerConfig]\n});\n\nclass CleanupStaleMultipartUploadsTaskImpl implements TaskDefinition.Interface {\n public readonly id = \"fileManagerCleanupStaleMultipartUploads\";\n public readonly title = \"Clean up stale multipart upload directories\";\n public readonly description =\n \"Removes multipart upload directories that are older than 24 hours.\";\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 handler = CleanupStaleMultipartUploadsTaskHandler;\n}\n\nexport const CleanupStaleMultipartUploadsTaskDefinition = TaskDefinition.createImplementation({\n implementation: CleanupStaleMultipartUploadsTaskImpl,\n dependencies: []\n});\n"],"names":["STALE_THRESHOLD_MS","readdirSafe","dirPath","fs","err","CleanupStaleMultipartUploadsTaskHandlerImpl","config","controller","storagePath","tenantsDir","path","now","Date","tenantDirs","tenantId","multipartDir","uploadDirs","uploadId","uploadPath","stat","ageMs","CleanupStaleMultipartUploadsTaskHandler","TaskHandler","FileManagerServerConfig","CleanupStaleMultipartUploadsTaskImpl","CleanupStaleMultipartUploadsTaskDefinition","TaskDefinition"],"mappings":";;;;AAaA,MAAMA,qBAAqB;AAG3B,eAAeC,YAAYC,OAAe;IACtC,IAAI;QACA,OAAO,MAAMC,SAAAA,OAAU,CAACD;IAC5B,EAAE,OAAOE,KAAK;QACV,IAAKA,AAAuC,aAAvCA,IAA8B,IAAI,EACnC,OAAO,EAAE;QAEb,MAAMA;IACV;AACJ;AAEA,MAAMC;IACF,YAAoCC,MAAyC,CAAE;aAA3CA,MAAM,GAANA;IAA4C;IAEhF,MAAa,IAAI,EACbC,UAAU,EAC6C,EAEzD;QACE,IAAIA,WAAW,OAAO,CAAC,SAAS,IAC5B,OAAOA,WAAW,QAAQ,CAAC,OAAO;QAGtC,MAAMC,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW;QAC3C,MAAMC,aAAaC,UAAAA,IAAS,CAACF,aAAa;QAC1C,MAAMG,MAAMC,KAAK,GAAG;QAEpB,MAAMC,aAAa,MAAMZ,YAAYQ;QAErC,KAAK,MAAMK,YAAYD,WAAY;YAC/B,MAAME,eAAeL,UAAAA,IAAS,CAACD,YAAYK,UAAU;YACrD,MAAME,aAAa,MAAMf,YAAYc;YAErC,KAAK,MAAME,YAAYD,WAAY;gBAC/B,MAAME,aAAaR,UAAAA,IAAS,CAACK,cAAcE;gBAE3C,IAAI;oBACA,MAAME,OAAO,MAAMhB,SAAAA,IAAO,CAACe;oBAC3B,MAAME,QAAQT,MAAMQ,KAAK,OAAO;oBAEhC,IAAIC,QAAQpB,oBACR,MAAMG,SAAAA,EAAK,CAACe,YAAY;wBAAE,WAAW;wBAAM,OAAO;oBAAK;gBAE/D,EAAE,OAAOd,KAAK;oBAEV,IAAKA,AAAuC,aAAvCA,IAA8B,IAAI,EACnC,MAAMA;gBAEd;YACJ;QACJ;QAEA,OAAOG,WAAW,QAAQ,CAAC,IAAI;IACnC;AACJ;AAEA,MAAMc,0CAA0CC,YAAY,oBAAoB,CAAC;IAC7E,gBAAgBjB;IAChB,cAAc;QAACkB;KAAwB;AAC3C;AAEA,MAAMC;;aACc,EAAE,GAAG;aACL,KAAK,GAAG;aACR,WAAW,GACvB;aACY,aAAa,GAAG;aAChB,SAAS,GAAG;aACZ,YAAY,GAAG;aACf,WAAW,GAAG;YAAC;YAAsB;SAAmB;aAExE,OAAO,GAAGH;;AACd;AAEO,MAAMI,6CAA6CC,eAAe,oBAAoB,CAAC;IAC1F,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
1
|
+
import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
2
2
|
import { UpdateFileUseCase } from "@webiny/api-file-manager/features/file/UpdateFile/index.js";
|
|
3
3
|
import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
|
|
4
4
|
import type { ExtractMetadataInput } from "@webiny/api-file-manager/features/extractMetadata/ExtractMetadataInput.js";
|
|
5
5
|
import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
|
|
6
|
-
declare class
|
|
6
|
+
declare class ExtractMetadataTaskHandlerImpl implements TaskHandler.Interface<ExtractMetadataInput> {
|
|
7
7
|
private readonly metadataReader;
|
|
8
8
|
private readonly updateFileUseCase;
|
|
9
9
|
private readonly config;
|
|
10
|
+
constructor(metadataReader: MetadataReader.Interface, updateFileUseCase: UpdateFileUseCase.Interface, config: FileManagerServerConfig.Interface);
|
|
11
|
+
run({ input, controller }: TaskHandler.RunParams<ExtractMetadataInput>): Promise<TaskDefinition.Result<ExtractMetadataInput>>;
|
|
12
|
+
private cleanValues;
|
|
13
|
+
}
|
|
14
|
+
declare class ExtractMetadataTaskImpl implements TaskDefinition.Interface {
|
|
10
15
|
readonly id = "fileManagerExtractMetadata";
|
|
11
16
|
readonly title = "Extract image metadata (dimensions, EXIF, IPTC)";
|
|
12
17
|
readonly description = "A task to extract metadata from uploaded image files";
|
|
@@ -14,9 +19,9 @@ declare class ExtractMetadataTaskImpl implements TaskDefinition.Interface<Extrac
|
|
|
14
19
|
readonly isPrivate = true;
|
|
15
20
|
readonly databaseLogs = false;
|
|
16
21
|
readonly selfCleanup: ("onAbort" | "onSuccess")[];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
handler: typeof ExtractMetadataTaskHandlerImpl & {
|
|
23
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
export declare const ExtractMetadataTaskDefinition: typeof ExtractMetadataTaskImpl & {
|
|
22
27
|
__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>>;
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import { promises } from "node:fs";
|
|
2
|
-
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
2
|
+
import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
3
3
|
import { UpdateFileUseCase } from "@webiny/api-file-manager/features/file/UpdateFile/index.js";
|
|
4
4
|
import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
|
|
5
5
|
import { FileManagerServerConfig } from "../FileManagerServerConfig/abstractions.js";
|
|
6
|
-
class
|
|
6
|
+
class ExtractMetadataTaskHandlerImpl {
|
|
7
7
|
constructor(metadataReader, updateFileUseCase, config){
|
|
8
8
|
this.metadataReader = metadataReader;
|
|
9
9
|
this.updateFileUseCase = updateFileUseCase;
|
|
10
10
|
this.config = config;
|
|
11
|
-
this.id = "fileManagerExtractMetadata";
|
|
12
|
-
this.title = "Extract image metadata (dimensions, EXIF, IPTC)";
|
|
13
|
-
this.description = "A task to extract metadata from uploaded image files";
|
|
14
|
-
this.maxIterations = 1;
|
|
15
|
-
this.isPrivate = true;
|
|
16
|
-
this.databaseLogs = false;
|
|
17
|
-
this.selfCleanup = [
|
|
18
|
-
"onSuccess",
|
|
19
|
-
"onAbort"
|
|
20
|
-
];
|
|
21
11
|
}
|
|
22
12
|
async run({ input, controller }) {
|
|
23
13
|
if (controller.runtime.isAborted()) return controller.response.aborted();
|
|
@@ -71,14 +61,33 @@ class ExtractMetadataTaskImpl {
|
|
|
71
61
|
return cleaned;
|
|
72
62
|
}
|
|
73
63
|
}
|
|
74
|
-
const
|
|
75
|
-
implementation:
|
|
64
|
+
const ExtractMetadataTaskHandler = TaskHandler.createImplementation({
|
|
65
|
+
implementation: ExtractMetadataTaskHandlerImpl,
|
|
76
66
|
dependencies: [
|
|
77
67
|
MetadataReader,
|
|
78
68
|
UpdateFileUseCase,
|
|
79
69
|
FileManagerServerConfig
|
|
80
70
|
]
|
|
81
71
|
});
|
|
72
|
+
class ExtractMetadataTaskImpl {
|
|
73
|
+
constructor(){
|
|
74
|
+
this.id = "fileManagerExtractMetadata";
|
|
75
|
+
this.title = "Extract image metadata (dimensions, EXIF, IPTC)";
|
|
76
|
+
this.description = "A task to extract metadata from uploaded image files";
|
|
77
|
+
this.maxIterations = 1;
|
|
78
|
+
this.isPrivate = true;
|
|
79
|
+
this.databaseLogs = false;
|
|
80
|
+
this.selfCleanup = [
|
|
81
|
+
"onSuccess",
|
|
82
|
+
"onAbort"
|
|
83
|
+
];
|
|
84
|
+
this.handler = ExtractMetadataTaskHandler;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const ExtractMetadataTaskDefinition = TaskDefinition.createImplementation({
|
|
88
|
+
implementation: ExtractMetadataTaskImpl,
|
|
89
|
+
dependencies: []
|
|
90
|
+
});
|
|
82
91
|
export { ExtractMetadataTaskDefinition };
|
|
83
92
|
|
|
84
93
|
//# sourceMappingURL=ExtractMetadataTask.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/ExtractMetadata/ExtractMetadataTask.js","sources":["../../../src/features/ExtractMetadata/ExtractMetadataTask.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport type { ExifTags } from \"exifreader\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/ExtractMetadata/ExtractMetadataTask.js","sources":["../../../src/features/ExtractMetadata/ExtractMetadataTask.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport type { ExifTags } from \"exifreader\";\nimport {\n TaskDefinition,\n TaskHandler\n} 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\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\n\nclass ExtractMetadataTaskHandlerImpl implements TaskHandler.Interface<ExtractMetadataInput> {\n public constructor(\n private readonly metadataReader: MetadataReader.Interface,\n private readonly updateFileUseCase: UpdateFileUseCase.Interface,\n private readonly config: FileManagerServerConfig.Interface\n ) {}\n\n public async run({\n input,\n controller\n }: TaskHandler.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 const storagePath = this.config.storagePath;\n const filePath = `${storagePath}/${fileMetadata.bucketKey}`;\n\n try {\n /* Read the image file from local disk. */\n const buffer = await fs.readFile(filePath);\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 /* 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, 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\nconst ExtractMetadataTaskHandler = TaskHandler.createImplementation({\n implementation: ExtractMetadataTaskHandlerImpl,\n dependencies: [MetadataReader, UpdateFileUseCase, FileManagerServerConfig]\n});\n\nclass ExtractMetadataTaskImpl implements TaskDefinition.Interface {\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 handler = ExtractMetadataTaskHandler;\n}\n\nexport const ExtractMetadataTaskDefinition = TaskDefinition.createImplementation({\n implementation: ExtractMetadataTaskImpl,\n dependencies: []\n});\n"],"names":["ExtractMetadataTaskHandlerImpl","metadataReader","updateFileUseCase","config","input","controller","fileMetadata","storagePath","filePath","buffer","fs","sharp","m","ExifReader","sharpInstance","sharpMetadata","tags","metadata","updateResult","error","Error","String","cleaned","key","tag","Object","undefined","Array","ExtractMetadataTaskHandler","TaskHandler","MetadataReader","UpdateFileUseCase","FileManagerServerConfig","ExtractMetadataTaskImpl","ExtractMetadataTaskDefinition","TaskDefinition"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/api-file-manager-server",
|
|
3
|
-
"version": "6.6.0-alpha.
|
|
3
|
+
"version": "6.6.0-alpha.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -14,22 +14,22 @@
|
|
|
14
14
|
"author": "Webiny Ltd",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@webiny/api-core": "6.6.0-alpha.
|
|
18
|
-
"@webiny/api-file-manager": "6.6.0-alpha.
|
|
19
|
-
"@webiny/api-graphql": "6.6.0-alpha.
|
|
20
|
-
"@webiny/background-tasks": "6.6.0-alpha.
|
|
21
|
-
"@webiny/event-handler-core": "6.6.0-alpha.
|
|
22
|
-
"@webiny/feature": "6.6.0-alpha.
|
|
23
|
-
"@webiny/handler": "6.6.0-alpha.
|
|
24
|
-
"@webiny/plugins": "6.6.0-alpha.
|
|
25
|
-
"@webiny/utils": "6.6.0-alpha.
|
|
26
|
-
"@webiny/validation": "6.6.0-alpha.
|
|
17
|
+
"@webiny/api-core": "6.6.0-alpha.3",
|
|
18
|
+
"@webiny/api-file-manager": "6.6.0-alpha.3",
|
|
19
|
+
"@webiny/api-graphql": "6.6.0-alpha.3",
|
|
20
|
+
"@webiny/background-tasks": "6.6.0-alpha.3",
|
|
21
|
+
"@webiny/event-handler-core": "6.6.0-alpha.3",
|
|
22
|
+
"@webiny/feature": "6.6.0-alpha.3",
|
|
23
|
+
"@webiny/handler": "6.6.0-alpha.3",
|
|
24
|
+
"@webiny/plugins": "6.6.0-alpha.3",
|
|
25
|
+
"@webiny/utils": "6.6.0-alpha.3",
|
|
26
|
+
"@webiny/validation": "6.6.0-alpha.3",
|
|
27
27
|
"exifreader": "4.43.0",
|
|
28
28
|
"p-map": "7.0.6",
|
|
29
29
|
"sharp": "0.35.3"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@webiny/build-tools": "6.6.0-alpha.
|
|
32
|
+
"@webiny/build-tools": "6.6.0-alpha.3",
|
|
33
33
|
"rimraf": "6.1.3",
|
|
34
34
|
"typescript": "7.0.2",
|
|
35
35
|
"vitest": "4.1.11"
|