diff --git a/package-lock.json b/package-lock.json index 06b9b20be..b97e255a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@sentry/nextjs": "7.60.0", "@tanstack/react-query": "4.29.5", "@tanstack/react-query-devtools": "4.29.5", - "@taskany/bricks": "1.28.0", + "@taskany/bricks": "1.29.0", "@taskany/colors": "1.1.0", "@taskany/icons": "1.0.0", "@tippyjs/react": "4.2.6", @@ -6036,9 +6036,9 @@ } }, "node_modules/@taskany/bricks": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@taskany/bricks/-/bricks-1.28.0.tgz", - "integrity": "sha512-KmrHora/Qzl2UyuPv+gDzJDYtgJE7grtkz71cB7zZmZ7a8wgXGovVhOglf44GQeFRHE2isDh2PkhBX5S+6P0aQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@taskany/bricks/-/bricks-1.29.0.tgz", + "integrity": "sha512-w6PwjCNOHfu1G1ioVG25um5aGX8EHCQsaJy+G+erDJg/X3BQyKSEdgetwLpMmtRgmj+burd6iwgjESNfOwNDJw==", "dependencies": { "@monaco-editor/react": "4.5.1", "@taskany/colors": "1.1.0", @@ -23225,9 +23225,9 @@ } }, "@taskany/bricks": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@taskany/bricks/-/bricks-1.28.0.tgz", - "integrity": "sha512-KmrHora/Qzl2UyuPv+gDzJDYtgJE7grtkz71cB7zZmZ7a8wgXGovVhOglf44GQeFRHE2isDh2PkhBX5S+6P0aQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@taskany/bricks/-/bricks-1.29.0.tgz", + "integrity": "sha512-w6PwjCNOHfu1G1ioVG25um5aGX8EHCQsaJy+G+erDJg/X3BQyKSEdgetwLpMmtRgmj+burd6iwgjESNfOwNDJw==", "requires": { "@monaco-editor/react": "4.5.1", "@taskany/colors": "1.1.0", diff --git a/package.json b/package.json index f71431965..271452140 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@sentry/nextjs": "7.60.0", "@tanstack/react-query": "4.29.5", "@tanstack/react-query-devtools": "4.29.5", - "@taskany/bricks": "1.28.0", + "@taskany/bricks": "1.29.0", "@taskany/colors": "1.1.0", "@taskany/icons": "1.0.0", "@tippyjs/react": "4.2.6", diff --git a/src/pages/api/upload.ts b/src/pages/api/upload.ts index 302caffad..cc5753d43 100644 --- a/src/pages/api/upload.ts +++ b/src/pages/api/upload.ts @@ -1,4 +1,5 @@ /* eslint-disable no-underscore-dangle */ +/* eslint-disable no-await-in-loop */ import nextConnect from 'next-connect'; import crypto from 'crypto'; import multer from 'multer'; @@ -23,6 +24,12 @@ const cors = Cors({ methods: ['HEAD', 'OPTIONS', 'POST'], }); +type ResponseObj = { + failed: string[]; + succeeded: string[]; + errorMessage?: string; +}; + const upload = multer({ storage: multer.memoryStorage() }); const route = nextConnect({ @@ -55,43 +62,48 @@ route.post(upload.array(formFieldName, 10), async (req: any, res: NextApiRespons region: process.env.S3_REGION, }); } - - const result = await Promise.all( - req[formFieldName].map( - async ({ originalname, mimetype, buffer }: { originalname: string; mimetype: string; buffer: Buffer }) => { - // @ts-ignore Translit is any ¯\_(ツ)_/¯ - let fileName = new Translit({ preset: 'ru' }).transform(originalname, '_'); - - if (JSON.parse(uniqueNames)) { - const hashSum = crypto.createHash('sha256'); - hashSum.update(buffer); - const hex = hashSum.digest('hex'); - - fileName = `${hex.slice(0, 8)}_${fileName}`; - } - - if (!s3Client) { - return saveFileInPublic(fileName, buffer); - } - - return Promise.resolve( - s3Client.send( - new PutObjectCommand({ - Bucket: process.env.S3_BUCKET, - BucketKeyEnabled: false, - Key: `${folder}/${fileName}`, - Body: buffer, - ACL: 'authenticated-read', - CacheControl: 'max-age=630720000, public', - ContentType: mimetype, - }), - ), - ).then(() => `${process.env.PUBLIC_URL}/static/${folder}/${fileName}`); - }, - ), - ); - - res.status(200).json(result); + const resultObject: ResponseObj = { + failed: [], + succeeded: [], + }; + + for (const file of req[formFieldName]) { + const { originalname, mimetype, buffer } = file; + // @ts-ignore Translit is any ¯\_(ツ)_/¯ + let fileName = new Translit({ preset: 'ru' }).transform(originalname, '_'); + + if (JSON.parse(uniqueNames)) { + const hashSum = crypto.createHash('sha256'); + hashSum.update(buffer); + const hex = hashSum.digest('hex'); + + fileName = `${hex.slice(0, 8)}_${fileName}`; + } + + if (!s3Client) { + const filePath = await saveFileInPublic(fileName, buffer); + resultObject.succeeded.push(filePath); + } else { + await s3Client + .send( + new PutObjectCommand({ + Bucket: process.env.S3_BUCKET, + BucketKeyEnabled: false, + Key: `${folder}/${fileName}`, + Body: buffer, + ACL: 'authenticated-read', + CacheControl: 'max-age=630720000, public', + ContentType: mimetype, + }), + ) + .then(() => resultObject.succeeded.push(`${process.env.PUBLIC_URL}/static/${folder}/${fileName}`)) + .catch((error) => { + resultObject.failed.push(originalname); + resultObject.errorMessage = error.message; + }); + } + } + res.status(200).json(resultObject); }); export default route;