diff --git a/package-lock.json b/package-lock.json index 04a0dcf5..90543b3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "sharp": "^0.32.6" }, "devDependencies": { - "@myrotvorets/eslint-config-myrotvorets-ts": "^2.21.0", + "@myrotvorets/eslint-config-myrotvorets-ts": "^2.22.4", "@types/chai": "^4.3.7", "@types/chai-as-promised": "^7.1.6", "@types/chai-subset": "^1.3.3", @@ -311,9 +311,9 @@ } }, "node_modules/@myrotvorets/eslint-config-myrotvorets-ts": { - "version": "2.21.0", - "resolved": "https://npm.pkg.github.com/download/@myrotvorets/eslint-config-myrotvorets-ts/2.21.0/8e57d162bb4245292092bb381e362d1f6fe97da5", - "integrity": "sha512-UNvOj3RbDivCSeeGgJ+l+3E92b0Y8nxfVEK0BUUd55AVpU/LpzgVNo8Ct0f2r5ATPeWt2dAnEpl9iI+8Rv8w4w==", + "version": "2.22.4", + "resolved": "https://npm.pkg.github.com/download/@myrotvorets/eslint-config-myrotvorets-ts/2.22.4/b27eaeb773c75d3b03ad794e3c1634dbfe9d6bf9", + "integrity": "sha512-ZQGyLWRvET3jXZfZZOu9VJL16IuIxroCmwRMfCF87ueHXRz7wiNTiDmYkP+lNSQqWb6LX31HbZVUBDpoVHGPzA==", "dev": true, "license": "MIT", "dependencies": { @@ -433,22 +433,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@myrotvorets/opentelemetry-configurator/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@myrotvorets/opentelemetry-resource-detectors": { "version": "1.0.1", "resolved": "https://npm.pkg.github.com/download/@myrotvorets/opentelemetry-resource-detectors/1.0.1/d3762f6c2898247d97b49a28b09b34fbe7a64610", @@ -570,22 +554,6 @@ "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@opentelemetry/exporter-logs-otlp-http": { "version": "0.43.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.43.0.tgz", @@ -615,22 +583,6 @@ "node": ">=14" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@opentelemetry/exporter-logs-otlp-proto": { "version": "0.43.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.43.0.tgz", @@ -663,22 +615,6 @@ "node": ">=14" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { "version": "0.43.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.43.0.tgz", @@ -983,22 +919,6 @@ "node": ">=14" } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@opentelemetry/propagator-b3": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.17.0.tgz", @@ -1042,6 +962,22 @@ "@opentelemetry/api": ">=1.0.0 <1.7.0" } }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", + "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", + "dependencies": { + "@opentelemetry/core": "1.17.0", + "@opentelemetry/resources": "1.17.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.7.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, "node_modules/@opentelemetry/sdk-metrics": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.17.0.tgz", @@ -1115,22 +1051,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-logs": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.43.0.tgz", - "integrity": "sha512-JyJ2BBRKm37Mc4cSEhFmsMl5ASQn1dkGhEWzAAMSlhPtLRTv5PfvJwhR+Mboaic/eDLAlciwsgijq8IFlf6IgQ==", - "dependencies": { - "@opentelemetry/core": "1.17.0", - "@opentelemetry/resources": "1.17.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.7.0", - "@opentelemetry/api-logs": ">=0.39.1" - } - }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.17.0.tgz", diff --git a/package.json b/package.json index 3fa314fa..82b37cd4 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "sharp": "^0.32.6" }, "devDependencies": { - "@myrotvorets/eslint-config-myrotvorets-ts": "^2.21.0", + "@myrotvorets/eslint-config-myrotvorets-ts": "^2.22.4", "@types/chai": "^4.3.7", "@types/chai-as-promised": "^7.1.6", "@types/chai-subset": "^1.3.3", diff --git a/src/controllers/upload.mts b/src/controllers/upload.mts index 47a56522..4e3dfd80 100644 --- a/src/controllers/upload.mts +++ b/src/controllers/upload.mts @@ -26,7 +26,7 @@ async function searchUploadHandler( res: Response, next: NextFunction, ): Promise { - const file = (req.files as Express.Multer.File[])[0]; + const file = (req.files as Express.Multer.File[])[0]!; const { guid } = req.params; await UploadService.uploadFile(file, guid); diff --git a/src/server.mts b/src/server.mts index 6f0ff5f3..6bd832c8 100644 --- a/src/server.mts +++ b/src/server.mts @@ -1,6 +1,6 @@ import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; -import express, { type Express, json, static as staticMiddleware } from 'express'; +import express, { type Express, json } from 'express'; import { installOpenApiValidator } from '@myrotvorets/oav-installer'; import { errorMiddleware, notFoundMiddleware } from '@myrotvorets/express-microservice-middlewares'; import { cleanUploadedFilesMiddleware } from '@myrotvorets/clean-up-after-multer'; @@ -18,22 +18,6 @@ import { uploadErrorHandlerMiddleware } from './middleware/upload.mjs'; export async function configureApp(app: express.Express): Promise { const env = environment(); - /* c8 ignore start */ - if (env.NODE_ENV !== 'production') { - app.use( - '/specs/', - staticMiddleware(join(dirname(fileURLToPath(import.meta.url)), 'specs'), { - acceptRanges: false, - index: false, - }), - ); - - if (process.env.HAVE_SWAGGER === 'true') { - app.get('/', (_req, res) => res.redirect('/swagger/')); - } - } - /* c8 ignore end */ - app.use(json()); await installOpenApiValidator( diff --git a/src/services/upload.mts b/src/services/upload.mts index c4aac016..ee1ca90c 100644 --- a/src/services/upload.mts +++ b/src/services/upload.mts @@ -1,16 +1,22 @@ import { mkdir } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; import { join, sep } from 'node:path'; import sharp from 'sharp'; +type UploadedFileInternal = + | (Pick & { buffer: undefined }) + | (Pick & { path: undefined; destination: undefined }); + +type UploadedFile = Pick; + +// eslint-disable-next-line @typescript-eslint/no-extraneous-class export class UploadService { - public static async uploadFile( - file: Pick, - guid: string, - ): Promise { - const img = await UploadService.prepareFile(file.path ?? file.buffer); // memoryStorage() returns Buffer + public static async uploadFile(file: UploadedFile, guid: string): Promise { + const f = file as unknown as UploadedFileInternal; + const img = await UploadService.prepareFile(f.path ?? f.buffer); // memoryStorage() returns Buffer const hashedPath = UploadService.hashFileName(guid); const filename = `${guid}.jpg`; - const destPath = join(file.destination ?? '', hashedPath); // No file.destination for memoryStorage() + const destPath = join(f.destination ?? tmpdir(), hashedPath); // No file.destination for memoryStorage() const destJpeg = join(destPath, filename); await mkdir(destPath, { recursive: true, mode: 0o755 }); diff --git a/tsconfig.json b/tsconfig.json index 58952e07..9b07b5a0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,10 @@ "noUnusedLocals": true, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noImplicitReturns": true, "esModuleInterop": true, "resolveJsonModule": true },