@webiny/api-file-manager-server 0.0.0-unstable.b6d7105cee → 6.6.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/FileManagerServerFeature.d.ts +5 -0
  2. package/FileManagerServerFeature.js +41 -0
  3. package/FileManagerServerFeature.js.map +1 -0
  4. package/assetDelivery/LazyLocalSharpTransform.d.ts +33 -0
  5. package/assetDelivery/LazyLocalSharpTransform.js +32 -0
  6. package/assetDelivery/LazyLocalSharpTransform.js.map +1 -0
  7. package/assetDelivery/LocalAssetResolver.d.ts +6 -4
  8. package/assetDelivery/LocalAssetResolver.js +9 -9
  9. package/assetDelivery/LocalAssetResolver.js.map +1 -1
  10. package/assetDelivery/LocalOutputStrategy.d.ts +3 -2
  11. package/assetDelivery/LocalOutputStrategy.js +4 -4
  12. package/assetDelivery/LocalOutputStrategy.js.map +1 -1
  13. package/assetDelivery/LocalSharpTransform.d.ts +2 -2
  14. package/assetDelivery/LocalSharpTransform.js +20 -33
  15. package/assetDelivery/LocalSharpTransform.js.map +1 -1
  16. package/assetDelivery/assetDeliveryConfig.d.ts +1 -1
  17. package/assetDelivery/feature.js +6 -6
  18. package/assetDelivery/feature.js.map +1 -1
  19. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.d.ts +3 -0
  20. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js +18 -14
  21. package/features/CleanupStaleMultipartUploads/CleanupStaleMultipartUploadsTask.js.map +1 -1
  22. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.d.ts +7 -5
  23. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js +8 -5
  24. package/features/CompleteMultiPartUpload/CompleteMultiPartUploadUseCase.js.map +1 -1
  25. package/features/CompleteMultiPartUpload/feature.js +2 -2
  26. package/features/CompleteMultiPartUpload/feature.js.map +1 -1
  27. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.d.ts +7 -7
  28. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js +9 -10
  29. package/features/CreateMultiPartUpload/CreateMultiPartUploadUseCase.js.map +1 -1
  30. package/features/CreateMultiPartUpload/feature.js +2 -2
  31. package/features/CreateMultiPartUpload/feature.js.map +1 -1
  32. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.d.ts +3 -1
  33. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js +6 -3
  34. package/features/DeleteFileFromDisk/DeleteFileFromDiskHandler.js.map +1 -1
  35. package/features/ExtractMetadata/ExtractMetadataTask.d.ts +3 -1
  36. package/features/ExtractMetadata/ExtractMetadataTask.js +6 -3
  37. package/features/ExtractMetadata/ExtractMetadataTask.js.map +1 -1
  38. package/features/FileManagerServerConfig/FileManagerServerConfig.d.ts +12 -0
  39. package/features/FileManagerServerConfig/FileManagerServerConfig.js +28 -0
  40. package/features/FileManagerServerConfig/FileManagerServerConfig.js.map +1 -0
  41. package/features/FileManagerServerConfig/abstractions.d.ts +10 -0
  42. package/features/FileManagerServerConfig/abstractions.js +5 -0
  43. package/features/FileManagerServerConfig/abstractions.js.map +1 -0
  44. package/features/FileManagerServerConfig/feature.d.ts +4 -0
  45. package/features/FileManagerServerConfig/feature.js +11 -0
  46. package/features/FileManagerServerConfig/feature.js.map +1 -0
  47. package/features/GetFileContentsById/GetFileContentsByIdUseCase.d.ts +7 -5
  48. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js +8 -5
  49. package/features/GetFileContentsById/GetFileContentsByIdUseCase.js.map +1 -1
  50. package/features/GetFileContentsById/feature.js +2 -2
  51. package/features/GetFileContentsById/feature.js.map +1 -1
  52. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.d.ts +7 -5
  53. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js +8 -5
  54. package/features/GetFileContentsByKey/GetFileContentsByKeyUseCase.js.map +1 -1
  55. package/features/GetFileContentsByKey/feature.js +2 -2
  56. package/features/GetFileContentsByKey/feature.js.map +1 -1
  57. package/features/GetUploadPayload/GetUploadPayloadUseCase.d.ts +6 -6
  58. package/features/GetUploadPayload/GetUploadPayloadUseCase.js +8 -9
  59. package/features/GetUploadPayload/GetUploadPayloadUseCase.js.map +1 -1
  60. package/features/GetUploadPayload/feature.js +2 -2
  61. package/features/GetUploadPayload/feature.js.map +1 -1
  62. package/graphql/ServerGraphQLSchema.d.ts +15 -0
  63. package/graphql/ServerGraphQLSchema.js +221 -0
  64. package/graphql/ServerGraphQLSchema.js.map +1 -0
  65. package/index.d.ts +1 -2
  66. package/index.js +1 -40
  67. package/package.json +15 -15
  68. package/routes/UploadPartRoute/UploadPartRoute.d.ts +23 -0
  69. package/routes/UploadPartRoute/UploadPartRoute.js +71 -0
  70. package/routes/UploadPartRoute/UploadPartRoute.js.map +1 -0
  71. package/routes/UploadPartRoute/feature.d.ts +4 -0
  72. package/routes/UploadPartRoute/feature.js +11 -0
  73. package/routes/UploadPartRoute/feature.js.map +1 -0
  74. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.d.ts +23 -0
  75. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js +78 -0
  76. package/routes/UploadSingleFileRoute/UploadSingleFileRoute.js.map +1 -0
  77. package/routes/UploadSingleFileRoute/feature.d.ts +4 -0
  78. package/routes/UploadSingleFileRoute/feature.js +11 -0
  79. package/routes/UploadSingleFileRoute/feature.js.map +1 -0
  80. package/routes/utils.d.ts +18 -0
  81. package/routes/utils.js +55 -0
  82. package/routes/utils.js.map +1 -0
  83. package/index.js.map +0 -1
  84. package/routes/uploadRoutes.d.ts +0 -4
  85. package/routes/uploadRoutes.js +0 -130
  86. package/routes/uploadRoutes.js.map +0 -1
  87. package/utils/resolveServerUrl.d.ts +0 -2
  88. package/utils/resolveServerUrl.js +0 -10
  89. package/utils/resolveServerUrl.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-file-manager-server",
