@webiny/api-file-manager-s3 0.0.0-ee-vpcs.549378cf03

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Webiny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @webiny/api-file-manager-s3
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const _default: () => (import("@webiny/handler-graphql/types").GraphQLSchemaPlugin<import("@webiny/api-file-manager/types").FileManagerContext> | import("@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin").FilePhysicalStoragePlugin<import("@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin").FilePhysicalStoragePluginUploadParams, import("@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin").FilePhysicalStoragePluginDeleteParams>)[];
2
+ export default _default;
package/index.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _graphqlFileStorageS = _interopRequireDefault(require("./plugins/graphqlFileStorageS3"));
11
+
12
+ var _fileStorageS = _interopRequireDefault(require("./plugins/fileStorageS3"));
13
+
14
+ var _default = () => [(0, _fileStorageS.default)(), _graphqlFileStorageS.default];
15
+
16
+ exports.default = _default;
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"names":["fileStorageS3","graphqlFileStorageS3"],"sources":["index.ts"],"sourcesContent":["import graphqlFileStorageS3 from \"./plugins/graphqlFileStorageS3\";\nimport fileStorageS3 from \"./plugins/fileStorageS3\";\n\nexport default () => [fileStorageS3(), graphqlFileStorageS3];\n"],"mappings":";;;;;;;;;AAAA;;AACA;;eAEe,MAAM,CAAC,IAAAA,qBAAA,GAAD,EAAkBC,4BAAlB,C"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@webiny/api-file-manager-s3",
3
+ "version": "0.0.0-ee-vpcs.549378cf03",
4
+ "main": "index.js",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/webiny/webiny-js.git"
8
+ },
9
+ "description": "File storage S3 plugin for the @webiny/api-file-manager.",
10
+ "author": "Webiny Ltd",
11
+ "license": "MIT",
12
+ "dependencies": {
13
+ "@webiny/api-file-manager": "0.0.0-ee-vpcs.549378cf03",
14
+ "@webiny/error": "0.0.0-ee-vpcs.549378cf03",
15
+ "@webiny/handler-graphql": "0.0.0-ee-vpcs.549378cf03",
16
+ "@webiny/validation": "0.0.0-ee-vpcs.549378cf03",
17
+ "form-data": "4.0.0",
18
+ "node-fetch": "2.6.7",
19
+ "sanitize-filename": "1.6.3",
20
+ "uniqid": "5.4.0"
21
+ },
22
+ "devDependencies": {
23
+ "@babel/cli": "^7.19.3",
24
+ "@babel/core": "^7.19.3",
25
+ "@types/node-fetch": "^2.6.1",
26
+ "@webiny/cli": "^0.0.0-ee-vpcs.549378cf03",
27
+ "@webiny/project-utils": "^0.0.0-ee-vpcs.549378cf03",
28
+ "rimraf": "^3.0.2",
29
+ "typescript": "4.7.4"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "directory": "dist"
34
+ },
35
+ "scripts": {
36
+ "build": "yarn webiny run build",
37
+ "watch": "yarn webiny run watch"
38
+ },
39
+ "gitHead": "549378cf03fcd27845fc3fa23d1dc6b32896f630"
40
+ }
@@ -0,0 +1,6 @@
1
+ import { FilePhysicalStoragePlugin, FilePhysicalStoragePluginUploadParams } from "@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin";
2
+ import { PresignedPostPayloadData } from "../types";
3
+ export interface S3FilePhysicalStoragePluginUploadParams extends FilePhysicalStoragePluginUploadParams, PresignedPostPayloadData {
4
+ }
5
+ declare const _default: () => FilePhysicalStoragePlugin;
6
+ export default _default;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
+
12
+ var _s = _interopRequireDefault(require("aws-sdk/clients/s3"));
13
+
14
+ var _getPresignedPostPayload = _interopRequireDefault(require("../utils/getPresignedPostPayload"));
15
+
16
+ var _uploadFileToS = _interopRequireDefault(require("../utils/uploadFileToS3"));
17
+
18
+ var _FilePhysicalStoragePlugin = require("@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin");
19
+
20
+ const _excluded = ["settings", "buffer"];
21
+ const S3_BUCKET = process.env.S3_BUCKET;
22
+
23
+ var _default = () => {
24
+ /**
25
+ * We need to extends the type for FilePhysicalStoragePlugin.
26
+ * Otherwise the getPresignedPostPayload does not know it has all required values in params.
27
+ */
28
+ return new _FilePhysicalStoragePlugin.FilePhysicalStoragePlugin({
29
+ upload: async params => {
30
+ const {
31
+ settings,
32
+ buffer
33
+ } = params,
34
+ data = (0, _objectWithoutProperties2.default)(params, _excluded);
35
+ const {
36
+ data: preSignedPostPayload,
37
+ file
38
+ } = await (0, _getPresignedPostPayload.default)(data, settings);
39
+ const response = await (0, _uploadFileToS.default)(buffer, preSignedPostPayload);
40
+
41
+ if (!response.ok) {
42
+ throw Error("Unable to upload file.");
43
+ }
44
+
45
+ return {
46
+ data: preSignedPostPayload,
47
+ file
48
+ };
49
+ },
50
+ delete: async params => {
51
+ const {
52
+ key
53
+ } = params;
54
+ const s3 = new _s.default();
55
+
56
+ if (!key || !S3_BUCKET) {
57
+ return;
58
+ }
59
+
60
+ await s3.deleteObject({
61
+ Bucket: S3_BUCKET,
62
+ Key: key
63
+ }).promise();
64
+ }
65
+ });
66
+ };
67
+
68
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["S3_BUCKET","process","env","FilePhysicalStoragePlugin","upload","params","settings","buffer","data","preSignedPostPayload","file","getPresignedPostPayload","response","uploadFileToS3","ok","Error","delete","key","s3","S3","deleteObject","Bucket","Key","promise"],"sources":["fileStorageS3.ts"],"sourcesContent":["import S3 from \"aws-sdk/clients/s3\";\nimport getPresignedPostPayload from \"../utils/getPresignedPostPayload\";\nimport uploadFileToS3 from \"../utils/uploadFileToS3\";\nimport {\n FilePhysicalStoragePlugin,\n FilePhysicalStoragePluginUploadParams\n} from \"@webiny/api-file-manager/plugins/definitions/FilePhysicalStoragePlugin\";\nimport { PresignedPostPayloadData } from \"~/types\";\n\nconst S3_BUCKET = process.env.S3_BUCKET;\n\nexport interface S3FilePhysicalStoragePluginUploadParams\n extends FilePhysicalStoragePluginUploadParams,\n PresignedPostPayloadData {}\n\nexport default (): FilePhysicalStoragePlugin => {\n /**\n * We need to extends the type for FilePhysicalStoragePlugin.\n * Otherwise the getPresignedPostPayload does not know it has all required values in params.\n */\n return new FilePhysicalStoragePlugin<S3FilePhysicalStoragePluginUploadParams>({\n upload: async params => {\n const { settings, buffer, ...data } = params;\n\n const { data: preSignedPostPayload, file } = await getPresignedPostPayload(\n data,\n settings\n );\n\n const response = await uploadFileToS3(buffer, preSignedPostPayload);\n if (!response.ok) {\n throw Error(\"Unable to upload file.\");\n }\n\n return {\n data: preSignedPostPayload,\n file\n };\n },\n delete: async params => {\n const { key } = params;\n const s3 = new S3();\n\n if (!key || !S3_BUCKET) {\n return;\n }\n\n await s3\n .deleteObject({\n Bucket: S3_BUCKET,\n Key: key\n })\n .promise();\n }\n });\n};\n"],"mappings":";;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;;AAMA,MAAMA,SAAS,GAAGC,OAAO,CAACC,GAAR,CAAYF,SAA9B;;eAMe,MAAiC;EAC5C;AACJ;AACA;AACA;EACI,OAAO,IAAIG,oDAAJ,CAAuE;IAC1EC,MAAM,EAAE,MAAMC,MAAN,IAAgB;MACpB,MAAM;QAAEC,QAAF;QAAYC;MAAZ,IAAgCF,MAAtC;MAAA,MAA6BG,IAA7B,0CAAsCH,MAAtC;MAEA,MAAM;QAAEG,IAAI,EAAEC,oBAAR;QAA8BC;MAA9B,IAAuC,MAAM,IAAAC,gCAAA,EAC/CH,IAD+C,EAE/CF,QAF+C,CAAnD;MAKA,MAAMM,QAAQ,GAAG,MAAM,IAAAC,sBAAA,EAAeN,MAAf,EAAuBE,oBAAvB,CAAvB;;MACA,IAAI,CAACG,QAAQ,CAACE,EAAd,EAAkB;QACd,MAAMC,KAAK,CAAC,wBAAD,CAAX;MACH;;MAED,OAAO;QACHP,IAAI,EAAEC,oBADH;QAEHC;MAFG,CAAP;IAIH,CAlByE;IAmB1EM,MAAM,EAAE,MAAMX,MAAN,IAAgB;MACpB,MAAM;QAAEY;MAAF,IAAUZ,MAAhB;MACA,MAAMa,EAAE,GAAG,IAAIC,UAAJ,EAAX;;MAEA,IAAI,CAACF,GAAD,IAAQ,CAACjB,SAAb,EAAwB;QACpB;MACH;;MAED,MAAMkB,EAAE,CACHE,YADC,CACY;QACVC,MAAM,EAAErB,SADE;QAEVsB,GAAG,EAAEL;MAFK,CADZ,EAKDM,OALC,EAAN;IAMH;EAjCyE,CAAvE,CAAP;AAmCH,C"}
@@ -0,0 +1,4 @@
1
+ import { GraphQLSchemaPlugin } from "@webiny/handler-graphql/types";
2
+ import { FileManagerContext } from "@webiny/api-file-manager/types";
3
+ declare const plugin: GraphQLSchemaPlugin<FileManagerContext>;
4
+ export default plugin;
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _responses = require("@webiny/handler-graphql/responses");
11
+
12
+ var _checkBasePermissions = _interopRequireDefault(require("@webiny/api-file-manager/plugins/crud/utils/checkBasePermissions"));
13
+
14
+ var _getPresignedPostPayload = _interopRequireDefault(require("../utils/getPresignedPostPayload"));
15
+
16
+ var _error = _interopRequireDefault(require("@webiny/error"));
17
+
18
+ const BATCH_UPLOAD_MAX_FILES = 20;
19
+ const plugin = {
20
+ type: "graphql-schema",
21
+ name: "graphql-schema-api-file-manager-s3",
22
+ schema: {
23
+ typeDefs:
24
+ /* GraphQL */
25
+ `
26
+ input PreSignedPostPayloadInput {
27
+ name: String!
28
+ type: String!
29
+ size: Int!
30
+ }
31
+
32
+ type GetPreSignedPostPayloadResponseDataFile {
33
+ name: String
34
+ type: String
35
+ size: Int
36
+ key: String
37
+ }
38
+
39
+ type GetPreSignedPostPayloadResponseData {
40
+ # Contains data that is necessary for initiating a file upload.
41
+ data: JSON
42
+ file: UploadFileResponseDataFile
43
+ }
44
+
45
+ type GetPreSignedPostPayloadResponse {
46
+ error: FileError
47
+ data: GetPreSignedPostPayloadResponseData
48
+ }
49
+
50
+ type GetPreSignedPostPayloadsResponse {
51
+ error: FileError
52
+ data: [GetPreSignedPostPayloadResponseData]!
53
+ }
54
+
55
+ extend type FmQuery {
56
+ getPreSignedPostPayload(
57
+ data: PreSignedPostPayloadInput!
58
+ ): GetPreSignedPostPayloadResponse
59
+ getPreSignedPostPayloads(
60
+ data: [PreSignedPostPayloadInput]!
61
+ ): GetPreSignedPostPayloadsResponse
62
+ }
63
+ `,
64
+ resolvers: {
65
+ FmQuery: {
66
+ getPreSignedPostPayload: async (_, args, context) => {
67
+ try {
68
+ await (0, _checkBasePermissions.default)(context, {
69
+ rwd: "w"
70
+ });
71
+ const {
72
+ data
73
+ } = args;
74
+ const settings = await context.fileManager.settings.getSettings();
75
+
76
+ if (!settings) {
77
+ throw new _error.default("Missing File Manager Settings.", "FILE_MANAGER_SETTINGS_ERROR", {
78
+ file: data
79
+ });
80
+ }
81
+
82
+ const response = await (0, _getPresignedPostPayload.default)(data, settings);
83
+ return new _responses.Response(response);
84
+ } catch (e) {
85
+ return new _responses.ErrorResponse({
86
+ message: e.message,
87
+ code: e.code,
88
+ data: e.data
89
+ });
90
+ }
91
+ },
92
+ getPreSignedPostPayloads: async (_, args, context) => {
93
+ await (0, _checkBasePermissions.default)(context, {
94
+ rwd: "w"
95
+ });
96
+ const {
97
+ data: files
98
+ } = args;
99
+
100
+ if (!Array.isArray(files)) {
101
+ return new _responses.ErrorResponse({
102
+ code: "UPLOAD_FILES_NON_ARRAY",
103
+ message: `"data" argument must be an array.`
104
+ });
105
+ }
106
+
107
+ if (files.length === 0) {
108
+ return new _responses.ErrorResponse({
109
+ code: "UPLOAD_FILES_MIN_FILES",
110
+ message: `"data" argument must contain at least one file.`
111
+ });
112
+ }
113
+
114
+ if (files.length > BATCH_UPLOAD_MAX_FILES) {
115
+ return new _responses.ErrorResponse({
116
+ code: "UPLOAD_FILES_MAX_FILES",
117
+ message: `"data" argument must not contain more than ${BATCH_UPLOAD_MAX_FILES} files.`
118
+ });
119
+ }
120
+
121
+ try {
122
+ const settings = await context.fileManager.settings.getSettings();
123
+
124
+ if (!settings) {
125
+ throw new _error.default("Missing File Manager Settings.", "FILE_MANAGER_SETTINGS_ERROR", {
126
+ files
127
+ });
128
+ }
129
+
130
+ const promises = [];
131
+
132
+ for (const item of files) {
133
+ promises.push((0, _getPresignedPostPayload.default)(item, settings));
134
+ }
135
+
136
+ return new _responses.Response(await Promise.all(promises));
137
+ } catch (e) {
138
+ return new _responses.ErrorResponse({
139
+ message: e.message,
140
+ code: e.code,
141
+ data: e.data
142
+ });
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ };
149
+ var _default = plugin;
150
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["BATCH_UPLOAD_MAX_FILES","plugin","type","name","schema","typeDefs","resolvers","FmQuery","getPreSignedPostPayload","_","args","context","checkBasePermissions","rwd","data","settings","fileManager","getSettings","WebinyError","file","response","getPresignedPostPayload","Response","e","ErrorResponse","message","code","getPreSignedPostPayloads","files","Array","isArray","length","promises","item","push","Promise","all"],"sources":["graphqlFileStorageS3.ts"],"sourcesContent":["import { GraphQLSchemaPlugin } from \"@webiny/handler-graphql/types\";\nimport { ErrorResponse, Response } from \"@webiny/handler-graphql/responses\";\nimport checkBasePermissions from \"@webiny/api-file-manager/plugins/crud/utils/checkBasePermissions\";\nimport { FileManagerContext } from \"@webiny/api-file-manager/types\";\nimport getPresignedPostPayload from \"../utils/getPresignedPostPayload\";\nimport WebinyError from \"@webiny/error\";\n\nconst BATCH_UPLOAD_MAX_FILES = 20;\n\nconst plugin: GraphQLSchemaPlugin<FileManagerContext> = {\n type: \"graphql-schema\",\n name: \"graphql-schema-api-file-manager-s3\",\n schema: {\n typeDefs: /* GraphQL */ `\n input PreSignedPostPayloadInput {\n name: String!\n type: String!\n size: Int!\n }\n\n type GetPreSignedPostPayloadResponseDataFile {\n name: String\n type: String\n size: Int\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: FileError\n data: GetPreSignedPostPayloadResponseData\n }\n\n type GetPreSignedPostPayloadsResponse {\n error: FileError\n data: [GetPreSignedPostPayloadResponseData]!\n }\n\n extend type FmQuery {\n getPreSignedPostPayload(\n data: PreSignedPostPayloadInput!\n ): GetPreSignedPostPayloadResponse\n getPreSignedPostPayloads(\n data: [PreSignedPostPayloadInput]!\n ): GetPreSignedPostPayloadsResponse\n }\n `,\n resolvers: {\n FmQuery: {\n getPreSignedPostPayload: async (_, args: any, context) => {\n try {\n await checkBasePermissions(context, { rwd: \"w\" });\n\n const { data } = args;\n const settings = await context.fileManager.settings.getSettings();\n if (!settings) {\n throw new WebinyError(\n \"Missing File Manager Settings.\",\n \"FILE_MANAGER_SETTINGS_ERROR\",\n {\n file: data\n }\n );\n }\n const response = await getPresignedPostPayload(data, settings);\n\n return new Response(response);\n } catch (e) {\n return new ErrorResponse({\n message: e.message,\n code: e.code,\n data: e.data\n });\n }\n },\n getPreSignedPostPayloads: async (_, args: any, context) => {\n await checkBasePermissions(context, { rwd: \"w\" });\n\n const { data: files } = args;\n if (!Array.isArray(files)) {\n return new ErrorResponse({\n code: \"UPLOAD_FILES_NON_ARRAY\",\n message: `\"data\" argument must be an array.`\n });\n }\n\n if (files.length === 0) {\n return new ErrorResponse({\n code: \"UPLOAD_FILES_MIN_FILES\",\n message: `\"data\" argument must contain at least one file.`\n });\n }\n\n if (files.length > BATCH_UPLOAD_MAX_FILES) {\n return new ErrorResponse({\n code: \"UPLOAD_FILES_MAX_FILES\",\n message: `\"data\" argument must not contain more than ${BATCH_UPLOAD_MAX_FILES} files.`\n });\n }\n\n try {\n const settings = await context.fileManager.settings.getSettings();\n if (!settings) {\n throw new WebinyError(\n \"Missing File Manager Settings.\",\n \"FILE_MANAGER_SETTINGS_ERROR\",\n {\n files\n }\n );\n }\n\n const promises = [];\n for (const item of files) {\n promises.push(getPresignedPostPayload(item, settings));\n }\n\n return new Response(await Promise.all(promises));\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};\n\nexport default plugin;\n"],"mappings":"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"}
package/types.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import S3 from "aws-sdk/clients/s3";
2
+ export interface PresignedPostPayloadData {
3
+ name: string;
4
+ type: string;
5
+ size: number;
6
+ keyPrefix: string;
7
+ }
8
+ export interface PresignedPostPayloadDataResponse {
9
+ data: S3.PresignedPost;
10
+ file: {
11
+ name: string;
12
+ key: string;
13
+ type: string;
14
+ size: number;
15
+ };
16
+ }
package/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
package/types.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import S3 from \"aws-sdk/clients/s3\";\n\nexport interface PresignedPostPayloadData {\n name: string;\n type: string;\n size: number;\n keyPrefix: string;\n}\n\nexport interface PresignedPostPayloadDataResponse {\n data: S3.PresignedPost;\n file: {\n name: string;\n key: string;\n type: string;\n size: number;\n };\n}\n"],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { PresignedPostPayloadData, PresignedPostPayloadDataResponse } from "../types";
2
+ import { FileManagerSettings } from "@webiny/api-file-manager/types";
3
+ declare const _default: (data: PresignedPostPayloadData, settings: FileManagerSettings) => Promise<PresignedPostPayloadDataResponse>;
4
+ export default _default;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _uniqid = _interopRequireDefault(require("uniqid"));
11
+
12
+ var _sanitizeFilename = _interopRequireDefault(require("sanitize-filename"));
13
+
14
+ var _s = _interopRequireDefault(require("aws-sdk/clients/s3"));
15
+
16
+ var _validation = require("@webiny/validation");
17
+
18
+ const S3_BUCKET = process.env.S3_BUCKET;
19
+ const UPLOAD_MAX_FILE_SIZE_DEFAULT = 26214400; // 25MB
20
+
21
+ const sanitizeFileSizeValue = (value, defaultValue) => {
22
+ try {
23
+ _validation.validation.validateSync(value, "required,numeric,gte:0");
24
+
25
+ return value;
26
+ } catch (e) {
27
+ // TODO @ts-refactor No need to log the error?
28
+ return defaultValue;
29
+ }
30
+ };
31
+
32
+ var _default = async (data, settings) => {
33
+ // If type is missing, let's use the default "application/octet-stream" type,
34
+ // which is also the default type that the Amazon S3 would use.
35
+ if (!data.type) {
36
+ data.type = "application/octet-stream";
37
+ }
38
+
39
+ const contentType = data.type;
40
+
41
+ if (!contentType) {
42
+ throw Error(`File's content type could not be resolved.`);
43
+ }
44
+
45
+ let key = (0, _sanitizeFilename.default)(data.name);
46
+
47
+ if (key) {
48
+ key = (0, _uniqid.default)() + "-" + key;
49
+ }
50
+
51
+ if (data.keyPrefix) {
52
+ key = `${(0, _sanitizeFilename.default)(data.keyPrefix)}-${key}`;
53
+ } // Replace all whitespace.
54
+
55
+
56
+ key = key.replace(/\s/g, "");
57
+ const uploadMinFileSize = sanitizeFileSizeValue(settings.uploadMinFileSize, 0);
58
+ const uploadMaxFileSize = sanitizeFileSizeValue(settings.uploadMaxFileSize, UPLOAD_MAX_FILE_SIZE_DEFAULT);
59
+ const params = {
60
+ Expires: 60,
61
+ Bucket: S3_BUCKET,
62
+ Conditions: [["content-length-range", uploadMinFileSize, uploadMaxFileSize]],
63
+ // 0 Bytes - 25MB
64
+ Fields: {
65
+ "Content-Type": contentType,
66
+ key
67
+ }
68
+ };
69
+
70
+ if (params.Fields.key.startsWith("/")) {
71
+ params.Fields.key = params.Fields.key.slice(1);
72
+ }
73
+
74
+ const s3 = new _s.default();
75
+ const payload = s3.createPresignedPost(params);
76
+ return {
77
+ data: payload,
78
+ file: {
79
+ name: key,
80
+ key,
81
+ type: contentType,
82
+ size: data.size
83
+ }
84
+ };
85
+ };
86
+
87
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["S3_BUCKET","process","env","UPLOAD_MAX_FILE_SIZE_DEFAULT","sanitizeFileSizeValue","value","defaultValue","validation","validateSync","e","data","settings","type","contentType","Error","key","sanitizeFilename","name","uniqueId","keyPrefix","replace","uploadMinFileSize","uploadMaxFileSize","params","Expires","Bucket","Conditions","Fields","startsWith","slice","s3","S3","payload","createPresignedPost","file","size"],"sources":["getPresignedPostPayload.ts"],"sourcesContent":["import uniqueId from \"uniqid\";\nimport sanitizeFilename from \"sanitize-filename\";\nimport S3 from \"aws-sdk/clients/s3\";\nimport { validation } from \"@webiny/validation\";\nimport { PresignedPostPayloadData, PresignedPostPayloadDataResponse } from \"~/types\";\nimport { FileManagerSettings } from \"@webiny/api-file-manager/types\";\n\nconst S3_BUCKET = process.env.S3_BUCKET;\nconst UPLOAD_MAX_FILE_SIZE_DEFAULT = 26214400; // 25MB\n\nconst sanitizeFileSizeValue = (value: number, defaultValue: number): number => {\n try {\n validation.validateSync(value, \"required,numeric,gte:0\");\n return value;\n } catch (e) {\n // TODO @ts-refactor No need to log the error?\n return defaultValue;\n }\n};\n\nexport default async (\n data: PresignedPostPayloadData,\n settings: FileManagerSettings\n): Promise<PresignedPostPayloadDataResponse> => {\n // If type is missing, let's use the default \"application/octet-stream\" type,\n // which is also the default type that the Amazon S3 would use.\n if (!data.type) {\n data.type = \"application/octet-stream\";\n }\n\n const contentType = data.type;\n if (!contentType) {\n throw Error(`File's content type could not be resolved.`);\n }\n\n let key = sanitizeFilename(data.name);\n if (key) {\n key = uniqueId() + \"-\" + key;\n }\n\n if (data.keyPrefix) {\n key = `${sanitizeFilename(data.keyPrefix)}-${key}`;\n }\n\n // Replace all whitespace.\n key = key.replace(/\\s/g, \"\");\n\n const uploadMinFileSize = sanitizeFileSizeValue(settings.uploadMinFileSize, 0);\n const uploadMaxFileSize = sanitizeFileSizeValue(\n settings.uploadMaxFileSize,\n UPLOAD_MAX_FILE_SIZE_DEFAULT\n );\n\n const params = {\n Expires: 60,\n Bucket: S3_BUCKET,\n Conditions: [[\"content-length-range\", uploadMinFileSize, uploadMaxFileSize]], // 0 Bytes - 25MB\n Fields: {\n \"Content-Type\": contentType,\n key\n }\n };\n\n if (params.Fields.key.startsWith(\"/\")) {\n params.Fields.key = params.Fields.key.slice(1);\n }\n\n const s3 = new S3();\n const payload = s3.createPresignedPost(params);\n\n return {\n data: payload,\n file: {\n name: key,\n key,\n type: contentType,\n size: data.size\n }\n };\n};\n"],"mappings":";;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AAIA,MAAMA,SAAS,GAAGC,OAAO,CAACC,GAAR,CAAYF,SAA9B;AACA,MAAMG,4BAA4B,GAAG,QAArC,C,CAA+C;;AAE/C,MAAMC,qBAAqB,GAAG,CAACC,KAAD,EAAgBC,YAAhB,KAAiD;EAC3E,IAAI;IACAC,sBAAA,CAAWC,YAAX,CAAwBH,KAAxB,EAA+B,wBAA/B;;IACA,OAAOA,KAAP;EACH,CAHD,CAGE,OAAOI,CAAP,EAAU;IACR;IACA,OAAOH,YAAP;EACH;AACJ,CARD;;eAUe,OACXI,IADW,EAEXC,QAFW,KAGiC;EAC5C;EACA;EACA,IAAI,CAACD,IAAI,CAACE,IAAV,EAAgB;IACZF,IAAI,CAACE,IAAL,GAAY,0BAAZ;EACH;;EAED,MAAMC,WAAW,GAAGH,IAAI,CAACE,IAAzB;;EACA,IAAI,CAACC,WAAL,EAAkB;IACd,MAAMC,KAAK,CAAE,4CAAF,CAAX;EACH;;EAED,IAAIC,GAAG,GAAG,IAAAC,yBAAA,EAAiBN,IAAI,CAACO,IAAtB,CAAV;;EACA,IAAIF,GAAJ,EAAS;IACLA,GAAG,GAAG,IAAAG,eAAA,MAAa,GAAb,GAAmBH,GAAzB;EACH;;EAED,IAAIL,IAAI,CAACS,SAAT,EAAoB;IAChBJ,GAAG,GAAI,GAAE,IAAAC,yBAAA,EAAiBN,IAAI,CAACS,SAAtB,CAAiC,IAAGJ,GAAI,EAAjD;EACH,CAnB2C,CAqB5C;;;EACAA,GAAG,GAAGA,GAAG,CAACK,OAAJ,CAAY,KAAZ,EAAmB,EAAnB,CAAN;EAEA,MAAMC,iBAAiB,GAAGjB,qBAAqB,CAACO,QAAQ,CAACU,iBAAV,EAA6B,CAA7B,CAA/C;EACA,MAAMC,iBAAiB,GAAGlB,qBAAqB,CAC3CO,QAAQ,CAACW,iBADkC,EAE3CnB,4BAF2C,CAA/C;EAKA,MAAMoB,MAAM,GAAG;IACXC,OAAO,EAAE,EADE;IAEXC,MAAM,EAAEzB,SAFG;IAGX0B,UAAU,EAAE,CAAC,CAAC,sBAAD,EAAyBL,iBAAzB,EAA4CC,iBAA5C,CAAD,CAHD;IAGmE;IAC9EK,MAAM,EAAE;MACJ,gBAAgBd,WADZ;MAEJE;IAFI;EAJG,CAAf;;EAUA,IAAIQ,MAAM,CAACI,MAAP,CAAcZ,GAAd,CAAkBa,UAAlB,CAA6B,GAA7B,CAAJ,EAAuC;IACnCL,MAAM,CAACI,MAAP,CAAcZ,GAAd,GAAoBQ,MAAM,CAACI,MAAP,CAAcZ,GAAd,CAAkBc,KAAlB,CAAwB,CAAxB,CAApB;EACH;;EAED,MAAMC,EAAE,GAAG,IAAIC,UAAJ,EAAX;EACA,MAAMC,OAAO,GAAGF,EAAE,CAACG,mBAAH,CAAuBV,MAAvB,CAAhB;EAEA,OAAO;IACHb,IAAI,EAAEsB,OADH;IAEHE,IAAI,EAAE;MACFjB,IAAI,EAAEF,GADJ;MAEFA,GAFE;MAGFH,IAAI,EAAEC,WAHJ;MAIFsB,IAAI,EAAEzB,IAAI,CAACyB;IAJT;EAFH,CAAP;AASH,C"}
@@ -0,0 +1,5 @@
1
+ /// <reference types="node" />
2
+ import { Response } from "node-fetch";
3
+ import S3 from "aws-sdk/clients/s3";
4
+ declare const _default: (buffer: Buffer, preSignedPostPayload: S3.PresignedPost) => Promise<Response>;
5
+ export default _default;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _formData = _interopRequireDefault(require("form-data"));
11
+
12
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
13
+
14
+ var _default = async (buffer, preSignedPostPayload) => {
15
+ const formData = new _formData.default(); // Add all pre signed payload field to "FormData".
16
+
17
+ Object.keys(preSignedPostPayload.fields).forEach(key => {
18
+ formData.append(key, preSignedPostPayload.fields[key]);
19
+ }); // Add file content to "FormData".
20
+
21
+ formData.append("file", buffer); // Finally make the upload request to S3.
22
+
23
+ return (0, _nodeFetch.default)(preSignedPostPayload.url, {
24
+ method: "POST",
25
+ body: formData
26
+ });
27
+ };
28
+
29
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["buffer","preSignedPostPayload","formData","FormData","Object","keys","fields","forEach","key","append","fetch","url","method","body"],"sources":["uploadFileToS3.ts"],"sourcesContent":["import FormData from \"form-data\";\nimport fetch, { Response } from \"node-fetch\";\nimport S3 from \"aws-sdk/clients/s3\";\n\nexport default async (\n buffer: Buffer,\n preSignedPostPayload: S3.PresignedPost\n): Promise<Response> => {\n const formData = new FormData();\n // Add all pre signed payload field to \"FormData\".\n Object.keys(preSignedPostPayload.fields).forEach(key => {\n formData.append(key, preSignedPostPayload.fields[key]);\n });\n // Add file content to \"FormData\".\n formData.append(\"file\", buffer);\n // Finally make the upload request to S3.\n return fetch(preSignedPostPayload.url, {\n method: \"POST\",\n body: formData\n });\n};\n"],"mappings":";;;;;;;;;AAAA;;AACA;;eAGe,OACXA,MADW,EAEXC,oBAFW,KAGS;EACpB,MAAMC,QAAQ,GAAG,IAAIC,iBAAJ,EAAjB,CADoB,CAEpB;;EACAC,MAAM,CAACC,IAAP,CAAYJ,oBAAoB,CAACK,MAAjC,EAAyCC,OAAzC,CAAiDC,GAAG,IAAI;IACpDN,QAAQ,CAACO,MAAT,CAAgBD,GAAhB,EAAqBP,oBAAoB,CAACK,MAArB,CAA4BE,GAA5B,CAArB;EACH,CAFD,EAHoB,CAMpB;;EACAN,QAAQ,CAACO,MAAT,CAAgB,MAAhB,EAAwBT,MAAxB,EAPoB,CAQpB;;EACA,OAAO,IAAAU,kBAAA,EAAMT,oBAAoB,CAACU,GAA3B,EAAgC;IACnCC,MAAM,EAAE,MAD2B;IAEnCC,IAAI,EAAEX;EAF6B,CAAhC,CAAP;AAIH,C"}