@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.
- package/FileManagerServerFeature.d.ts +5 -0
- package/FileManagerServerFeature.js +41 -0
- package/FileManagerServerFeature.js.map +1 -0
- package/assetDelivery/LocalAssetResolver.d.ts +6 -4
- package/assetDelivery/LocalAssetResolver.js +9 -9
- package/assetDelivery/LocalAssetResolver.js.map +1 -1
- package/assetDelivery/LocalOutputStrategy.d.ts +3 -2
- package/assetDelivery/LocalOutputStrategy.js +4 -4
- package/assetDelivery/LocalOutputStrategy.js.map +1 -1
- package/assetDelivery/LocalSharpTransform.d.ts +8 -14
- package/assetDelivery/LocalSharpTransform.js +72 -98
- package/assetDelivery/LocalSharpTransform.js.map +1 -1
- package/assetDelivery/abstractions.d.ts +0 -3
- package/assetDelivery/abstractions.js +1 -2
- package/assetDelivery/abstractions.js.map +1 -1
- package/assetDelivery/assetDeliveryConfig.d.ts +1 -1
- package/assetDelivery/feature.js +7 -9
- package/assetDelivery/feature.js.map +1 -1
- package/assetDelivery/types.d.ts +0 -3
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.d.ts +3 -0
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js +18 -14
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js.map +1 -1
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +7 -5
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +8 -5
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -1
- package/features/CompleteMultiPartUpload/feature.js +2 -2
- package/features/CompleteMultiPartUpload/feature.js.map +1 -1
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +7 -7
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +9 -10
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -1
- package/features/CreateMultiPartUpload/feature.js +2 -2
- package/features/CreateMultiPartUpload/feature.js.map +1 -1
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.d.ts +3 -1
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js +6 -3
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js.map +1 -1
- package/features/ExtractMetadata/ExtractMetadataTask.d.ts +3 -1
- package/features/ExtractMetadata/ExtractMetadataTask.js +6 -3
- package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
- package/features/FileManagerServerConfig/FileManagerServerConfig.d.ts +12 -0
- package/features/FileManagerServerConfig/FileManagerServerConfig.js +28 -0
- package/features/FileManagerServerConfig/FileManagerServerConfig.js.map +1 -0
- package/features/FileManagerServerConfig/abstractions.d.ts +10 -0
- package/features/FileManagerServerConfig/abstractions.js +5 -0
- package/features/FileManagerServerConfig/abstractions.js.map +1 -0
- package/features/FileManagerServerConfig/feature.d.ts +4 -0
- package/features/FileManagerServerConfig/feature.js +11 -0
- package/features/FileManagerServerConfig/feature.js.map +1 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +7 -5
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +8 -5
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -1
- package/features/GetFileContentsById/feature.js +2 -2
- package/features/GetFileContentsById/feature.js.map +1 -1
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +7 -5
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +8 -5
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -1
- package/features/GetFileContentsByKey/feature.js +2 -2
- package/features/GetFileContentsByKey/feature.js.map +1 -1
- package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +6 -6
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js +8 -9
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -1
- package/features/GetUploadPayload/feature.js +2 -2
- package/features/GetUploadPayload/feature.js.map +1 -1
- package/graphql/ServerGraphQLSchema.d.ts +15 -0
- package/graphql/ServerGraphQLSchema.js +221 -0
- package/graphql/ServerGraphQLSchema.js.map +1 -0
- package/index.d.ts +1 -2
- package/index.js +1 -40
- package/package.json +13 -13
- package/routes/UploadPartRoute/UploadPartRoute.d.ts +14 -0
- package/routes/UploadPartRoute/UploadPartRoute.js +66 -0
- package/routes/UploadPartRoute/UploadPartRoute.js.map +1 -0
- package/routes/UploadPartRoute/feature.d.ts +4 -0
- package/routes/UploadPartRoute/feature.js +11 -0
- package/routes/UploadPartRoute/feature.js.map +1 -0
- package/routes/UploadSingleFileRoute/UploadSingleFileRoute.d.ts +14 -0
- package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js +70 -0
- package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js.map +1 -0
- package/routes/UploadSingleFileRoute/feature.d.ts +4 -0
- package/routes/UploadSingleFileRoute/feature.js +11 -0
- package/routes/UploadSingleFileRoute/feature.js.map +1 -0
- package/routes/utils.d.ts +20 -0
- package/routes/utils.js +62 -0
- package/routes/utils.js.map +1 -0
- package/index.js.map +0 -1
- package/routes/uploadRoutes.d.ts +0 -4
- package/routes/uploadRoutes.js +0 -130
- package/routes/uploadRoutes.js.map +0 -1
- package/utils/resolveServerUrl.d.ts +0 -2
- package/utils/resolveServerUrl.js +0 -10
- package/utils/resolveServerUrl.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features/FileManagerServerConfig/feature.js","sources":["../../../src/features/FileManagerServerConfig/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { FileManagerServerConfig } from \"./FileManagerServerConfig.js\";\n\nexport const FileManagerServerConfigFeature = createFeature({\n name: \"FileManagerServer/Config\",\n register(container) {\n container.register(FileManagerServerConfig);\n }\n});\n"],"names":["FileManagerServerConfigFeature","createFeature","container","FileManagerServerConfig"],"mappings":";;AAGO,MAAMA,iCAAiCC,cAAc;IACxD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
|
-
import { GetFileContentsByIdUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
|
|
2
|
+
import { GetFileContentsByIdUseCase as GetFileContentsByIdUseCaseAbstraction } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
|
|
3
3
|
import type { FileContents } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
|
|
4
4
|
import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
|
|
5
|
-
|
|
5
|
+
import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
|
|
6
|
+
declare class GetFileContentsByIdUseCaseImpl implements GetFileContentsByIdUseCaseAbstraction.Interface {
|
|
6
7
|
private readonly metadataReader;
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
private readonly config;
|
|
9
|
+
constructor(metadataReader: MetadataReader.Interface, config: FileManagerServerConfig.Interface);
|
|
10
|
+
execute(fileId: string): Promise<Result<FileContents, GetFileContentsByIdUseCaseAbstraction.Error>>;
|
|
9
11
|
}
|
|
10
|
-
export declare const
|
|
12
|
+
export declare const GetFileContentsByIdUseCase: typeof GetFileContentsByIdUseCaseImpl & {
|
|
11
13
|
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/file/GetFileContentsById/abstractions").IGetFileContentsByIdUseCase>;
|
|
12
14
|
};
|
|
13
15
|
export {};
|
|
@@ -3,14 +3,16 @@ import { Result } from "@webiny/feature/api";
|
|
|
3
3
|
import { GetFileContentsByIdUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
|
|
4
4
|
import { FileNotFoundError, FilePersistenceError } from "@webiny/api-file-manager/domain/file/errors.js";
|
|
5
5
|
import { MetadataReader } from "@webiny/api-file-manager/features/upload/ReadFileMetadata/abstractions.js";
|
|
6
|
+
import { FileManagerServerConfig } from "../FileManagerServerConfig/abstractions.js";
|
|
6
7
|
class GetFileContentsByIdUseCaseImpl {
|
|
7
|
-
constructor(metadataReader){
|
|
8
|
+
constructor(metadataReader, config){
|
|
8
9
|
this.metadataReader = metadataReader;
|
|
10
|
+
this.config = config;
|
|
9
11
|
}
|
|
10
12
|
async execute(fileId) {
|
|
11
13
|
const metadata = await this.metadataReader.read(fileId);
|
|
12
14
|
if (!metadata) return Result.fail(new FileNotFoundError(fileId));
|
|
13
|
-
const storagePath =
|
|
15
|
+
const storagePath = this.config.storagePath;
|
|
14
16
|
try {
|
|
15
17
|
const filePath = `${storagePath}/${metadata.bucketKey}`;
|
|
16
18
|
const buffer = await promises.readFile(filePath);
|
|
@@ -24,12 +26,13 @@ class GetFileContentsByIdUseCaseImpl {
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
const
|
|
29
|
+
const GetFileContentsByIdUseCase_GetFileContentsByIdUseCase = GetFileContentsByIdUseCase.createImplementation({
|
|
28
30
|
implementation: GetFileContentsByIdUseCaseImpl,
|
|
29
31
|
dependencies: [
|
|
30
|
-
MetadataReader
|
|
32
|
+
MetadataReader,
|
|
33
|
+
FileManagerServerConfig
|
|
31
34
|
]
|
|
32
35
|
});
|
|
33
|
-
export {
|
|
36
|
+
export { GetFileContentsByIdUseCase_GetFileContentsByIdUseCase as GetFileContentsByIdUseCase };
|
|
34
37
|
|
|
35
38
|
//# sourceMappingURL=GetFileContentsByIdUseCase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetFileContentsById/GetFileContentsByIdUseCase.js","sources":["../../../src/features/GetFileContentsById/GetFileContentsByIdUseCase.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { Result } from \"@webiny/feature/api\";\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
|
|
1
|
+
{"version":3,"file":"features/GetFileContentsById/GetFileContentsByIdUseCase.js","sources":["../../../src/features/GetFileContentsById/GetFileContentsByIdUseCase.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { Result } from \"@webiny/feature/api\";\nimport { GetFileContentsByIdUseCase as GetFileContentsByIdUseCaseAbstraction } 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\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\n\nclass GetFileContentsByIdUseCaseImpl implements GetFileContentsByIdUseCaseAbstraction.Interface {\n private readonly metadataReader: MetadataReader.Interface;\n private readonly config: FileManagerServerConfig.Interface;\n\n public constructor(\n metadataReader: MetadataReader.Interface,\n config: FileManagerServerConfig.Interface\n ) {\n this.metadataReader = metadataReader;\n this.config = config;\n }\n\n public async execute(\n fileId: string\n ): Promise<Result<FileContents, GetFileContentsByIdUseCaseAbstraction.Error>> {\n const metadata = await this.metadataReader.read(fileId);\n if (!metadata) {\n return Result.fail(new FileNotFoundError(fileId));\n }\n\n const storagePath = this.config.storagePath;\n\n try {\n const filePath = `${storagePath}/${metadata.bucketKey}`;\n const buffer = await fs.readFile(filePath);\n return Result.ok({ buffer, contentType: metadata.contentType });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return Result.fail(new FileNotFoundError(fileId));\n }\n return Result.fail(\n new FilePersistenceError(error instanceof Error ? error : new Error(String(error)))\n );\n }\n }\n}\n\nexport const GetFileContentsByIdUseCase =\n GetFileContentsByIdUseCaseAbstraction.createImplementation({\n implementation: GetFileContentsByIdUseCaseImpl,\n dependencies: [MetadataReader, FileManagerServerConfig]\n });\n"],"names":["GetFileContentsByIdUseCaseImpl","metadataReader","config","fileId","metadata","Result","FileNotFoundError","storagePath","filePath","buffer","fs","error","FilePersistenceError","Error","String","GetFileContentsByIdUseCase","GetFileContentsByIdUseCaseAbstraction","MetadataReader","FileManagerServerConfig"],"mappings":";;;;;;AAWA,MAAMA;IAIF,YACIC,cAAwC,EACxCC,MAAyC,CAC3C;QACE,IAAI,CAAC,cAAc,GAAGD;QACtB,IAAI,CAAC,MAAM,GAAGC;IAClB;IAEA,MAAa,QACTC,MAAc,EAC4D;QAC1E,MAAMC,WAAW,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAACD;QAChD,IAAI,CAACC,UACD,OAAOC,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;QAG7C,MAAMI,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW;QAE3C,IAAI;YACA,MAAMC,WAAW,GAAGD,YAAY,CAAC,EAAEH,SAAS,SAAS,EAAE;YACvD,MAAMK,SAAS,MAAMC,SAAAA,QAAW,CAACF;YACjC,OAAOH,OAAO,EAAE,CAAC;gBAAEI;gBAAQ,aAAaL,SAAS,WAAW;YAAC;QACjE,EAAE,OAAOO,OAAO;YACZ,IAAKA,AAAyC,aAAzCA,MAAgC,IAAI,EACrC,OAAON,OAAO,IAAI,CAAC,IAAIC,kBAAkBH;YAE7C,OAAOE,OAAO,IAAI,CACd,IAAIO,qBAAqBD,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH;QAEnF;IACJ;AACJ;AAEO,MAAMI,wDACTC,2BAAAA,oBAA0D,CAAC;IACvD,gBAAgBhB;IAChB,cAAc;QAACiB;QAAgBC;KAAwB;AAC3D"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createFeature } from "@webiny/feature/api";
|
|
2
|
-
import {
|
|
2
|
+
import { GetFileContentsByIdUseCase } from "./GetFileContentsByIdUseCase.js";
|
|
3
3
|
const GetFileContentsByIdFeature = createFeature({
|
|
4
4
|
name: "FileManagerServer/GetFileContentsById",
|
|
5
5
|
register (container) {
|
|
6
|
-
container.register(
|
|
6
|
+
container.register(GetFileContentsByIdUseCase);
|
|
7
7
|
}
|
|
8
8
|
});
|
|
9
9
|
export { GetFileContentsByIdFeature };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetFileContentsById/feature.js","sources":["../../../src/features/GetFileContentsById/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/GetFileContentsById/feature.js","sources":["../../../src/features/GetFileContentsById/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { GetFileContentsByIdUseCase } from \"./GetFileContentsByIdUseCase.js\";\n\nexport const GetFileContentsByIdFeature = createFeature({\n name: \"FileManagerServer/GetFileContentsById\",\n register(container) {\n container.register(GetFileContentsByIdUseCase);\n }\n});\n"],"names":["GetFileContentsByIdFeature","createFeature","container","GetFileContentsByIdUseCase"],"mappings":";;AAGO,MAAMA,6BAA6BC,cAAc;IACpD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
3
|
-
import { GetFileContentsByKeyUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsByKey/index.js";
|
|
3
|
+
import { GetFileContentsByKeyUseCase as GetFileContentsByKeyUseCaseAbstraction } from "@webiny/api-file-manager/features/file/GetFileContentsByKey/index.js";
|
|
4
4
|
import type { FileContents } from "@webiny/api-file-manager/features/file/GetFileContentsById/index.js";
|
|
5
|
-
|
|
5
|
+
import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
|
|
6
|
+
declare class GetFileContentsByKeyUseCaseImpl implements GetFileContentsByKeyUseCaseAbstraction.Interface {
|
|
6
7
|
private readonly tenantContext;
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
private readonly config;
|
|
9
|
+
constructor(tenantContext: TenantContext.Interface, config: FileManagerServerConfig.Interface);
|
|
10
|
+
execute(key: string): Promise<Result<FileContents, GetFileContentsByKeyUseCaseAbstraction.Error>>;
|
|
9
11
|
}
|
|
10
|
-
export declare const
|
|
12
|
+
export declare const GetFileContentsByKeyUseCase: typeof GetFileContentsByKeyUseCaseImpl & {
|
|
11
13
|
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/file/GetFileContentsByKey/abstractions").IGetFileContentsByKeyUseCase>;
|
|
12
14
|
};
|
|
13
15
|
export {};
|
|
@@ -3,6 +3,7 @@ import { Result } from "@webiny/feature/api";
|
|
|
3
3
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
4
4
|
import { GetFileContentsByKeyUseCase } from "@webiny/api-file-manager/features/file/GetFileContentsByKey/index.js";
|
|
5
5
|
import { FileNotFoundError, FilePersistenceError } from "@webiny/api-file-manager/domain/file/errors.js";
|
|
6
|
+
import { FileManagerServerConfig } from "../FileManagerServerConfig/abstractions.js";
|
|
6
7
|
const CONTENT_TYPE_MAP = {
|
|
7
8
|
jpg: "image/jpeg",
|
|
8
9
|
jpeg: "image/jpeg",
|
|
@@ -37,13 +38,14 @@ function resolveContentType(key) {
|
|
|
37
38
|
return CONTENT_TYPE_MAP[ext] ?? "application/octet-stream";
|
|
38
39
|
}
|
|
39
40
|
class GetFileContentsByKeyUseCaseImpl {
|
|
40
|
-
constructor(tenantContext){
|
|
41
|
+
constructor(tenantContext, config){
|
|
41
42
|
this.tenantContext = tenantContext;
|
|
43
|
+
this.config = config;
|
|
42
44
|
}
|
|
43
45
|
async execute(key) {
|
|
44
46
|
const tenant = this.tenantContext.getTenant();
|
|
45
47
|
const bucketKey = `tenants/${tenant.id}/files/${key}`;
|
|
46
|
-
const storagePath =
|
|
48
|
+
const storagePath = this.config.storagePath;
|
|
47
49
|
const filePath = `${storagePath}/${bucketKey}`;
|
|
48
50
|
try {
|
|
49
51
|
const buffer = await promises.readFile(filePath);
|
|
@@ -58,12 +60,13 @@ class GetFileContentsByKeyUseCaseImpl {
|
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
|
-
const
|
|
63
|
+
const GetFileContentsByKeyUseCase_GetFileContentsByKeyUseCase = GetFileContentsByKeyUseCase.createImplementation({
|
|
62
64
|
implementation: GetFileContentsByKeyUseCaseImpl,
|
|
63
65
|
dependencies: [
|
|
64
|
-
TenantContext
|
|
66
|
+
TenantContext,
|
|
67
|
+
FileManagerServerConfig
|
|
65
68
|
]
|
|
66
69
|
});
|
|
67
|
-
export {
|
|
70
|
+
export { GetFileContentsByKeyUseCase_GetFileContentsByKeyUseCase as GetFileContentsByKeyUseCase };
|
|
68
71
|
|
|
69
72
|
//# sourceMappingURL=GetFileContentsByKeyUseCase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js","sources":["../../../src/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { Result } from \"@webiny/feature/api\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { GetFileContentsByKeyUseCase } from \"@webiny/api-file-manager/features/file/GetFileContentsByKey/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\";\n\nconst CONTENT_TYPE_MAP: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n pdf: \"application/pdf\",\n json: \"application/json\",\n xml: \"application/xml\",\n zip: \"application/zip\",\n gz: \"application/gzip\",\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n js: \"application/javascript\",\n ts: \"application/typescript\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\"\n};\n\nfunction resolveContentType(key: string): string {\n const ext = key.split(\".\").pop()?.toLowerCase();\n if (!ext) {\n return \"application/octet-stream\";\n }\n return CONTENT_TYPE_MAP[ext] ?? \"application/octet-stream\";\n}\n\nclass GetFileContentsByKeyUseCaseImpl implements
|
|
1
|
+
{"version":3,"file":"features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js","sources":["../../../src/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { Result } from \"@webiny/feature/api\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { GetFileContentsByKeyUseCase as GetFileContentsByKeyUseCaseAbstraction } from \"@webiny/api-file-manager/features/file/GetFileContentsByKey/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 { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\n\nconst CONTENT_TYPE_MAP: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n pdf: \"application/pdf\",\n json: \"application/json\",\n xml: \"application/xml\",\n zip: \"application/zip\",\n gz: \"application/gzip\",\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n js: \"application/javascript\",\n ts: \"application/typescript\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\"\n};\n\nfunction resolveContentType(key: string): string {\n const ext = key.split(\".\").pop()?.toLowerCase();\n if (!ext) {\n return \"application/octet-stream\";\n }\n return CONTENT_TYPE_MAP[ext] ?? \"application/octet-stream\";\n}\n\nclass GetFileContentsByKeyUseCaseImpl implements GetFileContentsByKeyUseCaseAbstraction.Interface {\n constructor(\n private readonly tenantContext: TenantContext.Interface,\n private readonly config: FileManagerServerConfig.Interface\n ) {}\n\n async execute(\n key: string\n ): Promise<Result<FileContents, GetFileContentsByKeyUseCaseAbstraction.Error>> {\n const tenant = this.tenantContext.getTenant();\n const bucketKey = `tenants/${tenant.id}/files/${key}`;\n const storagePath = this.config.storagePath;\n const filePath = `${storagePath}/${bucketKey}`;\n\n try {\n const buffer = await fs.readFile(filePath);\n const contentType = resolveContentType(key);\n return Result.ok({ buffer, contentType });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return Result.fail(new FileNotFoundError(key));\n }\n return Result.fail(\n new FilePersistenceError(error instanceof Error ? error : new Error(String(error)))\n );\n }\n }\n}\n\nexport const GetFileContentsByKeyUseCase =\n GetFileContentsByKeyUseCaseAbstraction.createImplementation({\n implementation: GetFileContentsByKeyUseCaseImpl,\n dependencies: [TenantContext, FileManagerServerConfig]\n });\n"],"names":["CONTENT_TYPE_MAP","resolveContentType","key","ext","GetFileContentsByKeyUseCaseImpl","tenantContext","config","tenant","bucketKey","storagePath","filePath","buffer","fs","contentType","Result","error","FileNotFoundError","FilePersistenceError","Error","String","GetFileContentsByKeyUseCase","GetFileContentsByKeyUseCaseAbstraction","TenantContext","FileManagerServerConfig"],"mappings":";;;;;;AAWA,MAAMA,mBAA2C;IAC7C,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,IAAI;IACJ,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;AACT;AAEA,SAASC,mBAAmBC,GAAW;IACnC,MAAMC,MAAMD,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI;IAClC,IAAI,CAACC,KACD,OAAO;IAEX,OAAOH,gBAAgB,CAACG,IAAI,IAAI;AACpC;AAEA,MAAMC;IACF,YACqBC,aAAsC,EACtCC,MAAyC,CAC5D;aAFmBD,aAAa,GAAbA;aACAC,MAAM,GAANA;IAClB;IAEH,MAAM,QACFJ,GAAW,EACgE;QAC3E,MAAMK,SAAS,IAAI,CAAC,aAAa,CAAC,SAAS;QAC3C,MAAMC,YAAY,CAAC,QAAQ,EAAED,OAAO,EAAE,CAAC,OAAO,EAAEL,KAAK;QACrD,MAAMO,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW;QAC3C,MAAMC,WAAW,GAAGD,YAAY,CAAC,EAAED,WAAW;QAE9C,IAAI;YACA,MAAMG,SAAS,MAAMC,SAAAA,QAAW,CAACF;YACjC,MAAMG,cAAcZ,mBAAmBC;YACvC,OAAOY,OAAO,EAAE,CAAC;gBAAEH;gBAAQE;YAAY;QAC3C,EAAE,OAAOE,OAAO;YACZ,IAAKA,AAAyC,aAAzCA,MAAgC,IAAI,EACrC,OAAOD,OAAO,IAAI,CAAC,IAAIE,kBAAkBd;YAE7C,OAAOY,OAAO,IAAI,CACd,IAAIG,qBAAqBF,iBAAiBG,QAAQH,QAAQ,IAAIG,MAAMC,OAAOJ;QAEnF;IACJ;AACJ;AAEO,MAAMK,0DACTC,4BAAAA,oBAA2D,CAAC;IACxD,gBAAgBjB;IAChB,cAAc;QAACkB;QAAeC;KAAwB;AAC1D"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createFeature } from "@webiny/feature/api";
|
|
2
|
-
import {
|
|
2
|
+
import { GetFileContentsByKeyUseCase } from "./GetFileContentsByKeyUseCase.js";
|
|
3
3
|
const GetFileContentsByKeyFeature = createFeature({
|
|
4
4
|
name: "FileManagerServer/GetFileContentsByKey",
|
|
5
5
|
register (container) {
|
|
6
|
-
container.register(
|
|
6
|
+
container.register(GetFileContentsByKeyUseCase);
|
|
7
7
|
}
|
|
8
8
|
});
|
|
9
9
|
export { GetFileContentsByKeyFeature };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetFileContentsByKey/feature.js","sources":["../../../src/features/GetFileContentsByKey/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/GetFileContentsByKey/feature.js","sources":["../../../src/features/GetFileContentsByKey/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { GetFileContentsByKeyUseCase } from \"./GetFileContentsByKeyUseCase.js\";\n\nexport const GetFileContentsByKeyFeature = createFeature({\n name: \"FileManagerServer/GetFileContentsByKey\",\n register(container) {\n container.register(GetFileContentsByKeyUseCase);\n }\n});\n"],"names":["GetFileContentsByKeyFeature","createFeature","container","GetFileContentsByKeyUseCase"],"mappings":";;AAGO,MAAMA,8BAA8BC,cAAc;IACrD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { GetUploadPayloadUseCase } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
|
|
2
|
+
import { GetUploadPayloadUseCase as GetUploadPayloadUseCaseAbstraction } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
|
|
4
3
|
import type { FileData } from "@webiny/api-file-manager/features/upload/types.js";
|
|
5
4
|
import type { UploadPayloadResponse } from "@webiny/api-file-manager/features/upload/types.js";
|
|
6
5
|
import type { FileManagerSettings } from "@webiny/api-file-manager/domain/settings/types.js";
|
|
7
|
-
|
|
6
|
+
import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
|
|
7
|
+
declare class GetUploadPayloadUseCaseImpl implements GetUploadPayloadUseCaseAbstraction.Interface {
|
|
8
8
|
private readonly tenantContext;
|
|
9
|
-
private readonly
|
|
10
|
-
constructor(tenantContext: TenantContext.Interface,
|
|
9
|
+
private readonly config;
|
|
10
|
+
constructor(tenantContext: TenantContext.Interface, config: FileManagerServerConfig.Interface);
|
|
11
11
|
execute(file: FileData, settings: FileManagerSettings): Promise<UploadPayloadResponse>;
|
|
12
12
|
}
|
|
13
|
-
export declare const
|
|
13
|
+
export declare const GetUploadPayloadUseCase: typeof GetUploadPayloadUseCaseImpl & {
|
|
14
14
|
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-file-manager/features/upload/GetUploadPayload/abstractions").IGetUploadPayloadUseCase>;
|
|
15
15
|
};
|
|
16
16
|
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { validation } from "@webiny/validation";
|
|
2
2
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
3
|
-
import { Request } from "@webiny/handler/abstractions/Request.js";
|
|
4
3
|
import { GetUploadPayloadUseCase } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
|
|
5
4
|
import { createUploadToken } from "../../utils/uploadToken.js";
|
|
6
|
-
import {
|
|
5
|
+
import { FileManagerServerConfig } from "../FileManagerServerConfig/abstractions.js";
|
|
7
6
|
const UPLOAD_MAX_FILE_SIZE_DEFAULT = 1099511627776;
|
|
8
7
|
const sanitizeFileSizeValue = (value, defaultValue)=>{
|
|
9
8
|
try {
|
|
@@ -14,16 +13,16 @@ const sanitizeFileSizeValue = (value, defaultValue)=>{
|
|
|
14
13
|
}
|
|
15
14
|
};
|
|
16
15
|
class GetUploadPayloadUseCaseImpl {
|
|
17
|
-
constructor(tenantContext,
|
|
16
|
+
constructor(tenantContext, config){
|
|
18
17
|
this.tenantContext = tenantContext;
|
|
19
|
-
this.
|
|
18
|
+
this.config = config;
|
|
20
19
|
}
|
|
21
20
|
async execute(file, settings) {
|
|
22
21
|
const uploadMinFileSize = sanitizeFileSizeValue(settings.uploadMinFileSize, 0);
|
|
23
22
|
const uploadMaxFileSize = sanitizeFileSizeValue(settings.uploadMaxFileSize, UPLOAD_MAX_FILE_SIZE_DEFAULT);
|
|
24
23
|
const tenant = this.tenantContext.getTenant();
|
|
25
24
|
const storageKey = `tenants/${tenant.id}/files/${file.key}`;
|
|
26
|
-
const secret =
|
|
25
|
+
const secret = this.config.uploadSecret;
|
|
27
26
|
const expiresAt = Date.now() + 60000;
|
|
28
27
|
const token = createUploadToken({
|
|
29
28
|
key: storageKey,
|
|
@@ -32,7 +31,7 @@ class GetUploadPayloadUseCaseImpl {
|
|
|
32
31
|
uploadMinFileSize,
|
|
33
32
|
uploadMaxFileSize
|
|
34
33
|
}, secret);
|
|
35
|
-
const serverUrl =
|
|
34
|
+
const serverUrl = this.config.apiUrl;
|
|
36
35
|
const data = {
|
|
37
36
|
url: `${serverUrl}/webiny-file-upload`,
|
|
38
37
|
fields: {
|
|
@@ -46,13 +45,13 @@ class GetUploadPayloadUseCaseImpl {
|
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
|
-
const
|
|
48
|
+
const GetUploadPayloadUseCase_GetUploadPayloadUseCase = GetUploadPayloadUseCase.createImplementation({
|
|
50
49
|
implementation: GetUploadPayloadUseCaseImpl,
|
|
51
50
|
dependencies: [
|
|
52
51
|
TenantContext,
|
|
53
|
-
|
|
52
|
+
FileManagerServerConfig
|
|
54
53
|
]
|
|
55
54
|
});
|
|
56
|
-
export {
|
|
55
|
+
export { GetUploadPayloadUseCase_GetUploadPayloadUseCase as GetUploadPayloadUseCase };
|
|
57
56
|
|
|
58
57
|
//# sourceMappingURL=GetUploadPayloadUseCase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetUploadPayload/GetUploadPayloadUseCase.js","sources":["../../../src/features/GetUploadPayload/GetUploadPayloadUseCase.ts"],"sourcesContent":["import { validation } from \"@webiny/validation\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/GetUploadPayload/GetUploadPayloadUseCase.js","sources":["../../../src/features/GetUploadPayload/GetUploadPayloadUseCase.ts"],"sourcesContent":["import { validation } from \"@webiny/validation\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { GetUploadPayloadUseCase as GetUploadPayloadUseCaseAbstraction } 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\";\nimport { createUploadToken } from \"~/utils/uploadToken.js\";\nimport { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.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 GetUploadPayloadUseCaseAbstraction.Interface {\n public constructor(\n private readonly tenantContext: TenantContext.Interface,\n private readonly config: FileManagerServerConfig.Interface\n ) {}\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 const secret = this.config.uploadSecret;\n const expiresAt = Date.now() + 60_000;\n\n const token = createUploadToken(\n {\n key: storageKey,\n tenantId: tenant.id,\n expiresAt,\n uploadMinFileSize,\n uploadMaxFileSize\n },\n secret\n );\n\n const serverUrl = this.config.apiUrl;\n\n const data = {\n url: `${serverUrl}/webiny-file-upload`,\n fields: {\n key: storageKey,\n token\n }\n };\n\n return {\n data: data as unknown as Record<string, unknown>,\n file\n };\n }\n}\n\nexport const GetUploadPayloadUseCase = GetUploadPayloadUseCaseAbstraction.createImplementation({\n implementation: GetUploadPayloadUseCaseImpl,\n dependencies: [TenantContext, FileManagerServerConfig]\n});\n"],"names":["UPLOAD_MAX_FILE_SIZE_DEFAULT","sanitizeFileSizeValue","value","defaultValue","validation","GetUploadPayloadUseCaseImpl","tenantContext","config","file","settings","uploadMinFileSize","uploadMaxFileSize","tenant","storageKey","secret","expiresAt","Date","token","createUploadToken","serverUrl","data","GetUploadPayloadUseCase","GetUploadPayloadUseCaseAbstraction","TenantContext","FileManagerServerConfig"],"mappings":";;;;;AASA,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,YACqBC,aAAsC,EACtCC,MAAyC,CAC5D;aAFmBD,aAAa,GAAbA;aACAC,MAAM,GAANA;IAClB;IAEH,MAAa,QACTC,IAAc,EACdC,QAA6B,EACC;QAC9B,MAAMC,oBAAoBT,sBAAsBQ,SAAS,iBAAiB,EAAE;QAC5E,MAAME,oBAAoBV,sBACtBQ,SAAS,iBAAiB,EAC1BT;QAGJ,MAAMY,SAAS,IAAI,CAAC,aAAa,CAAC,SAAS;QAC3C,MAAMC,aAAa,CAAC,QAAQ,EAAED,OAAO,EAAE,CAAC,OAAO,EAAEJ,KAAK,GAAG,EAAE;QAC3D,MAAMM,SAAS,IAAI,CAAC,MAAM,CAAC,YAAY;QACvC,MAAMC,YAAYC,KAAK,GAAG,KAAK;QAE/B,MAAMC,QAAQC,kBACV;YACI,KAAKL;YACL,UAAUD,OAAO,EAAE;YACnBG;YACAL;YACAC;QACJ,GACAG;QAGJ,MAAMK,YAAY,IAAI,CAAC,MAAM,CAAC,MAAM;QAEpC,MAAMC,OAAO;YACT,KAAK,GAAGD,UAAU,mBAAmB,CAAC;YACtC,QAAQ;gBACJ,KAAKN;gBACLI;YACJ;QACJ;QAEA,OAAO;YACH,MAAMG;YACNZ;QACJ;IACJ;AACJ;AAEO,MAAMa,kDAA0BC,wBAAAA,oBAAuD,CAAC;IAC3F,gBAAgBjB;IAChB,cAAc;QAACkB;QAAeC;KAAwB;AAC1D"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createFeature } from "@webiny/feature/api";
|
|
2
|
-
import {
|
|
2
|
+
import { GetUploadPayloadUseCase } from "./GetUploadPayloadUseCase.js";
|
|
3
3
|
const GetUploadPayloadFeature = createFeature({
|
|
4
4
|
name: "FileManagerServer/GetUploadPayload",
|
|
5
5
|
register (container) {
|
|
6
|
-
container.register(
|
|
6
|
+
container.register(GetUploadPayloadUseCase);
|
|
7
7
|
}
|
|
8
8
|
});
|
|
9
9
|
export { GetUploadPayloadFeature };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/GetUploadPayload/feature.js","sources":["../../../src/features/GetUploadPayload/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/GetUploadPayload/feature.js","sources":["../../../src/features/GetUploadPayload/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { GetUploadPayloadUseCase } from \"./GetUploadPayloadUseCase.js\";\n\nexport const GetUploadPayloadFeature = createFeature({\n name: \"FileManagerServer/GetUploadPayload\",\n register(container) {\n container.register(GetUploadPayloadUseCase);\n }\n});\n"],"names":["GetUploadPayloadFeature","createFeature","container","GetUploadPayloadUseCase"],"mappings":";;AAGO,MAAMA,0BAA0BC,cAAc;IACjD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CoreGraphQLSchemaFactory } from "@webiny/api-graphql/graphql/abstractions.js";
|
|
2
|
+
import { GraphQLSchemaBuilder } from "@webiny/api-graphql/features/GraphQLSchemaBuilder/abstractions.js";
|
|
3
|
+
/**
|
|
4
|
+
* Upload GraphQL for the self-hosted (server) hosting type. Mirrors the SDL that `api-file-manager-s3`'s
|
|
5
|
+
* `S3GraphQLSchema` contributes (same query/mutation names + `PreSignedPostPayloadInput`), so the
|
|
6
|
+
* transport-agnostic SDK works unchanged. Only the resolvers differ from S3 — they resolve the server
|
|
7
|
+
* upload use cases (local disk + the `/webiny-file-upload` HTTP routes) instead of an S3 client.
|
|
8
|
+
*/
|
|
9
|
+
declare class ServerGraphQLSchemaImpl implements CoreGraphQLSchemaFactory.Interface {
|
|
10
|
+
execute(builder: GraphQLSchemaBuilder.Interface): CoreGraphQLSchemaFactory.Return;
|
|
11
|
+
}
|
|
12
|
+
export declare const ServerGraphQLSchema: typeof ServerGraphQLSchemaImpl & {
|
|
13
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-graphql/graphql/abstractions.core").ICoreGraphQLSchemaFactory>;
|
|
14
|
+
};
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import p_map from "p-map";
|
|
2
|
+
import { CoreGraphQLSchemaFactory } from "@webiny/api-graphql/graphql/abstractions.js";
|
|
3
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
|
+
import { ErrorResponse, Response } from "@webiny/api-graphql/responses.js";
|
|
5
|
+
import { GetSettingsUseCase } from "@webiny/api-file-manager/features/settings/GetSettings/abstractions.js";
|
|
6
|
+
import { GetUploadPayloadUseCase } from "@webiny/api-file-manager/features/upload/GetUploadPayload/index.js";
|
|
7
|
+
import { CreateMultiPartUploadUseCase } from "@webiny/api-file-manager/features/upload/CreateMultiPartUpload/index.js";
|
|
8
|
+
import { CompleteMultiPartUploadUseCase } from "@webiny/api-file-manager/features/upload/CompleteMultiPartUpload/index.js";
|
|
9
|
+
import { FileNormalizer, checkPermissions } from "@webiny/api-file-manager/features/upload/index.js";
|
|
10
|
+
const createNormalizer = ()=>new FileNormalizer();
|
|
11
|
+
const TYPE_DEFS = `
|
|
12
|
+
type UploadFileResponseDataFile {
|
|
13
|
+
id: ID!
|
|
14
|
+
name: String!
|
|
15
|
+
type: String!
|
|
16
|
+
size: Long!
|
|
17
|
+
key: String!
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
input PreSignedPostPayloadInput {
|
|
21
|
+
id: ID
|
|
22
|
+
name: String!
|
|
23
|
+
type: String!
|
|
24
|
+
size: Long!
|
|
25
|
+
key: String
|
|
26
|
+
keyPrefix: String
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type GetPreSignedPostPayloadResponseDataFile {
|
|
30
|
+
id: ID!
|
|
31
|
+
name: String!
|
|
32
|
+
type: String!
|
|
33
|
+
size: Long!
|
|
34
|
+
key: String!
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type GetPreSignedPostPayloadResponseData {
|
|
38
|
+
# Contains data that is necessary for initiating a file upload.
|
|
39
|
+
data: JSON!
|
|
40
|
+
file: UploadFileResponseDataFile!
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type GetPreSignedPostPayloadResponse {
|
|
44
|
+
error: FmError
|
|
45
|
+
data: GetPreSignedPostPayloadResponseData
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type MultiPartUploadFilePart {
|
|
49
|
+
partNumber: Int!
|
|
50
|
+
url: String!
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type CreateMultiPartUploadResponseData {
|
|
54
|
+
file: GetPreSignedPostPayloadResponseDataFile!
|
|
55
|
+
uploadId: String!
|
|
56
|
+
parts: [MultiPartUploadFilePart!]!
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type CompleteMultiPartUploadResponse {
|
|
60
|
+
data: Boolean
|
|
61
|
+
error: FmError
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type GetPreSignedPostPayloadsResponse {
|
|
65
|
+
error: FmError
|
|
66
|
+
data: [GetPreSignedPostPayloadResponseData!]!
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
extend type FmQuery {
|
|
70
|
+
getPreSignedPostPayload(data: PreSignedPostPayloadInput!): GetPreSignedPostPayloadResponse
|
|
71
|
+
getPreSignedPostPayloads(
|
|
72
|
+
data: [PreSignedPostPayloadInput]!
|
|
73
|
+
): GetPreSignedPostPayloadsResponse
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
type CreateMultiPartUploadResponse {
|
|
77
|
+
data: CreateMultiPartUploadResponseData
|
|
78
|
+
error: FmError
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
input MultiPartUploadFilePartInput {
|
|
82
|
+
partNumber: Int!
|
|
83
|
+
etag: String!
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
extend type FmMutation {
|
|
87
|
+
createMultiPartUpload(
|
|
88
|
+
data: PreSignedPostPayloadInput!
|
|
89
|
+
numberOfParts: Number!
|
|
90
|
+
): CreateMultiPartUploadResponse
|
|
91
|
+
|
|
92
|
+
completeMultiPartUpload(
|
|
93
|
+
fileKey: String!
|
|
94
|
+
uploadId: String!
|
|
95
|
+
): CompleteMultiPartUploadResponse
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
class ServerGraphQLSchemaImpl {
|
|
99
|
+
async execute(builder) {
|
|
100
|
+
builder.addTypeDefs(TYPE_DEFS);
|
|
101
|
+
builder.addResolver({
|
|
102
|
+
path: "FmQuery.getPreSignedPostPayload",
|
|
103
|
+
dependencies: [
|
|
104
|
+
IdentityContext,
|
|
105
|
+
GetSettingsUseCase,
|
|
106
|
+
GetUploadPayloadUseCase
|
|
107
|
+
],
|
|
108
|
+
resolver (identityContext, getSettings, getUploadPayload) {
|
|
109
|
+
return async ({ args })=>{
|
|
110
|
+
try {
|
|
111
|
+
await checkPermissions(identityContext, {
|
|
112
|
+
rwd: "w"
|
|
113
|
+
});
|
|
114
|
+
const settingsResult = await getSettings.execute();
|
|
115
|
+
const settings = settingsResult.value;
|
|
116
|
+
const normalizer = createNormalizer();
|
|
117
|
+
const payload = await getUploadPayload.execute(await normalizer.normalizeFile(args.data), settings);
|
|
118
|
+
return new Response(payload);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
return new ErrorResponse({
|
|
121
|
+
message: e.message,
|
|
122
|
+
code: e.code,
|
|
123
|
+
data: e.data
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
builder.addResolver({
|
|
130
|
+
path: "FmQuery.getPreSignedPostPayloads",
|
|
131
|
+
dependencies: [
|
|
132
|
+
IdentityContext,
|
|
133
|
+
GetSettingsUseCase,
|
|
134
|
+
GetUploadPayloadUseCase
|
|
135
|
+
],
|
|
136
|
+
resolver (identityContext, getSettings, getUploadPayload) {
|
|
137
|
+
return async ({ args })=>{
|
|
138
|
+
try {
|
|
139
|
+
await checkPermissions(identityContext, {
|
|
140
|
+
rwd: "w"
|
|
141
|
+
});
|
|
142
|
+
const settingsResult = await getSettings.execute();
|
|
143
|
+
const settings = settingsResult.value;
|
|
144
|
+
const normalizer = createNormalizer();
|
|
145
|
+
const payloads = await p_map(args.data, async (data)=>getUploadPayload.execute(await normalizer.normalizeFile(data), settings));
|
|
146
|
+
return new Response(payloads);
|
|
147
|
+
} catch (e) {
|
|
148
|
+
return new ErrorResponse({
|
|
149
|
+
message: e.message,
|
|
150
|
+
code: e.code,
|
|
151
|
+
data: e.data
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
builder.addResolver({
|
|
158
|
+
path: "FmMutation.createMultiPartUpload",
|
|
159
|
+
dependencies: [
|
|
160
|
+
IdentityContext,
|
|
161
|
+
CreateMultiPartUploadUseCase
|
|
162
|
+
],
|
|
163
|
+
resolver (identityContext, createMultiPartUpload) {
|
|
164
|
+
return async ({ args })=>{
|
|
165
|
+
try {
|
|
166
|
+
await checkPermissions(identityContext, {
|
|
167
|
+
rwd: "w"
|
|
168
|
+
});
|
|
169
|
+
const normalizer = createNormalizer();
|
|
170
|
+
const result = await createMultiPartUpload.execute({
|
|
171
|
+
file: await normalizer.normalizeFile(args.data),
|
|
172
|
+
numberOfParts: args.numberOfParts
|
|
173
|
+
});
|
|
174
|
+
return new Response(result);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
return new ErrorResponse({
|
|
177
|
+
message: e.message,
|
|
178
|
+
code: e.code,
|
|
179
|
+
data: e.data
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
builder.addResolver({
|
|
186
|
+
path: "FmMutation.completeMultiPartUpload",
|
|
187
|
+
dependencies: [
|
|
188
|
+
IdentityContext,
|
|
189
|
+
CompleteMultiPartUploadUseCase
|
|
190
|
+
],
|
|
191
|
+
resolver (identityContext, completeMultiPartUpload) {
|
|
192
|
+
return async ({ args })=>{
|
|
193
|
+
try {
|
|
194
|
+
await checkPermissions(identityContext, {
|
|
195
|
+
rwd: "w"
|
|
196
|
+
});
|
|
197
|
+
await completeMultiPartUpload.execute({
|
|
198
|
+
fileKey: args.fileKey,
|
|
199
|
+
uploadId: args.uploadId
|
|
200
|
+
});
|
|
201
|
+
return new Response(true);
|
|
202
|
+
} catch (e) {
|
|
203
|
+
return new ErrorResponse({
|
|
204
|
+
message: e.message,
|
|
205
|
+
code: e.code,
|
|
206
|
+
data: e.data
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
return builder;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const ServerGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({
|
|
216
|
+
implementation: ServerGraphQLSchemaImpl,
|
|
217
|
+
dependencies: []
|
|
218
|
+
});
|
|
219
|
+
export { ServerGraphQLSchema };
|
|
220
|
+
|
|
221
|
+
//# sourceMappingURL=ServerGraphQLSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql/ServerGraphQLSchema.js","sources":["../../src/graphql/ServerGraphQLSchema.ts"],"sourcesContent":["import pMap from \"p-map\";\nimport { CoreGraphQLSchemaFactory } from \"@webiny/api-graphql/graphql/abstractions.js\";\nimport { GraphQLSchemaBuilder } from \"@webiny/api-graphql/features/GraphQLSchemaBuilder/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { ErrorResponse, Response } from \"@webiny/api-graphql/responses.js\";\nimport { GetSettingsUseCase } from \"@webiny/api-file-manager/features/settings/GetSettings/abstractions.js\";\nimport { GetUploadPayloadUseCase } from \"@webiny/api-file-manager/features/upload/GetUploadPayload/index.js\";\nimport { CreateMultiPartUploadUseCase } from \"@webiny/api-file-manager/features/upload/CreateMultiPartUpload/index.js\";\nimport { CompleteMultiPartUploadUseCase } from \"@webiny/api-file-manager/features/upload/CompleteMultiPartUpload/index.js\";\nimport {\n checkPermissions,\n FileNormalizer\n} from \"@webiny/api-file-manager/features/upload/index.js\";\nimport type { FileData } from \"@webiny/api-file-manager/features/upload/types.js\";\n\n// Build the normalizer WITHOUT the gql context: the domain's `createFileNormalizerFromContext` reads\n// `context.plugins.byType(...)` (the legacy plugins registry), which the DI-native server gql context\n// does not populate — calling it throws \"Cannot read properties of undefined (reading 'byType')\". The\n// modifier is optional; FileNormalizer still generates the id/type/key. The server has no legacy\n// FileUploadModifierPlugins, so an empty (no-modifier) normalizer is the correct behaviour here.\nconst createNormalizer = () => new FileNormalizer();\n\nconst TYPE_DEFS = /* GraphQL */ `\n type UploadFileResponseDataFile {\n id: ID!\n name: String!\n type: String!\n size: Long!\n key: String!\n }\n\n input PreSignedPostPayloadInput {\n id: ID\n name: String!\n type: String!\n size: Long!\n key: String\n keyPrefix: String\n }\n\n type GetPreSignedPostPayloadResponseDataFile {\n id: ID!\n name: String!\n type: String!\n size: Long!\n key: String!\n }\n\n type GetPreSignedPostPayloadResponseData {\n # Contains data that is necessary for initiating a file upload.\n data: JSON!\n file: UploadFileResponseDataFile!\n }\n\n type GetPreSignedPostPayloadResponse {\n error: FmError\n data: GetPreSignedPostPayloadResponseData\n }\n\n type MultiPartUploadFilePart {\n partNumber: Int!\n url: String!\n }\n\n type CreateMultiPartUploadResponseData {\n file: GetPreSignedPostPayloadResponseDataFile!\n uploadId: String!\n parts: [MultiPartUploadFilePart!]!\n }\n\n type CompleteMultiPartUploadResponse {\n data: Boolean\n error: FmError\n }\n\n type GetPreSignedPostPayloadsResponse {\n error: FmError\n data: [GetPreSignedPostPayloadResponseData!]!\n }\n\n extend type FmQuery {\n getPreSignedPostPayload(data: PreSignedPostPayloadInput!): GetPreSignedPostPayloadResponse\n getPreSignedPostPayloads(\n data: [PreSignedPostPayloadInput]!\n ): GetPreSignedPostPayloadsResponse\n }\n\n type CreateMultiPartUploadResponse {\n data: CreateMultiPartUploadResponseData\n error: FmError\n }\n\n input MultiPartUploadFilePartInput {\n partNumber: Int!\n etag: String!\n }\n\n extend type FmMutation {\n createMultiPartUpload(\n data: PreSignedPostPayloadInput!\n numberOfParts: Number!\n ): CreateMultiPartUploadResponse\n\n completeMultiPartUpload(\n fileKey: String!\n uploadId: String!\n ): CompleteMultiPartUploadResponse\n }\n`;\n\n/**\n * Upload GraphQL for the self-hosted (server) hosting type. Mirrors the SDL that `api-file-manager-s3`'s\n * `S3GraphQLSchema` contributes (same query/mutation names + `PreSignedPostPayloadInput`), so the\n * transport-agnostic SDK works unchanged. Only the resolvers differ from S3 — they resolve the server\n * upload use cases (local disk + the `/webiny-file-upload` HTTP routes) instead of an S3 client.\n */\nclass ServerGraphQLSchemaImpl implements CoreGraphQLSchemaFactory.Interface {\n public async execute(builder: GraphQLSchemaBuilder.Interface): CoreGraphQLSchemaFactory.Return {\n builder.addTypeDefs(TYPE_DEFS);\n\n builder.addResolver<{ data: any }>({\n path: \"FmQuery.getPreSignedPostPayload\",\n dependencies: [IdentityContext, GetSettingsUseCase, GetUploadPayloadUseCase],\n resolver(\n identityContext: IdentityContext.Interface,\n getSettings: GetSettingsUseCase.Interface,\n getUploadPayload: GetUploadPayloadUseCase.Interface\n ) {\n return async ({ args }) => {\n try {\n await checkPermissions(identityContext, { rwd: \"w\" });\n\n const settingsResult = await getSettings.execute();\n const settings = settingsResult.value;\n\n const normalizer = createNormalizer();\n const payload = await getUploadPayload.execute(\n (await normalizer.normalizeFile(args.data)) as FileData,\n settings\n );\n\n return new Response(payload);\n } catch (e) {\n return new ErrorResponse({\n message: e.message,\n code: e.code,\n data: e.data\n });\n }\n };\n }\n });\n\n builder.addResolver<{ data: any[] }>({\n path: \"FmQuery.getPreSignedPostPayloads\",\n dependencies: [IdentityContext, GetSettingsUseCase, GetUploadPayloadUseCase],\n resolver(\n identityContext: IdentityContext.Interface,\n getSettings: GetSettingsUseCase.Interface,\n getUploadPayload: GetUploadPayloadUseCase.Interface\n ) {\n return async ({ args }) => {\n try {\n await checkPermissions(identityContext, { rwd: \"w\" });\n\n const settingsResult = await getSettings.execute();\n const settings = settingsResult.value;\n\n const normalizer = createNormalizer();\n const payloads = await pMap(args.data, async (data: any) => {\n return getUploadPayload.execute(\n (await normalizer.normalizeFile(data)) as FileData,\n settings\n );\n });\n\n return new Response(payloads);\n } catch (e) {\n return new ErrorResponse({\n message: e.message,\n code: e.code,\n data: e.data\n });\n }\n };\n }\n });\n\n builder.addResolver<{ data: any; numberOfParts: number }>({\n path: \"FmMutation.createMultiPartUpload\",\n dependencies: [IdentityContext, CreateMultiPartUploadUseCase],\n resolver(\n identityContext: IdentityContext.Interface,\n createMultiPartUpload: CreateMultiPartUploadUseCase.Interface\n ) {\n return async ({ args }) => {\n try {\n await checkPermissions(identityContext, { rwd: \"w\" });\n\n const normalizer = createNormalizer();\n const result = await createMultiPartUpload.execute({\n file: (await normalizer.normalizeFile(args.data)) as FileData,\n numberOfParts: args.numberOfParts\n });\n\n return new Response(result);\n } catch (e) {\n return new ErrorResponse({\n message: e.message,\n code: e.code,\n data: e.data\n });\n }\n };\n }\n });\n\n builder.addResolver<{ fileKey: string; uploadId: string }>({\n path: \"FmMutation.completeMultiPartUpload\",\n dependencies: [IdentityContext, CompleteMultiPartUploadUseCase],\n resolver(\n identityContext: IdentityContext.Interface,\n completeMultiPartUpload: CompleteMultiPartUploadUseCase.Interface\n ) {\n return async ({ args }) => {\n try {\n await checkPermissions(identityContext, { rwd: \"w\" });\n\n await completeMultiPartUpload.execute({\n fileKey: args.fileKey,\n uploadId: args.uploadId\n });\n\n return new Response(true);\n } catch (e) {\n return new ErrorResponse({\n message: e.message,\n code: e.code,\n data: e.data\n });\n }\n };\n }\n });\n\n return builder;\n }\n}\n\nexport const ServerGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({\n implementation: ServerGraphQLSchemaImpl,\n dependencies: []\n});\n"],"names":["createNormalizer","FileNormalizer","TYPE_DEFS","ServerGraphQLSchemaImpl","builder","IdentityContext","GetSettingsUseCase","GetUploadPayloadUseCase","identityContext","getSettings","getUploadPayload","args","checkPermissions","settingsResult","settings","normalizer","payload","Response","e","ErrorResponse","payloads","pMap","data","CreateMultiPartUploadUseCase","createMultiPartUpload","result","CompleteMultiPartUploadUseCase","completeMultiPartUpload","ServerGraphQLSchema","CoreGraphQLSchemaFactory"],"mappings":"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"}
|