3
- "version": "0.0.0-unstable.b6d7105cee",
3
+ "version": "6.6.0-alpha.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -14,25 +14,25 @@
14
14
  "author": "Webiny Ltd",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@fastify/multipart": "10.1.0",
18
- "@webiny/api": "0.0.0-unstable.b6d7105cee",
19
- "@webiny/api-core": "0.0.0-unstable.b6d7105cee",
20
- "@webiny/api-file-manager": "0.0.0-unstable.b6d7105cee",
21
- "@webiny/background-tasks": "0.0.0-unstable.b6d7105cee",
22
- "@webiny/feature": "0.0.0-unstable.b6d7105cee",
23
- "@webiny/handler": "0.0.0-unstable.b6d7105cee",
24
- "@webiny/plugins": "0.0.0-unstable.b6d7105cee",
25
- "@webiny/utils": "0.0.0-unstable.b6d7105cee",
26
- "@webiny/validation": "0.0.0-unstable.b6d7105cee",
27
- "exifreader": "4.41.3",
28
- "fastify": "5.10.0",
17
+ "@webiny/api-core": "6.6.0-alpha.1",
18
+ "@webiny/api-file-manager": "6.6.0-alpha.1",
19
+ "@webiny/api-graphql": "6.6.0-alpha.1",
20
+ "@webiny/background-tasks": "6.6.0-alpha.1",
21
+ "@webiny/event-handler-core": "6.6.0-alpha.1",
22
+ "@webiny/feature": "6.6.0-alpha.1",
23
+ "@webiny/handler": "6.6.0-alpha.1",
24
+ "@webiny/plugins": "6.6.0-alpha.1",
25
+ "@webiny/utils": "6.6.0-alpha.1",
26
+ "@webiny/validation": "6.6.0-alpha.1",
27
+ "exifreader": "4.43.0",
28
+ "p-map": "7.0.6",
29
29
  "sharp": "0.35.3"
30
30
  },
