@webiny/api-file-manager-standalone 6.6.0-alpha.4
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/FileManagerStandaloneFeature.d.ts +5 -0
- package/FileManagerStandaloneFeature.js +41 -0
- package/FileManagerStandaloneFeature.js.map +1 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/assetDelivery/LazyLocalSharpTransform.d.ts +33 -0
- package/assetDelivery/LazyLocalSharpTransform.js +32 -0
- package/assetDelivery/LazyLocalSharpTransform.js.map +1 -0
- package/assetDelivery/LocalAssetResolver.d.ts +15 -0
- package/assetDelivery/LocalAssetResolver.js +40 -0
- package/assetDelivery/LocalAssetResolver.js.map +1 -0
- package/assetDelivery/LocalContentsReader.d.ts +7 -0
- package/assetDelivery/LocalContentsReader.js +18 -0
- package/assetDelivery/LocalContentsReader.js.map +1 -0
- package/assetDelivery/LocalOutputStrategy.d.ts +12 -0
- package/assetDelivery/LocalOutputStrategy.js +21 -0
- package/assetDelivery/LocalOutputStrategy.js.map +1 -0
- package/assetDelivery/LocalSharpTransform.d.ts +24 -0
- package/assetDelivery/LocalSharpTransform.js +161 -0
- package/assetDelivery/LocalSharpTransform.js.map +1 -0
- package/assetDelivery/abstractions.d.ts +8 -0
- package/assetDelivery/abstractions.js +6 -0
- package/assetDelivery/abstractions.js.map +1 -0
- package/assetDelivery/assetDeliveryConfig.d.ts +2 -0
- package/assetDelivery/assetDeliveryConfig.js +15 -0
- package/assetDelivery/assetDeliveryConfig.js.map +1 -0
- package/assetDelivery/createAssetDelivery.d.ts +3 -0
- package/assetDelivery/createAssetDelivery.js +7 -0
- package/assetDelivery/createAssetDelivery.js.map +1 -0
- package/assetDelivery/feature.d.ts +5 -0
- package/assetDelivery/feature.js +33 -0
- package/assetDelivery/feature.js.map +1 -0
- package/assetDelivery/types.d.ts +8 -0
- package/assetDelivery/types.js +0 -0
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.d.ts +26 -0
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js +71 -0
- package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js.map +1 -0
- package/features/CleanupStaleMultipartUploads/feature.d.ts +4 -0
- package/features/CleanupStaleMultipartUploads/feature.js +11 -0
- package/features/CleanupStaleMultipartUploads/feature.js.map +1 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +13 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +62 -0
- package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -0
- package/features/CompleteMultiPartUpload/feature.d.ts +4 -0
- package/features/CompleteMultiPartUpload/feature.js +11 -0
- package/features/CompleteMultiPartUpload/feature.js.map +1 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +14 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +58 -0
- package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -0
- package/features/CreateMultiPartUpload/feature.d.ts +4 -0
- package/features/CreateMultiPartUpload/feature.js +11 -0
- package/features/CreateMultiPartUpload/feature.js.map +1 -0
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.d.ts +15 -0
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js +34 -0
- package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js.map +1 -0
- package/features/DeleteFileFromDisk/feature.d.ts +4 -0
- package/features/DeleteFileFromDisk/feature.js +11 -0
- package/features/DeleteFileFromDisk/feature.js.map +1 -0
- package/features/ExtractMetadata/ExtractMetadataHandler.d.ts +1 -0
- package/features/ExtractMetadata/ExtractMetadataHandler.js +1 -0
- package/features/ExtractMetadata/ExtractMetadataTask.d.ts +29 -0
- package/features/ExtractMetadata/ExtractMetadataTask.js +93 -0
- package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -0
- package/features/ExtractMetadata/feature.d.ts +4 -0
- package/features/ExtractMetadata/feature.js +13 -0
- package/features/ExtractMetadata/feature.js.map +1 -0
- package/features/FileManagerStandaloneConfig/FileManagerStandaloneConfig.d.ts +12 -0
- package/features/FileManagerStandaloneConfig/FileManagerStandaloneConfig.js +28 -0
- package/features/FileManagerStandaloneConfig/FileManagerStandaloneConfig.js.map +1 -0
- package/features/FileManagerStandaloneConfig/abstractions.d.ts +10 -0
- package/features/FileManagerStandaloneConfig/abstractions.js +5 -0
- package/features/FileManagerStandaloneConfig/abstractions.js.map +1 -0
- package/features/FileManagerStandaloneConfig/feature.d.ts +4 -0
- package/features/FileManagerStandaloneConfig/feature.js +11 -0
- package/features/FileManagerStandaloneConfig/feature.js.map +1 -0
- package/features/FlushCache/FlushCacheOnFileBeforeUpdateHandler.d.ts +8 -0
- package/features/FlushCache/FlushCacheOnFileBeforeUpdateHandler.js +11 -0
- package/features/FlushCache/FlushCacheOnFileBeforeUpdateHandler.js.map +1 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.d.ts +8 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.js +11 -0
- package/features/FlushCache/FlushCacheOnFileDeleteHandler.js.map +1 -0
- package/features/FlushCache/feature.d.ts +4 -0
- package/features/FlushCache/feature.js +13 -0
- package/features/FlushCache/feature.js.map +1 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +15 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +38 -0
- package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -0
- package/features/GetFileContentsById/feature.d.ts +4 -0
- package/features/GetFileContentsById/feature.js +11 -0
- package/features/GetFileContentsById/feature.js.map +1 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +15 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +72 -0
- package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -0
- package/features/GetFileContentsByKey/feature.d.ts +4 -0
- package/features/GetFileContentsByKey/feature.js +11 -0
- package/features/GetFileContentsByKey/feature.js.map +1 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +16 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js +57 -0
- package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -0
- package/features/GetUploadPayload/feature.d.ts +4 -0
- package/features/GetUploadPayload/feature.js +11 -0
- package/features/GetUploadPayload/feature.js.map +1 -0
- package/graphql/StandaloneGraphQLSchema.d.ts +15 -0
- package/graphql/StandaloneGraphQLSchema.js +221 -0
- package/graphql/StandaloneGraphQLSchema.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +44 -0
- package/routes/UploadPartRoute/UploadPartRoute.d.ts +23 -0
- package/routes/UploadPartRoute/UploadPartRoute.js +71 -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 +23 -0
- package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js +78 -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 +18 -0
- package/routes/utils.js +55 -0
- package/routes/utils.js.map +1 -0
- package/types.d.ts +10 -0
- package/types.js +1 -0
- package/utils/uploadToken.d.ts +3 -0
- package/utils/uploadToken.js +22 -0
- package/utils/uploadToken.js.map +1 -0
|
@@ -0,0 +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 { 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 { FileManagerStandaloneConfig } from \"~/features/FileManagerStandaloneConfig/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: FileManagerStandaloneConfig.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, FileManagerStandaloneConfig]\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","FileManagerStandaloneConfig"],"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,MAA6C,CAChE;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;KAA4B;AAC9D"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { GetUploadPayloadUseCase } from "./GetUploadPayloadUseCase.js";
|
|
3
|
+
const GetUploadPayloadFeature = createFeature({
|
|
4
|
+
name: "FileManagerServer/GetUploadPayload",
|
|
5
|
+
register (container) {
|
|
6
|
+
container.register(GetUploadPayloadUseCase);
|
|
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 { 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 standalone 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 StandaloneGraphQLSchemaImpl implements CoreGraphQLSchemaFactory.Interface {
|
|
10
|
+
execute(builder: GraphQLSchemaBuilder.Interface): CoreGraphQLSchemaFactory.Return;
|
|
11
|
+
}
|
|
12
|
+
export declare const StandaloneGraphQLSchema: typeof StandaloneGraphQLSchemaImpl & {
|
|
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 StandaloneGraphQLSchemaImpl {
|
|
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 StandaloneGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({
|
|
216
|
+
implementation: StandaloneGraphQLSchemaImpl,
|
|
217
|
+
dependencies: []
|
|
218
|
+
});
|
|
219
|
+
export { StandaloneGraphQLSchema };
|
|
220
|
+
|
|
221
|
+
//# sourceMappingURL=StandaloneGraphQLSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql/StandaloneGraphQLSchema.js","sources":["../../src/graphql/StandaloneGraphQLSchema.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 standalone 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 StandaloneGraphQLSchemaImpl 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 StandaloneGraphQLSchema = CoreGraphQLSchemaFactory.createImplementation({\n implementation: StandaloneGraphQLSchemaImpl,\n dependencies: []\n});\n"],"names":["createNormalizer","FileNormalizer","TYPE_DEFS","StandaloneGraphQLSchemaImpl","builder","IdentityContext","GetSettingsUseCase","GetUploadPayloadUseCase","identityContext","getSettings","getUploadPayload","args","checkPermissions","settingsResult","settings","normalizer","payload","Response","e","ErrorResponse","payloads","pMap","data","CreateMultiPartUploadUseCase","createMultiPartUpload","result","CompleteMultiPartUploadUseCase","completeMultiPartUpload","StandaloneGraphQLSchema","CoreGraphQLSchemaFactory"],"mappings":"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"}
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webiny/api-file-manager-standalone",
|
|
3
|
+
"version": "6.6.0-alpha.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.js",
|
|
7
|
+
"./*": "./*"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/webiny/webiny-js.git"
|
|
12
|
+
},
|
|
13
|
+
"description": "File storage plugin for the @webiny/api-file-manager, for standalone Webiny projects.",
|
|
14
|
+
"author": "Webiny Ltd",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@webiny/api-core": "6.6.0-alpha.4",
|
|
18
|
+
"@webiny/api-file-manager": "6.6.0-alpha.4",
|
|
19
|
+
"@webiny/api-graphql": "6.6.0-alpha.4",
|
|
20
|
+
"@webiny/background-tasks": "6.6.0-alpha.4",
|
|
21
|
+
"@webiny/event-handler-core": "6.6.0-alpha.4",
|
|
22
|
+
"@webiny/feature": "6.6.0-alpha.4",
|
|
23
|
+
"@webiny/handler": "6.6.0-alpha.4",
|
|
24
|
+
"@webiny/plugins": "6.6.0-alpha.4",
|
|
25
|
+
"@webiny/utils": "6.6.0-alpha.4",
|
|
26
|
+
"@webiny/validation": "6.6.0-alpha.4",
|
|
27
|
+
"exifreader": "4.43.0",
|
|
28
|
+
"p-map": "7.0.6",
|
|
29
|
+
"sharp": "0.35.3"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@webiny/build-tools": "6.6.0-alpha.4",
|
|
33
|
+
"rimraf": "6.1.3",
|
|
34
|
+
"typescript": "7.0.2",
|
|
35
|
+
"vitest": "4.1.11"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"gitHead": "8476da73b653c89cc1474d968baf55c1b0ae0e5f",
|
|
41
|
+
"webiny": {
|
|
42
|
+
"publishFrom": "dist"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
|
|
2
|
+
import { FileManagerStandaloneConfig } from "../../features/FileManagerStandaloneConfig/abstractions.js";
|
|
3
|
+
declare class UploadPartRouteImpl implements HttpRouteHandler.Interface {
|
|
4
|
+
private readonly config;
|
|
5
|
+
constructor(config: FileManagerStandaloneConfig.Interface);
|
|
6
|
+
handle(request: HttpRouteHandler.Request, response: HttpRouteHandler.Response): Promise<import("@webiny/event-handler-core").IHttpResponseBuilder>;
|
|
7
|
+
}
|
|
8
|
+
export declare const UploadPartRoute: typeof UploadPartRouteImpl & {
|
|
9
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
|
|
10
|
+
};
|
|
11
|
+
declare class UploadPartRouteDefinitionImpl implements HttpRouteDefinition.Interface {
|
|
12
|
+
readonly name = "upload-part";
|
|
13
|
+
readonly method = "PUT";
|
|
14
|
+
readonly path = "/webiny-file-upload/parts";
|
|
15
|
+
readonly handler: typeof UploadPartRouteImpl & {
|
|
16
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** What the router matches on. Zero dependencies, so building it costs nothing. */
|
|
20
|
+
export declare const UploadPartRouteDefinition: typeof UploadPartRouteDefinitionImpl & {
|
|
21
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRouteDefinition>;
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
|
|
5
|
+
import { verifyUploadToken } from "../../utils/uploadToken.js";
|
|
6
|
+
import { FileManagerStandaloneConfig } from "../../features/FileManagerStandaloneConfig/abstractions.js";
|
|
7
|
+
import { isPathContained, toBuffer } from "../utils.js";
|
|
8
|
+
class UploadPartRouteImpl {
|
|
9
|
+
constructor(config){
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async handle(request, response) {
|
|
13
|
+
const storagePath = this.config.storagePath;
|
|
14
|
+
const secret = this.config.uploadSecret;
|
|
15
|
+
const query = request.query ?? {};
|
|
16
|
+
const uploadId = query["uploadId"];
|
|
17
|
+
const partNumberStr = query["partNumber"];
|
|
18
|
+
const token = query["token"];
|
|
19
|
+
if (!uploadId || !partNumberStr || !token) return response.status(400).json({
|
|
20
|
+
error: "Missing uploadId, partNumber, or token."
|
|
21
|
+
});
|
|
22
|
+
const partNumber = parseInt(partNumberStr, 10);
|
|
23
|
+
if (isNaN(partNumber) || partNumber < 1) return response.status(400).json({
|
|
24
|
+
error: "Invalid partNumber."
|
|
25
|
+
});
|
|
26
|
+
let payload;
|
|
27
|
+
try {
|
|
28
|
+
payload = verifyUploadToken(token, secret);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
return response.status(400).json({
|
|
31
|
+
error: err instanceof Error ? err.message : "Invalid token."
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const expectedKey = `tenants/${payload.tenantId}/multipart/${uploadId}/part-${partNumber}`;
|
|
35
|
+
if (payload.key !== expectedKey) return response.status(400).json({
|
|
36
|
+
error: "Token key mismatch."
|
|
37
|
+
});
|
|
38
|
+
const destPath = node_path.join(storagePath, expectedKey);
|
|
39
|
+
if (!isPathContained(destPath, storagePath)) return response.status(400).json({
|
|
40
|
+
error: "Invalid path."
|
|
41
|
+
});
|
|
42
|
+
await mkdir(node_path.dirname(destPath), {
|
|
43
|
+
recursive: true
|
|
44
|
+
});
|
|
45
|
+
const body = toBuffer(request.body);
|
|
46
|
+
await writeFile(destPath, body);
|
|
47
|
+
const etag = createHash("md5").update(body).digest("hex");
|
|
48
|
+
return response.header("etag", etag);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const UploadPartRoute = HttpRouteHandler.createImplementation({
|
|
52
|
+
implementation: UploadPartRouteImpl,
|
|
53
|
+
dependencies: [
|
|
54
|
+
FileManagerStandaloneConfig
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
class UploadPartRouteDefinitionImpl {
|
|
58
|
+
constructor(){
|
|
59
|
+
this.name = "upload-part";
|
|
60
|
+
this.method = "PUT";
|
|
61
|
+
this.path = "/webiny-file-upload/parts";
|
|
62
|
+
this.handler = UploadPartRoute;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const UploadPartRouteDefinition = HttpRouteDefinition.createImplementation({
|
|
66
|
+
implementation: UploadPartRouteDefinitionImpl,
|
|
67
|
+
dependencies: []
|
|
68
|
+
});
|
|
69
|
+
export { UploadPartRoute, UploadPartRouteDefinition };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=UploadPartRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes/UploadPartRoute/UploadPartRoute.js","sources":["../../../src/routes/UploadPartRoute/UploadPartRoute.ts"],"sourcesContent":["import path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { HttpRouteDefinition, HttpRouteHandler } from \"@webiny/event-handler-core\";\nimport { verifyUploadToken } from \"~/utils/uploadToken.js\";\nimport { FileManagerStandaloneConfig } from \"~/features/FileManagerStandaloneConfig/abstractions.js\";\nimport { isPathContained, toBuffer } from \"../utils.js\";\n\nclass UploadPartRouteImpl implements HttpRouteHandler.Interface {\n public constructor(private readonly config: FileManagerStandaloneConfig.Interface) {}\n\n public async handle(request: HttpRouteHandler.Request, response: HttpRouteHandler.Response) {\n const storagePath = this.config.storagePath;\n const secret = this.config.uploadSecret;\n\n const query = request.query ?? {};\n const uploadId = query[\"uploadId\"];\n const partNumberStr = query[\"partNumber\"];\n const token = query[\"token\"];\n\n if (!uploadId || !partNumberStr || !token) {\n return response.status(400).json({ error: \"Missing uploadId, partNumber, or token.\" });\n }\n\n const partNumber = parseInt(partNumberStr, 10);\n if (isNaN(partNumber) || partNumber < 1) {\n return response.status(400).json({ error: \"Invalid partNumber.\" });\n }\n\n let payload;\n try {\n payload = verifyUploadToken(token, secret);\n } catch (err) {\n return response\n .status(400)\n .json({ error: err instanceof Error ? err.message : \"Invalid token.\" });\n }\n\n const expectedKey = `tenants/${payload.tenantId}/multipart/${uploadId}/part-${partNumber}`;\n if (payload.key !== expectedKey) {\n return response.status(400).json({ error: \"Token key mismatch.\" });\n }\n\n const destPath = path.join(storagePath, expectedKey);\n if (!isPathContained(destPath, storagePath)) {\n return response.status(400).json({ error: \"Invalid path.\" });\n }\n\n await mkdir(path.dirname(destPath), { recursive: true });\n\n const body = toBuffer(request.body);\n await writeFile(destPath, body);\n\n const etag = createHash(\"md5\").update(body).digest(\"hex\");\n\n return response.header(\"etag\", etag);\n }\n}\n\nexport const UploadPartRoute = HttpRouteHandler.createImplementation({\n implementation: UploadPartRouteImpl,\n dependencies: [FileManagerStandaloneConfig]\n});\n\nclass UploadPartRouteDefinitionImpl implements HttpRouteDefinition.Interface {\n readonly name = \"upload-part\";\n readonly method = \"PUT\";\n readonly path = \"/webiny-file-upload/parts\";\n readonly handler = UploadPartRoute;\n}\n\n/** What the router matches on. Zero dependencies, so building it costs nothing. */\nexport const UploadPartRouteDefinition = HttpRouteDefinition.createImplementation({\n implementation: UploadPartRouteDefinitionImpl,\n dependencies: []\n});\n"],"names":["UploadPartRouteImpl","config","request","response","storagePath","secret","query","uploadId","partNumberStr","token","partNumber","parseInt","isNaN","payload","verifyUploadToken","err","Error","expectedKey","destPath","path","isPathContained","mkdir","body","toBuffer","writeFile","etag","createHash","UploadPartRoute","HttpRouteHandler","FileManagerStandaloneConfig","UploadPartRouteDefinitionImpl","UploadPartRouteDefinition","HttpRouteDefinition"],"mappings":";;;;;;;AAQA,MAAMA;IACF,YAAoCC,MAA6C,CAAE;aAA/CA,MAAM,GAANA;IAAgD;IAEpF,MAAa,OAAOC,OAAiC,EAAEC,QAAmC,EAAE;QACxF,MAAMC,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW;QAC3C,MAAMC,SAAS,IAAI,CAAC,MAAM,CAAC,YAAY;QAEvC,MAAMC,QAAQJ,QAAQ,KAAK,IAAI,CAAC;QAChC,MAAMK,WAAWD,KAAK,CAAC,WAAW;QAClC,MAAME,gBAAgBF,KAAK,CAAC,aAAa;QACzC,MAAMG,QAAQH,KAAK,CAAC,QAAQ;QAE5B,IAAI,CAACC,YAAY,CAACC,iBAAiB,CAACC,OAChC,OAAON,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAA0C;QAGxF,MAAMO,aAAaC,SAASH,eAAe;QAC3C,IAAII,MAAMF,eAAeA,aAAa,GAClC,OAAOP,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAsB;QAGpE,IAAIU;QACJ,IAAI;YACAA,UAAUC,kBAAkBL,OAAOJ;QACvC,EAAE,OAAOU,KAAK;YACV,OAAOZ,SACF,MAAM,CAAC,KACP,IAAI,CAAC;gBAAE,OAAOY,eAAeC,QAAQD,IAAI,OAAO,GAAG;YAAiB;QAC7E;QAEA,MAAME,cAAc,CAAC,QAAQ,EAAEJ,QAAQ,QAAQ,CAAC,WAAW,EAAEN,SAAS,MAAM,EAAEG,YAAY;QAC1F,IAAIG,QAAQ,GAAG,KAAKI,aAChB,OAAOd,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAsB;QAGpE,MAAMe,WAAWC,UAAAA,IAAS,CAACf,aAAaa;QACxC,IAAI,CAACG,gBAAgBF,UAAUd,cAC3B,OAAOD,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAgB;QAG9D,MAAMkB,MAAMF,UAAAA,OAAY,CAACD,WAAW;YAAE,WAAW;QAAK;QAEtD,MAAMI,OAAOC,SAASrB,QAAQ,IAAI;QAClC,MAAMsB,UAAUN,UAAUI;QAE1B,MAAMG,OAAOC,WAAW,OAAO,MAAM,CAACJ,MAAM,MAAM,CAAC;QAEnD,OAAOnB,SAAS,MAAM,CAAC,QAAQsB;IACnC;AACJ;AAEO,MAAME,kBAAkBC,iBAAiB,oBAAoB,CAAC;IACjE,gBAAgB5B;IAChB,cAAc;QAAC6B;KAA4B;AAC/C;AAEA,MAAMC;;aACO,IAAI,GAAG;aACP,MAAM,GAAG;aACT,IAAI,GAAG;aACP,OAAO,GAAGH;;AACvB;AAGO,MAAMI,4BAA4BC,oBAAoB,oBAAoB,CAAC;IAC9E,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { UploadPartRouteDefinition } from "./UploadPartRoute.js";
|
|
3
|
+
const UploadPartRouteFeature = createFeature({
|
|
4
|
+
name: "FileManagerServer/UploadPartRoute",
|
|
5
|
+
register (container) {
|
|
6
|
+
container.register(UploadPartRouteDefinition);
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
export { UploadPartRouteFeature };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes/UploadPartRoute/feature.js","sources":["../../../src/routes/UploadPartRoute/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { UploadPartRouteDefinition } from \"./UploadPartRoute.js\";\n\nexport const UploadPartRouteFeature = createFeature({\n name: \"FileManagerServer/UploadPartRoute\",\n register(container) {\n container.register(UploadPartRouteDefinition);\n }\n});\n"],"names":["UploadPartRouteFeature","createFeature","container","UploadPartRouteDefinition"],"mappings":";;AAGO,MAAMA,yBAAyBC,cAAc;IAChD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
|
|
2
|
+
import { FileManagerStandaloneConfig } from "../../features/FileManagerStandaloneConfig/abstractions.js";
|
|
3
|
+
declare class UploadSingleFileRouteImpl implements HttpRouteHandler.Interface {
|
|
4
|
+
private readonly config;
|
|
5
|
+
constructor(config: FileManagerStandaloneConfig.Interface);
|
|
6
|
+
handle(request: HttpRouteHandler.Request, response: HttpRouteHandler.Response): Promise<import("@webiny/event-handler-core").IHttpResponseBuilder>;
|
|
7
|
+
}
|
|
8
|
+
export declare const UploadSingleFileRoute: typeof UploadSingleFileRouteImpl & {
|
|
9
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
|
|
10
|
+
};
|
|
11
|
+
declare class UploadSingleFileRouteDefinitionImpl implements HttpRouteDefinition.Interface {
|
|
12
|
+
readonly name = "upload-single-file";
|
|
13
|
+
readonly method = "POST";
|
|
14
|
+
readonly path = "/webiny-file-upload";
|
|
15
|
+
readonly handler: typeof UploadSingleFileRouteImpl & {
|
|
16
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** What the router matches on. Zero dependencies, so building it costs nothing. */
|
|
20
|
+
export declare const UploadSingleFileRouteDefinition: typeof UploadSingleFileRouteDefinitionImpl & {
|
|
21
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRouteDefinition>;
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
|
|
4
|
+
import { verifyUploadToken } from "../../utils/uploadToken.js";
|
|
5
|
+
import { FileManagerStandaloneConfig } from "../../features/FileManagerStandaloneConfig/abstractions.js";
|
|
6
|
+
import { getBoundary, isPathContained, parseMultipart, toBuffer } from "../utils.js";
|
|
7
|
+
class UploadSingleFileRouteImpl {
|
|
8
|
+
constructor(config){
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
async handle(request, response) {
|
|
12
|
+
const storagePath = this.config.storagePath;
|
|
13
|
+
const secret = this.config.uploadSecret;
|
|
14
|
+
const contentType = request.headers["content-type"] ?? request.headers["Content-Type"] ?? "";
|
|
15
|
+
const boundary = getBoundary(contentType);
|
|
16
|
+
if (!boundary) return response.status(400).json({
|
|
17
|
+
error: "Expected multipart/form-data with a boundary."
|
|
18
|
+
});
|
|
19
|
+
const { fields, files } = parseMultipart(toBuffer(request.body), boundary);
|
|
20
|
+
const key = fields.find((field)=>"key" === field.name)?.value;
|
|
21
|
+
const token = fields.find((field)=>"token" === field.name)?.value;
|
|
22
|
+
const file = files[0];
|
|
23
|
+
if (!key || !token) return response.status(400).json({
|
|
24
|
+
error: "Missing key or token."
|
|
25
|
+
});
|
|
26
|
+
if (!file) return response.status(400).json({
|
|
27
|
+
error: "No file in request."
|
|
28
|
+
});
|
|
29
|
+
let payload;
|
|
30
|
+
try {
|
|
31
|
+
payload = verifyUploadToken(token, secret);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return response.status(400).json({
|
|
34
|
+
error: err instanceof Error ? err.message : "Invalid token."
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (payload.key !== key) return response.status(400).json({
|
|
38
|
+
error: "Token key mismatch."
|
|
39
|
+
});
|
|
40
|
+
const fileSize = file.data.length;
|
|
41
|
+
if (payload.uploadMaxFileSize > 0 && fileSize > payload.uploadMaxFileSize) return response.status(400).json({
|
|
42
|
+
error: "File exceeds maximum allowed size."
|
|
43
|
+
});
|
|
44
|
+
if (payload.uploadMinFileSize > 0 && fileSize < payload.uploadMinFileSize) return response.status(400).json({
|
|
45
|
+
error: "File is below minimum allowed size."
|
|
46
|
+
});
|
|
47
|
+
const destPath = node_path.join(storagePath, key);
|
|
48
|
+
if (!isPathContained(destPath, storagePath)) return response.status(400).json({
|
|
49
|
+
error: "Invalid path."
|
|
50
|
+
});
|
|
51
|
+
await mkdir(node_path.dirname(destPath), {
|
|
52
|
+
recursive: true
|
|
53
|
+
});
|
|
54
|
+
await writeFile(destPath, file.data);
|
|
55
|
+
return response.status(204);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const UploadSingleFileRoute = HttpRouteHandler.createImplementation({
|
|
59
|
+
implementation: UploadSingleFileRouteImpl,
|
|
60
|
+
dependencies: [
|
|
61
|
+
FileManagerStandaloneConfig
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
class UploadSingleFileRouteDefinitionImpl {
|
|
65
|
+
constructor(){
|
|
66
|
+
this.name = "upload-single-file";
|
|
67
|
+
this.method = "POST";
|
|
68
|
+
this.path = "/webiny-file-upload";
|
|
69
|
+
this.handler = UploadSingleFileRoute;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const UploadSingleFileRouteDefinition = HttpRouteDefinition.createImplementation({
|
|
73
|
+
implementation: UploadSingleFileRouteDefinitionImpl,
|
|
74
|
+
dependencies: []
|
|
75
|
+
});
|
|
76
|
+
export { UploadSingleFileRoute, UploadSingleFileRouteDefinition };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=UploadSingleFileRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes/UploadSingleFileRoute/UploadSingleFileRoute.js","sources":["../../../src/routes/UploadSingleFileRoute/UploadSingleFileRoute.ts"],"sourcesContent":["import path from \"node:path\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { HttpRouteDefinition, HttpRouteHandler } from \"@webiny/event-handler-core\";\nimport { verifyUploadToken } from \"~/utils/uploadToken.js\";\nimport { FileManagerStandaloneConfig } from \"~/features/FileManagerStandaloneConfig/abstractions.js\";\nimport { isPathContained, toBuffer, parseMultipart, getBoundary } from \"../utils.js\";\n\nclass UploadSingleFileRouteImpl implements HttpRouteHandler.Interface {\n public constructor(private readonly config: FileManagerStandaloneConfig.Interface) {}\n\n public async handle(request: HttpRouteHandler.Request, response: HttpRouteHandler.Response) {\n const storagePath = this.config.storagePath;\n const secret = this.config.uploadSecret;\n\n const contentType =\n request.headers[\"content-type\"] ?? request.headers[\"Content-Type\"] ?? \"\";\n const boundary = getBoundary(contentType);\n if (!boundary) {\n return response\n .status(400)\n .json({ error: \"Expected multipart/form-data with a boundary.\" });\n }\n\n const { fields, files } = parseMultipart(toBuffer(request.body), boundary);\n const key = fields.find(field => field.name === \"key\")?.value;\n const token = fields.find(field => field.name === \"token\")?.value;\n const file = files[0];\n\n if (!key || !token) {\n return response.status(400).json({ error: \"Missing key or token.\" });\n }\n\n if (!file) {\n return response.status(400).json({ error: \"No file in request.\" });\n }\n\n let payload;\n try {\n payload = verifyUploadToken(token, secret);\n } catch (err) {\n return response\n .status(400)\n .json({ error: err instanceof Error ? err.message : \"Invalid token.\" });\n }\n\n if (payload.key !== key) {\n return response.status(400).json({ error: \"Token key mismatch.\" });\n }\n\n const fileSize = file.data.length;\n if (payload.uploadMaxFileSize > 0 && fileSize > payload.uploadMaxFileSize) {\n return response.status(400).json({ error: \"File exceeds maximum allowed size.\" });\n }\n\n if (payload.uploadMinFileSize > 0 && fileSize < payload.uploadMinFileSize) {\n return response.status(400).json({ error: \"File is below minimum allowed size.\" });\n }\n\n const destPath = path.join(storagePath, key);\n if (!isPathContained(destPath, storagePath)) {\n return response.status(400).json({ error: \"Invalid path.\" });\n }\n\n await mkdir(path.dirname(destPath), { recursive: true });\n await writeFile(destPath, file.data);\n\n return response.status(204);\n }\n}\n\nexport const UploadSingleFileRoute = HttpRouteHandler.createImplementation({\n implementation: UploadSingleFileRouteImpl,\n dependencies: [FileManagerStandaloneConfig]\n});\n\nclass UploadSingleFileRouteDefinitionImpl implements HttpRouteDefinition.Interface {\n readonly name = \"upload-single-file\";\n readonly method = \"POST\";\n readonly path = \"/webiny-file-upload\";\n readonly handler = UploadSingleFileRoute;\n}\n\n/** What the router matches on. Zero dependencies, so building it costs nothing. */\nexport const UploadSingleFileRouteDefinition = HttpRouteDefinition.createImplementation({\n implementation: UploadSingleFileRouteDefinitionImpl,\n dependencies: []\n});\n"],"names":["UploadSingleFileRouteImpl","config","request","response","storagePath","secret","contentType","boundary","getBoundary","fields","files","parseMultipart","toBuffer","key","field","token","file","payload","verifyUploadToken","err","Error","fileSize","destPath","path","isPathContained","mkdir","writeFile","UploadSingleFileRoute","HttpRouteHandler","FileManagerStandaloneConfig","UploadSingleFileRouteDefinitionImpl","UploadSingleFileRouteDefinition","HttpRouteDefinition"],"mappings":";;;;;;AAOA,MAAMA;IACF,YAAoCC,MAA6C,CAAE;aAA/CA,MAAM,GAANA;IAAgD;IAEpF,MAAa,OAAOC,OAAiC,EAAEC,QAAmC,EAAE;QACxF,MAAMC,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW;QAC3C,MAAMC,SAAS,IAAI,CAAC,MAAM,CAAC,YAAY;QAEvC,MAAMC,cACFJ,QAAQ,OAAO,CAAC,eAAe,IAAIA,QAAQ,OAAO,CAAC,eAAe,IAAI;QAC1E,MAAMK,WAAWC,YAAYF;QAC7B,IAAI,CAACC,UACD,OAAOJ,SACF,MAAM,CAAC,KACP,IAAI,CAAC;YAAE,OAAO;QAAgD;QAGvE,MAAM,EAAEM,MAAM,EAAEC,KAAK,EAAE,GAAGC,eAAeC,SAASV,QAAQ,IAAI,GAAGK;QACjE,MAAMM,MAAMJ,OAAO,IAAI,CAACK,CAAAA,QAASA,AAAe,UAAfA,MAAM,IAAI,GAAa;QACxD,MAAMC,QAAQN,OAAO,IAAI,CAACK,CAAAA,QAASA,AAAe,YAAfA,MAAM,IAAI,GAAe;QAC5D,MAAME,OAAON,KAAK,CAAC,EAAE;QAErB,IAAI,CAACG,OAAO,CAACE,OACT,OAAOZ,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAwB;QAGtE,IAAI,CAACa,MACD,OAAOb,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAsB;QAGpE,IAAIc;QACJ,IAAI;YACAA,UAAUC,kBAAkBH,OAAOV;QACvC,EAAE,OAAOc,KAAK;YACV,OAAOhB,SACF,MAAM,CAAC,KACP,IAAI,CAAC;gBAAE,OAAOgB,eAAeC,QAAQD,IAAI,OAAO,GAAG;YAAiB;QAC7E;QAEA,IAAIF,QAAQ,GAAG,KAAKJ,KAChB,OAAOV,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAsB;QAGpE,MAAMkB,WAAWL,KAAK,IAAI,CAAC,MAAM;QACjC,IAAIC,QAAQ,iBAAiB,GAAG,KAAKI,WAAWJ,QAAQ,iBAAiB,EACrE,OAAOd,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAqC;QAGnF,IAAIc,QAAQ,iBAAiB,GAAG,KAAKI,WAAWJ,QAAQ,iBAAiB,EACrE,OAAOd,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAsC;QAGpF,MAAMmB,WAAWC,UAAAA,IAAS,CAACnB,aAAaS;QACxC,IAAI,CAACW,gBAAgBF,UAAUlB,cAC3B,OAAOD,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO;QAAgB;QAG9D,MAAMsB,MAAMF,UAAAA,OAAY,CAACD,WAAW;YAAE,WAAW;QAAK;QACtD,MAAMI,UAAUJ,UAAUN,KAAK,IAAI;QAEnC,OAAOb,SAAS,MAAM,CAAC;IAC3B;AACJ;AAEO,MAAMwB,wBAAwBC,iBAAiB,oBAAoB,CAAC;IACvE,gBAAgB5B;IAChB,cAAc;QAAC6B;KAA4B;AAC/C;AAEA,MAAMC;;aACO,IAAI,GAAG;aACP,MAAM,GAAG;aACT,IAAI,GAAG;aACP,OAAO,GAAGH;;AACvB;AAGO,MAAMI,kCAAkCC,oBAAoB,oBAAoB,CAAC;IACpF,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { UploadSingleFileRouteDefinition } from "./UploadSingleFileRoute.js";
|
|
3
|
+
const UploadSingleFileRouteFeature = createFeature({
|
|
4
|
+
name: "FileManagerServer/UploadSingleFileRoute",
|
|
5
|
+
register (container) {
|
|
6
|
+
container.register(UploadSingleFileRouteDefinition);
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
export { UploadSingleFileRouteFeature };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes/UploadSingleFileRoute/feature.js","sources":["../../../src/routes/UploadSingleFileRoute/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { UploadSingleFileRouteDefinition } from \"./UploadSingleFileRoute.js\";\n\nexport const UploadSingleFileRouteFeature = createFeature({\n name: \"FileManagerServer/UploadSingleFileRoute\",\n register(container) {\n container.register(UploadSingleFileRouteDefinition);\n }\n});\n"],"names":["UploadSingleFileRouteFeature","createFeature","container","UploadSingleFileRouteDefinition"],"mappings":";;AAGO,MAAMA,+BAA+BC,cAAc;IACtD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|