diff --git a/package-lock.json b/package-lock.json index c54c50b2..70556acf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -995,11 +995,11 @@ } }, "@nestjs/common": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-7.6.3.tgz", - "integrity": "sha512-y6aOMZfWSBnAPi2g/UuhK0IIGNafIvgxAmOVjw9punui1mFpkBe0c0hkEnUOG3iDEVncqooqEgln48D160JA5g==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-7.6.5.tgz", + "integrity": "sha512-WvBJd71ktaCRm9KTURVqn1YMyUzsOIkvezjP7WEpP9DVqQUOFVvn6/osJGZky/qL+zE4P7NBNyoXM94bpYvMwQ==", "requires": { - "axios": "0.21.0", + "axios": "0.21.1", "iterare": "1.2.1", "tslib": "2.0.3", "uuid": "8.3.2" @@ -1281,6 +1281,12 @@ "@types/node": "*" } }, + "@types/cache-manager": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-2.10.3.tgz", + "integrity": "sha512-PbaxAeU8SZhbVd6+IuepvyWN7KAjEThsrkdvITDxKAlN6/abIr3NW3WPzNLjJekqbVijg4YUYsyrVc84xXUHQw==", + "dev": true + }, "@types/connect": { "version": "3.4.34", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", @@ -2149,6 +2155,11 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -2184,9 +2195,9 @@ "dev": true }, "axios": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", - "integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { "follow-redirects": "^1.10.0" } @@ -2518,6 +2529,16 @@ "unset-value": "^1.0.0" } }, + "cache-manager": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-3.4.0.tgz", + "integrity": "sha512-+WtL5sKHGngtnzTHNFA6+gC0wjpAAUmwmprXOSeaCBOkohM8Nh7GvV8fC90NFrDh7m3i87AshGd39/yYbWNtWA==", + "requires": { + "async": "^3.2.0", + "lodash": "^4.17.20", + "lru-cache": "6.0.0" + } + }, "call-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", @@ -6663,7 +6684,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -10064,8 +10084,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.0", diff --git a/package.json b/package.json index a08512c8..099ffdff 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@nestjs/common": "^7.4.2", + "@nestjs/common": "^7.6.5", "@nestjs/config": "^0.5.0", "@nestjs/core": "^7.4.2", "@nestjs/jwt": "^7.1.0", @@ -32,6 +32,7 @@ "@nestjs/websockets": "^7.4.2", "@prisma/client": "2.12.1", "bcryptjs": "^2.4.3", + "cache-manager": "^3.4.0", "class-transformer": "^0.3.1", "class-validator": "^0.12.2", "fs-extra": "^9.0.1", @@ -54,6 +55,7 @@ "@nestjs/testing": "^7.4.2", "@prisma/cli": "2.12.1", "@types/bcryptjs": "^2.4.2", + "@types/cache-manager": "^2.10.3", "@types/express": "^4.17.7", "@types/jest": "26.0.14", "@types/node": "^14.0.27", diff --git a/src/app.module.ts b/src/app.module.ts index 94e90b21..fda65c63 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { CacheInterceptor, CacheModule, Module } from '@nestjs/common'; import { AuthModule } from './auth/auth.module'; import { UsersModule } from './users/users.module'; import { BuildsModule } from './builds/builds.module'; @@ -7,12 +7,13 @@ import { TestRunsModule } from './test-runs/test-runs.module'; import { TestVariationsModule } from './test-variations/test-variations.module'; import { PrismaService } from './prisma/prisma.service'; import { ConfigModule } from '@nestjs/config'; -import { APP_FILTER } from '@nestjs/core'; +import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core'; import { HttpExceptionFilter } from './http-exception.filter'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), + CacheModule.register(), AuthModule, UsersModule, BuildsModule, @@ -26,6 +27,10 @@ import { HttpExceptionFilter } from './http-exception.filter'; provide: APP_FILTER, useClass: HttpExceptionFilter, }, + { + provide: APP_INTERCEPTOR, + useClass: CacheInterceptor, + }, ], }) export class AppModule {} diff --git a/src/main.ts b/src/main.ts index cceb8a83..25a6489b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,8 @@ import { join } from 'path'; import * as bodyParser from 'body-parser'; import { readFileSync, existsSync } from 'fs'; import { HttpsOptions } from '@nestjs/common/interfaces/external/https-options.interface'; +import { IMAGE_PATH } from './shared/static/static.service'; +import { NestExpressApplication } from '@nestjs/platform-express'; function getHttpsOptions(): HttpsOptions | null { const keyPath = './secrets/ssl.key'; @@ -22,7 +24,7 @@ function getHttpsOptions(): HttpsOptions | null { } async function bootstrap() { - const app = await NestFactory.create(AppModule, { + const app = await NestFactory.create(AppModule, { cors: true, httpsOptions: getHttpsOptions(), }); @@ -34,7 +36,9 @@ async function bootstrap() { } // serve images - app.use(express.static(join(process.cwd(), 'imageUploads/'))); + app.useStaticAssets(join(process.cwd(), IMAGE_PATH), { + maxAge: 31536000 + }); await app.listen(process.env.APP_PORT || 3000); } diff --git a/src/shared/static/static.service.ts b/src/shared/static/static.service.ts index 33daed8f..221c82f5 100644 --- a/src/shared/static/static.service.ts +++ b/src/shared/static/static.service.ts @@ -3,6 +3,8 @@ import path from 'path'; import { writeFileSync, readFileSync, unlink, mkdirSync, existsSync } from 'fs'; import { PNG, PNGWithMetadata } from 'pngjs'; +export const IMAGE_PATH = 'imageUploads/' + @Injectable() export class StaticService { saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): string { @@ -35,9 +37,8 @@ export class StaticService { } private getImagePath(imageName: string): string { - const dir = 'imageUploads/'; - this.ensureDirectoryExistence(dir); - return path.resolve(dir, imageName); + this.ensureDirectoryExistence(IMAGE_PATH); + return path.resolve(IMAGE_PATH, imageName); } private ensureDirectoryExistence(dir: string) {