31
31
  "devDependencies": {
32
- "@webiny/build-tools": "0.0.0-unstable.b6d7105cee",
32
+ "@webiny/build-tools": "6.6.0-alpha.1",
33
33
  "rimraf": "6.1.3",
34
34
  "typescript": "7.0.2",
35
- "vitest": "4.1.10"
35
+ "vitest": "4.1.11"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"
@@ -0,0 +1,23 @@
1
+ import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
2
+ import { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
3
+ declare class UploadPartRouteImpl implements HttpRouteHandler.Interface {
4
+ private readonly config;
5
+ constructor(config: FileManagerServerConfig.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 { FileManagerServerConfig } from "../../features/FileManagerServerConfig/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
+ FileManagerServerConfig
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 { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\nimport { isPathContained, toBuffer } from \"../utils.js\";\n\nclass UploadPartRouteImpl implements HttpRouteHandler.Interface {\n public constructor(private readonly config: FileManagerServerConfig.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: [FileManagerServerConfig]\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","FileManagerServerConfig","UploadPartRouteDefinitionImpl","UploadPartRouteDefinition","HttpRouteDefinition"],"mappings":";;;;;;;AAQA,MAAMA;IACF,YAAoCC,MAAyC,CAAE;aAA3CA,MAAM,GAANA;IAA4C;IAEhF,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;KAAwB;AAC3C;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,4 @@
1
+ export declare const UploadPartRouteFeature: {
2
+ name: string;
3
+ register(container: import("@webiny/di").Container): void;
4
+ };
@@ -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 { FileManagerServerConfig } from "../../features/FileManagerServerConfig/abstractions.js";
3
+ declare class UploadSingleFileRouteImpl implements HttpRouteHandler.Interface {
4
+ private readonly config;
5
+ constructor(config: FileManagerServerConfig.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 { FileManagerServerConfig } from "../../features/FileManagerServerConfig/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
+ FileManagerServerConfig
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 { FileManagerServerConfig } from \"~/features/FileManagerServerConfig/abstractions.js\";\nimport { isPathContained, toBuffer, parseMultipart, getBoundary } from \"../utils.js\";\n\nclass UploadSingleFileRouteImpl implements HttpRouteHandler.Interface {\n public constructor(private readonly config: FileManagerServerConfig.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: [FileManagerServerConfig]\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","FileManagerServerConfig","UploadSingleFileRouteDefinitionImpl","UploadSingleFileRouteDefinition","HttpRouteDefinition"],"mappings":";;;;;;AAOA,MAAMA;IACF,YAAoCC,MAAyC,CAAE;aAA3CA,MAAM,GAANA;IAA4C;IAEhF,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;KAAwB;AAC3C;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,4 @@
1
+ export declare const UploadSingleFileRouteFeature: {
2
+ name: string;
3
+ register(container: import("@webiny/di").Container): void;
4
+ };
@@ -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"}
@@ -0,0 +1,18 @@
1
+ export declare const isPathContained: (filePath: string, storagePath: string) => boolean;
2
+ export declare const toBuffer: (body: unknown) => Buffer;
3
+ interface MultipartField {
4
+ name: string;
5
+ value: string;
6
+ }
7
+ interface MultipartFile {
8
+ name: string;
9
+ filename: string;
10
+ data: Buffer;
11
+ }
12
+ export interface MultipartResult {
13
+ fields: MultipartField[];
14
+ files: MultipartFile[];
15
+ }
16
+ export declare const parseMultipart: (buffer: Buffer, boundary: string) => MultipartResult;
17
+ export declare const getBoundary: (contentType: string) => string | undefined;
18
+ export {};
@@ -0,0 +1,55 @@
1
+ import node_path from "node:path";
2
+ const isPathContained = (filePath, storagePath)=>{
3
+ const resolved = node_path.resolve(filePath);
4
+ const root = node_path.resolve(storagePath);
5
+ return resolved === root || resolved.startsWith(root + node_path.sep);
6
+ };
7
+ const toBuffer = (body)=>{
8
+ if (Buffer.isBuffer(body)) return body;
9
+ if (body instanceof Uint8Array) return Buffer.from(body);
10
+ if ("string" == typeof body) return Buffer.from(body, "base64");
11
+ return Buffer.alloc(0);
12
+ };
13
+ const parseMultipart = (buffer, boundary)=>{
14
+ const fields = [];
15
+ const files = [];
16
+ const separator = Buffer.from(`--${boundary}`);
17
+ let idx = buffer.indexOf(separator);
18
+ while(-1 !== idx){
19
+ const next = buffer.indexOf(separator, idx + separator.length);
20
+ if (-1 === next) break;
21
+ let part = buffer.subarray(idx + separator.length, next);
22
+ if ("\r\n" === part.subarray(0, 2).toString("latin1")) part = part.subarray(2);
23
+ if ("\r\n" === part.subarray(-2).toString("latin1")) part = part.subarray(0, -2);
24
+ const headerEnd = part.indexOf("\r\n\r\n");
25
+ if (-1 !== headerEnd) {
26
+ const rawHeaders = part.subarray(0, headerEnd).toString("utf8");
27
+ const content = part.subarray(headerEnd + 4);
28
+ const disposition = /content-disposition:[^\r\n]*/i.exec(rawHeaders)?.[0] ?? "";
29
+ const name = /name="([^"]*)"/i.exec(disposition)?.[1];
30
+ const filename = /filename="([^"]*)"/i.exec(disposition)?.[1];
31
+ if (void 0 !== name) if (void 0 !== filename) files.push({
32
+ name,
33
+ filename,
34
+ data: content
35
+ });
36
+ else fields.push({
37
+ name,
38
+ value: content.toString("utf8")
39
+ });
40
+ }
41
+ idx = next;
42
+ }
43
+ return {
44
+ fields,
45
+ files
46
+ };
47
+ };
48
+ const getBoundary = (contentType)=>{
49
+ const match = /boundary=(?:"([^"]+)"|([^;]+))/i.exec(contentType);
50
+ const value = match?.[1] ?? match?.[2];
51
+ return value?.trim();
52
+ };
53
+ export { getBoundary, isPathContained, parseMultipart, toBuffer };
54
+
55
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes/utils.js","sources":["../../src/routes/utils.ts"],"sourcesContent":["import path from \"node:path\";\n\nexport const isPathContained = (filePath: string, storagePath: string): boolean => {\n const resolved = path.resolve(filePath);\n const root = path.resolve(storagePath);\n return resolved === root || resolved.startsWith(root + path.sep);\n};\n\n/* Normalise a transport request body into a Buffer. */\nexport const toBuffer = (body: unknown): Buffer => {\n if (Buffer.isBuffer(body)) {\n return body;\n }\n if (body instanceof Uint8Array) {\n return Buffer.from(body);\n }\n if (typeof body === \"string\") {\n return Buffer.from(body, \"base64\");\n }\n return Buffer.alloc(0);\n};\n\ninterface MultipartField {\n name: string;\n value: string;\n}\n\ninterface MultipartFile {\n name: string;\n filename: string;\n data: Buffer;\n}\n\nexport interface MultipartResult {\n fields: MultipartField[];\n files: MultipartFile[];\n}\n\n/* Minimal multipart/form-data parser operating on the raw body buffer. */\nexport const parseMultipart = (buffer: Buffer, boundary: string): MultipartResult => {\n const fields: MultipartField[] = [];\n const files: MultipartFile[] = [];\n const separator = Buffer.from(`--${boundary}`);\n\n let idx = buffer.indexOf(separator);\n while (idx !== -1) {\n const next = buffer.indexOf(separator, idx + separator.length);\n if (next === -1) {\n break;\n }\n\n let part = buffer.subarray(idx + separator.length, next);\n if (part.subarray(0, 2).toString(\"latin1\") === \"\\r\\n\") {\n part = part.subarray(2);\n }\n if (part.subarray(-2).toString(\"latin1\") === \"\\r\\n\") {\n part = part.subarray(0, -2);\n }\n\n const headerEnd = part.indexOf(\"\\r\\n\\r\\n\");\n if (headerEnd !== -1) {\n const rawHeaders = part.subarray(0, headerEnd).toString(\"utf8\");\n const content = part.subarray(headerEnd + 4);\n\n const disposition = /content-disposition:[^\\r\\n]*/i.exec(rawHeaders)?.[0] ?? \"\";\n const name = /name=\"([^\"]*)\"/i.exec(disposition)?.[1];\n const filename = /filename=\"([^\"]*)\"/i.exec(disposition)?.[1];\n\n if (name !== undefined) {\n if (filename !== undefined) {\n files.push({ name, filename, data: content });\n } else {\n fields.push({ name, value: content.toString(\"utf8\") });\n }\n }\n }\n\n idx = next;\n }\n\n return { fields, files };\n};\n\nexport const getBoundary = (contentType: string): string | undefined => {\n const match = /boundary=(?:\"([^\"]+)\"|([^;]+))/i.exec(contentType);\n const value = match?.[1] ?? match?.[2];\n return value?.trim();\n};\n"],"names":["isPathContained","filePath","storagePath","resolved","path","root","toBuffer","body","Buffer","Uint8Array","parseMultipart","buffer","boundary","fields","files","separator","idx","next","part","headerEnd","rawHeaders","content","disposition","name","filename","undefined","getBoundary","contentType","match","value"],"mappings":";AAEO,MAAMA,kBAAkB,CAACC,UAAkBC;IAC9C,MAAMC,WAAWC,UAAAA,OAAY,CAACH;IAC9B,MAAMI,OAAOD,UAAAA,OAAY,CAACF;IAC1B,OAAOC,aAAaE,QAAQF,SAAS,UAAU,CAACE,OAAOD,UAAAA,GAAQ;AACnE;AAGO,MAAME,WAAW,CAACC;IACrB,IAAIC,OAAO,QAAQ,CAACD,OAChB,OAAOA;IAEX,IAAIA,gBAAgBE,YAChB,OAAOD,OAAO,IAAI,CAACD;IAEvB,IAAI,AAAgB,YAAhB,OAAOA,MACP,OAAOC,OAAO,IAAI,CAACD,MAAM;IAE7B,OAAOC,OAAO,KAAK,CAAC;AACxB;AAmBO,MAAME,iBAAiB,CAACC,QAAgBC;IAC3C,MAAMC,SAA2B,EAAE;IACnC,MAAMC,QAAyB,EAAE;IACjC,MAAMC,YAAYP,OAAO,IAAI,CAAC,CAAC,EAAE,EAAEI,UAAU;IAE7C,IAAII,MAAML,OAAO,OAAO,CAACI;IACzB,MAAOC,AAAQ,OAARA,IAAY;QACf,MAAMC,OAAON,OAAO,OAAO,CAACI,WAAWC,MAAMD,UAAU,MAAM;QAC7D,IAAIE,AAAS,OAATA,MACA;QAGJ,IAAIC,OAAOP,OAAO,QAAQ,CAACK,MAAMD,UAAU,MAAM,EAAEE;QACnD,IAAIC,AAA2C,WAA3CA,KAAK,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,WAC7BA,OAAOA,KAAK,QAAQ,CAAC;QAEzB,IAAIA,AAAyC,WAAzCA,KAAK,QAAQ,CAAC,IAAI,QAAQ,CAAC,WAC3BA,OAAOA,KAAK,QAAQ,CAAC,GAAG;QAG5B,MAAMC,YAAYD,KAAK,OAAO,CAAC;QAC/B,IAAIC,AAAc,OAAdA,WAAkB;YAClB,MAAMC,aAAaF,KAAK,QAAQ,CAAC,GAAGC,WAAW,QAAQ,CAAC;YACxD,MAAME,UAAUH,KAAK,QAAQ,CAACC,YAAY;YAE1C,MAAMG,cAAc,gCAAgC,IAAI,CAACF,aAAa,CAAC,EAAE,IAAI;YAC7E,MAAMG,OAAO,kBAAkB,IAAI,CAACD,cAAc,CAAC,EAAE;YACrD,MAAME,WAAW,sBAAsB,IAAI,CAACF,cAAc,CAAC,EAAE;YAE7D,IAAIC,AAASE,WAATF,MACA,IAAIC,AAAaC,WAAbD,UACAV,MAAM,IAAI,CAAC;gBAAES;gBAAMC;gBAAU,MAAMH;YAAQ;iBAE3CR,OAAO,IAAI,CAAC;gBAAEU;gBAAM,OAAOF,QAAQ,QAAQ,CAAC;YAAQ;QAGhE;QAEAL,MAAMC;IACV;IAEA,OAAO;QAAEJ;QAAQC;IAAM;AAC3B;AAEO,MAAMY,cAAc,CAACC;IACxB,MAAMC,QAAQ,kCAAkC,IAAI,CAACD;IACrD,MAAME,QAAQD,OAAO,CAAC,EAAE,IAAIA,OAAO,CAAC,EAAE;IACtC,OAAOC,OAAO;AAClB"}
package/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdirSync } from \"node:fs\";\nimport { ContextPlugin } from \"@webiny/api\";\nimport { uploadRoutesPlugin } from \"~/routes/uploadRoutes.js\";\nimport { modifyFastifyPlugin } from \"~/routes/uploadRoutes.js\";\nimport { CleanupStaleMultipartUploadsFeature } from \"~/features/CleanupStaleMultipartUploads/feature.js\";\nimport { DeleteFileFromDiskFeature } from \"~/features/DeleteFileFromDisk/feature.js\";\nimport { ExtractMetadataFeature } from \"~/features/ExtractMetadata/feature.js\";\nimport { FlushCacheFeature } from \"~/features/FlushCache/feature.js\";\nimport { GetFileContentsByIdFeature } from \"~/features/GetFileContentsById/feature.js\";\nimport { GetFileContentsByKeyFeature } from \"~/features/GetFileContentsByKey/feature.js\";\nimport { GetUploadPayloadFeature } from \"~/features/GetUploadPayload/feature.js\";\nimport { CreateMultiPartUploadFeature } from \"~/features/CreateMultiPartUpload/feature.js\";\nimport { CompleteMultiPartUploadFeature } from \"~/features/CompleteMultiPartUpload/feature.js\";\nexport { createFileUploadModifier } from \"@webiny/api-file-manager/features/upload/index.js\";\nexport { createAssetDelivery } from \"./assetDelivery/createAssetDelivery.js\";\n\nconst contextPlugin = new ContextPlugin(context => {\n const storagePath = process.env[\"WEBINY_LOCAL_STORAGE_PATH\"];\n if (!storagePath) {\n throw new Error(\n `\"WEBINY_LOCAL_STORAGE_PATH\" environment variable is not defined. Please set it to a valid local path.`\n );\n }\n\n const uploadSecret = process.env[\"WEBINY_UPLOAD_SECRET\"];\n if (!uploadSecret) {\n throw new Error(\n `\"WEBINY_UPLOAD_SECRET\" environment variable is not defined. Please set it to a secret string used to sign upload tokens.`\n );\n }\n\n if (!existsSync(storagePath)) {\n mkdirSync(storagePath, { recursive: true });\n }\n\n const container = context.container;\n\n FlushCacheFeature.register(container);\n DeleteFileFromDiskFeature.register(container);\n ExtractMetadataFeature.register(container);\n GetFileContentsByIdFeature.register(container);\n GetFileContentsByKeyFeature.register(container);\n GetUploadPayloadFeature.register(container);\n CreateMultiPartUploadFeature.register(container);\n CompleteMultiPartUploadFeature.register(container);\n CleanupStaleMultipartUploadsFeature.register(container);\n});\n\ncontextPlugin.name = `fileManagerServer.context`;\n\nexport const createFileManagerServer = () => [\n contextPlugin,\n uploadRoutesPlugin,\n modifyFastifyPlugin\n];\n"],"names":["contextPlugin","ContextPlugin","context","storagePath","process","Error","uploadSecret","existsSync","mkdirSync","container","FlushCacheFeature","DeleteFileFromDiskFeature","ExtractMetadataFeature","GetFileContentsByIdFeature","GetFileContentsByKeyFeature","GetUploadPayloadFeature","CreateMultiPartUploadFeature","CompleteMultiPartUploadFeature","CleanupStaleMultipartUploadsFeature","createFileManagerServer","uploadRoutesPlugin","modifyFastifyPlugin"],"mappings":";;;;;;;;;;;;AAiBA,MAAMA,gBAAgB,IAAIC,cAAcC,CAAAA;IACpC,MAAMC,cAAcC,QAAQ,GAAG,CAAC,4BAA4B;IAC5D,IAAI,CAACD,aACD,MAAM,IAAIE,MACN;IAIR,MAAMC,eAAeF,QAAQ,GAAG,CAAC,uBAAuB;IACxD,IAAI,CAACE,cACD,MAAM,IAAID,MACN;IAIR,IAAI,CAACE,WAAWJ,cACZK,UAAUL,aAAa;QAAE,WAAW;IAAK;IAG7C,MAAMM,YAAYP,QAAQ,SAAS;IAEnCQ,kBAAkB,QAAQ,CAACD;IAC3BE,0BAA0B,QAAQ,CAACF;IACnCG,uBAAuB,QAAQ,CAACH;IAChCI,2BAA2B,QAAQ,CAACJ;IACpCK,4BAA4B,QAAQ,CAACL;IACrCM,wBAAwB,QAAQ,CAACN;IACjCO,6BAA6B,QAAQ,CAACP;IACtCQ,+BAA+B,QAAQ,CAACR;IACxCS,oCAAoC,QAAQ,CAACT;AACjD;AAEAT,cAAc,IAAI,GAAG;AAEd,MAAMmB,0BAA0B,IAAM;QACzCnB;QACAoB;QACAC;KACH"}
@@ -1,4 +0,0 @@
1
- import { RoutePlugin } from "@webiny/handler/plugins/RoutePlugin.js";
2
- import { ModifyFastifyPlugin } from "@webiny/handler/plugins/ModifyFastifyPlugin.js";
3
- export declare const modifyFastifyPlugin: ModifyFastifyPlugin;
4
- export declare const uploadRoutesPlugin: RoutePlugin<import("@webiny/handler/types").Context>;
@@ -1,130 +0,0 @@
1
- import node_path from "node:path";
2
- import { Readable } from "node:stream";
3
- import { createHash } from "node:crypto";
4
- import { mkdir, writeFile } from "node:fs/promises";
5
- import { createWriteStream } from "node:fs";
6
- import { pipeline } from "node:stream/promises";
7
- import { RoutePlugin } from "@webiny/handler/plugins/RoutePlugin.js";
8
- import { ModifyFastifyPlugin } from "@webiny/handler/plugins/ModifyFastifyPlugin.js";
9
- import { verifyUploadToken } from "../utils/uploadToken.js";
10
- const getStoragePath = ()=>String(process.env.WEBINY_LOCAL_STORAGE_PATH);
11
- const getUploadSecret = ()=>String(process.env.WEBINY_UPLOAD_SECRET);
12
- const isPathContained = (filePath, storagePath)=>{
13
- const resolved = node_path.resolve(filePath);
14
- const root = node_path.resolve(storagePath);
15
- if (!resolved.startsWith(root + node_path.sep) && resolved !== root) return false;
16
- return true;
17
- };
18
- const modifyFastifyPlugin = new ModifyFastifyPlugin((app)=>{
19
- app.register(import("@fastify/multipart"), {
20
- limits: {
21
- fileSize: 5368709120
22
- }
23
- });
24
- app.addContentTypeParser("application/octet-stream", {
25
- parseAs: "buffer"
26
- }, (_request, body, done)=>{
27
- done(null, body);
28
- });
29
- });
30
- modifyFastifyPlugin.name = "fileManagerServer.modifyFastify";
31
- const uploadRoutesPlugin = new RoutePlugin(({ onPost, onPut })=>{
32
- onPost("/webiny-file-upload", async (request, reply)=>{
33
- const storagePath = getStoragePath();
34
- const secret = getUploadSecret();
35
- let key;
36
- let token;
37
- let fileChunks;
38
- let fileSize = 0;
39
- const parts = request.parts();
40
- for await (const part of parts)if ("field" === part.type) {
41
- if ("key" === part.fieldname) key = part.value;
42
- else if ("token" === part.fieldname) token = part.value;
43
- } else if ("file" === part.type) {
44
- const chunks = [];
45
- for await (const chunk of part.file){
46
- chunks.push(chunk);
47
- fileSize += chunk.length;
48
- }
49
- fileChunks = chunks;
50
- }
51
- if (!key || !token) return reply.code(400).send({
52
- error: "Missing key or token."
53
- });
54
- if (!fileChunks) return reply.code(400).send({
55
- error: "No file in request."
56
- });
57
- let payload;
58
- try {
59
- payload = verifyUploadToken(token, secret);
60
- } catch (err) {
61
- return reply.code(400).send({
62
- error: err instanceof Error ? err.message : "Invalid token."
63
- });
64
- }
65
- if (payload.key !== key) return reply.code(400).send({
66
- error: "Token key mismatch."
67
- });
68
- if (payload.uploadMaxFileSize > 0 && fileSize > payload.uploadMaxFileSize) return reply.code(400).send({
69
- error: "File exceeds maximum allowed size."
70
- });
71
- if (payload.uploadMinFileSize > 0 && fileSize < payload.uploadMinFileSize) return reply.code(400).send({
72
- error: "File is below minimum allowed size."
73
- });
74
- const destPath = node_path.join(storagePath, key);
75
- if (!isPathContained(destPath, storagePath)) return reply.code(400).send({
76
- error: "Invalid path."
77
- });
78
- const destDir = node_path.dirname(destPath);
79
- await mkdir(destDir, {
80
- recursive: true
81
- });
82
- const writeStream = createWriteStream(destPath);
83
- const readable = Readable.from(fileChunks);
84
- await pipeline(readable, writeStream);
85
- return reply.code(204).send();
86
- });
87
- onPut("/webiny-file-upload/parts", async (request, reply)=>{
88
- const storagePath = getStoragePath();
89
- const secret = getUploadSecret();
90
- const query = request.query;
91
- const uploadId = query["uploadId"];
92
- const partNumberStr = query["partNumber"];
93
- const token = query["token"];
94
- if (!uploadId || !partNumberStr || !token) return reply.code(400).send({
95
- error: "Missing uploadId, partNumber, or token."
96
- });
97
- const partNumber = parseInt(partNumberStr, 10);
98
- if (isNaN(partNumber) || partNumber < 1) return reply.code(400).send({
99
- error: "Invalid partNumber."
100
- });
101
- let payload;
102
- try {
103
- payload = verifyUploadToken(token, secret);
104
- } catch (err) {
105
- return reply.code(400).send({
106
- error: err instanceof Error ? err.message : "Invalid token."
107
- });
108
- }
109
- const expectedKey = `tenants/${payload.tenantId}/multipart/${uploadId}/part-${partNumber}`;
110
- if (payload.key !== expectedKey) return reply.code(400).send({
111
- error: "Token key mismatch."
112
- });
113
- const destPath = node_path.join(storagePath, expectedKey);
114
- if (!isPathContained(destPath, storagePath)) return reply.code(400).send({
115
- error: "Invalid path."
116
- });
117
- const destDir = node_path.dirname(destPath);
118
- await mkdir(destDir, {
119
- recursive: true
120
- });
121
- const body = request.body;
122
- await writeFile(destPath, body);
123
- const etag = createHash("md5").update(body).digest("hex");
124
- return reply.code(200).header("ETag", etag).send();
125
- });
126
- });
127
- uploadRoutesPlugin.name = "fileManagerServer.uploadRoutes";
128
- export { modifyFastifyPlugin, uploadRoutesPlugin };
129
-
130
- //# sourceMappingURL=uploadRoutes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes/uploadRoutes.js","sources":["../../src/routes/uploadRoutes.ts"],"sourcesContent":["import path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir } from \"node:fs/promises\";\nimport { writeFile } from \"node:fs/promises\";\nimport { createWriteStream } from \"node:fs\";\nimport { pipeline } from \"node:stream/promises\";\nimport { RoutePlugin } from \"@webiny/handler/plugins/RoutePlugin.js\";\nimport { ModifyFastifyPlugin } from \"@webiny/handler/plugins/ModifyFastifyPlugin.js\";\nimport { verifyUploadToken } from \"~/utils/uploadToken.js\";\n\nconst getStoragePath = (): string => {\n return String(process.env.WEBINY_LOCAL_STORAGE_PATH);\n};\n\nconst getUploadSecret = (): string => {\n return String(process.env.WEBINY_UPLOAD_SECRET);\n};\n\nconst isPathContained = (filePath: string, storagePath: string): boolean => {\n const resolved = path.resolve(filePath);\n const root = path.resolve(storagePath);\n if (!resolved.startsWith(root + path.sep) && resolved !== root) {\n return false;\n }\n return true;\n};\n\nexport const modifyFastifyPlugin = new ModifyFastifyPlugin(app => {\n app.register(import(\"@fastify/multipart\"), {\n limits: {\n fileSize: 5 * 1024 * 1024 * 1024 /* 5 GB */\n }\n });\n\n app.addContentTypeParser(\n \"application/octet-stream\",\n { parseAs: \"buffer\" },\n (_request, body, done) => {\n done(null, body);\n }\n );\n});\n\nmodifyFastifyPlugin.name = \"fileManagerServer.modifyFastify\";\n\nexport const uploadRoutesPlugin = new RoutePlugin(({ onPost, onPut }) => {\n /* POST /webiny-file-upload — simple single-file upload via multipart/form-data.\n Form fields: key (storage path), token (HMAC upload token).\n File field: the raw file bytes (any field name). */\n onPost(\"/webiny-file-upload\", async (request, reply) => {\n const storagePath = getStoragePath();\n const secret = getUploadSecret();\n\n let key: string | undefined;\n let token: string | undefined;\n let fileChunks: Buffer[] | undefined;\n let fileSize = 0;\n\n const parts = request.parts();\n\n for await (const part of parts) {\n if (part.type === \"field\") {\n if (part.fieldname === \"key\") {\n key = part.value as string;\n } else if (part.fieldname === \"token\") {\n token = part.value as string;\n }\n } else if (part.type === \"file\") {\n /* Collect the file stream into memory so we can measure and hash it. */\n const chunks: Buffer[] = [];\n for await (const chunk of part.file) {\n chunks.push(chunk as Buffer);\n fileSize += (chunk as Buffer).length;\n }\n fileChunks = chunks;\n }\n }\n\n if (!key || !token) {\n return reply.code(400).send({ error: \"Missing key or token.\" });\n }\n\n if (!fileChunks) {\n return reply.code(400).send({ error: \"No file in request.\" });\n }\n\n let payload;\n try {\n payload = verifyUploadToken(token, secret);\n } catch (err) {\n return reply\n .code(400)\n .send({ error: err instanceof Error ? err.message : \"Invalid token.\" });\n }\n\n if (payload.key !== key) {\n return reply.code(400).send({ error: \"Token key mismatch.\" });\n }\n\n if (payload.uploadMaxFileSize > 0 && fileSize > payload.uploadMaxFileSize) {\n return reply.code(400).send({ error: \"File exceeds maximum allowed size.\" });\n }\n\n if (payload.uploadMinFileSize > 0 && fileSize < payload.uploadMinFileSize) {\n return reply.code(400).send({ error: \"File is below minimum allowed size.\" });\n }\n\n const destPath = path.join(storagePath, key);\n\n if (!isPathContained(destPath, storagePath)) {\n return reply.code(400).send({ error: \"Invalid path.\" });\n }\n\n const destDir = path.dirname(destPath);\n await mkdir(destDir, { recursive: true });\n\n const writeStream = createWriteStream(destPath);\n const readable = Readable.from(fileChunks);\n\n await pipeline(readable, writeStream);\n\n return reply.code(204).send();\n });\n\n /* PUT /webiny-file-upload/parts — multipart chunk upload via raw binary body.\n Query params: uploadId, partNumber, token.\n Body: raw binary chunk (application/octet-stream). */\n onPut(\"/webiny-file-upload/parts\", async (request, reply) => {\n const storagePath = getStoragePath();\n const secret = getUploadSecret();\n\n const query = request.query as Record<string, string | undefined>;\n const uploadId = query[\"uploadId\"];\n const partNumberStr = query[\"partNumber\"];\n const token = query[\"token\"];\n\n if (!uploadId || !partNumberStr || !token) {\n return reply.code(400).send({ error: \"Missing uploadId, partNumber, or token.\" });\n }\n\n const partNumber = parseInt(partNumberStr, 10);\n if (isNaN(partNumber) || partNumber < 1) {\n return reply.code(400).send({ error: \"Invalid partNumber.\" });\n }\n\n let payload;\n try {\n payload = verifyUploadToken(token, secret);\n } catch (err) {\n return reply\n .code(400)\n .send({ error: err instanceof Error ? err.message : \"Invalid token.\" });\n }\n\n const expectedKey = `tenants/${payload.tenantId}/multipart/${uploadId}/part-${partNumber}`;\n\n if (payload.key !== expectedKey) {\n return reply.code(400).send({ error: \"Token key mismatch.\" });\n }\n\n const destPath = path.join(storagePath, expectedKey);\n\n if (!isPathContained(destPath, storagePath)) {\n return reply.code(400).send({ error: \"Invalid path.\" });\n }\n\n const destDir = path.dirname(destPath);\n await mkdir(destDir, { recursive: true });\n\n const body = request.body as Buffer;\n\n await writeFile(destPath, body);\n\n const etag = createHash(\"md5\").update(body).digest(\"hex\");\n\n return reply.code(200).header(\"ETag\", etag).send();\n });\n});\n\nuploadRoutesPlugin.name = \"fileManagerServer.uploadRoutes\";\n"],"names":["getStoragePath","String","process","getUploadSecret","isPathContained","filePath","storagePath","resolved","path","root","modifyFastifyPlugin","ModifyFastifyPlugin","app","_request","body","done","uploadRoutesPlugin","RoutePlugin","onPost","onPut","request","reply","secret","key","token","fileChunks","fileSize","parts","part","chunks","chunk","payload","verifyUploadToken","err","Error","destPath","destDir","mkdir","writeStream","createWriteStream","readable","Readable","pipeline","query","uploadId","partNumberStr","partNumber","parseInt","isNaN","expectedKey","writeFile","etag","createHash"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import type { FastifyRequest } from "fastify";
2
- export declare const resolveServerUrl: (request: FastifyRequest) => Promise<string>;
@@ -1,10 +0,0 @@
1
- import { ServiceDiscovery } from "@webiny/api-core/features/serviceDiscovery/ServiceDiscovery.js";
2
- const resolveServerUrl = async (request)=>{
3
- const manifest = await ServiceDiscovery.load();
4
- const domain = manifest?.api?.cloudfront?.domain;
5
- if (domain) return domain;
6
- return `${request.protocol}://${request.hostname}`;
7
- };
8
- export { resolveServerUrl };
9
-
10
- //# sourceMappingURL=resolveServerUrl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils/resolveServerUrl.js","sources":["../../src/utils/resolveServerUrl.ts"],"sourcesContent":["import { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/ServiceDiscovery.js\";\nimport type { FastifyRequest } from \"fastify\";\n\nexport const resolveServerUrl = async (request: FastifyRequest): Promise<string> => {\n const manifest = await ServiceDiscovery.load();\n const domain = manifest?.api?.cloudfront?.domain;\n if (domain) {\n return domain as string;\n }\n\n return `${request.protocol}://${request.hostname}`;\n};\n"],"names":["resolveServerUrl","request","manifest","ServiceDiscovery","domain"],"mappings":";AAGO,MAAMA,mBAAmB,OAAOC;IACnC,MAAMC,WAAW,MAAMC,iBAAiB,IAAI;IAC5C,MAAMC,SAASF,UAAU,KAAK,YAAY;IAC1C,IAAIE,QACA,OAAOA;IAGX,OAAO,GAAGH,QAAQ,QAAQ,CAAC,GAAG,EAAEA,QAAQ,QAAQ,EAAE;AACtD"}