So basicly i’m trying to deploy a nestjs app and even if tweek the vercel.json file so that the deployment at least succeeds, when i try to access a swagger or any other route it gives me a 404 error. (Obs: AT DEV ENV EVERYTHING WORKS FINE)
vercel.json:
{
"version": 2,
"buildCommand": "npm run build",
"devCommand": "npm run start:dev",
"installCommand": "npm install --legacy-peer-deps",
"outputDirectory": "dist"
}
package.json
{
"name": "commerce-blog.api",
"version": "0.0.1",
"description": "",
"author": "Gustavo Augusto",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "node dist/main.js",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
"typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
"migration:run": "npm run typeorm -- -d src/lib/database/database.providers.ts migration:run",
"seed:run": "ts-node -r tsconfig-paths/register ./node_modules/typeorm-extension/bin/cli.cjs seed:run -d src/lib/database/database.providers.ts",
"seed:create": "ts-node ./node_modules/typeorm-extension/bin/cli.cjs seed:create"
},
"dependencies": {
"@nestjs/bull": "^10.2.2",
"@nestjs/common": "^10.4.6",
"@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.4.6",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.4.6",
"@nestjs/platform-socket.io": "^10.4.6",
"@nestjs/schedule": "^4.1.1",
"@nestjs/swagger": "^8.0.1",
"@nestjs/terminus": "^10.2.3",
"@nestjs/typeorm": "^10.0.2",
"@nestjs/websockets": "^10.4.6",
"@socket.io/redis-adapter": "^8.3.0",
"bcrypt": "^5.1.1",
"bull": "^4.16.3",
"cron": "^3.1.8",
"dotenv": "^16.4.5",
"nestjs-typeorm-paginate": "^4.0.4",
"nestjs-zod": "^4.1.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.13.1",
"redis": "^4.7.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"socket.io": "^4.8.1",
"typeorm": "^0.3.20",
"typeorm-extension": "^3.6.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@jest/types": "^29.6.3",
"@nestjs/cli": "^10.4.5",
"@nestjs/schematics": "^10.2.3",
"@nestjs/testing": "^10.4.6",
"@types/bcrypt": "^5.0.2",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.8.4",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.2",
"@typescript-eslint/eslint-plugin": "^8.12.2",
"@typescript-eslint/parser": "^8.12.2",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"source-map-support": "^0.5.21",
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.6.3"
}
}
main.ts
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { corsConfig } from './config/cors.config';
import { ENV_VARIABLES, IS_DEV_ENV } from './config/env.config';
import { DataBaseInterceptor } from './lib/http-exceptions/errors/interceptors/database.interceptor';
import { NotFoundInterceptor } from './lib/http-exceptions/errors/interceptors/not-found.interceptor';
import { BadRequestInterceptor } from './lib/http-exceptions/errors/interceptors/bad-request.interceptor';
import { UnauthorizedInterceptor } from './lib/http-exceptions/errors/interceptors/unauthorized.interceptor';
import { DataSourceInterceptor } from './lib/http-exceptions/errors/interceptors/conction-data-source.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
try {
app.enableCors({
origin: corsConfig.allowedDomains,
});
app.enableShutdownHooks();
app.setGlobalPrefix('server');
/**
* -----------------------------------------------------------------------------
* HTTP Interceptor
* -----------------------------------------------------------------------------
*/
app.useGlobalInterceptors(
new UnauthorizedInterceptor(),
new DataSourceInterceptor(),
new BadRequestInterceptor(),
new NotFoundInterceptor(),
new DataBaseInterceptor(),
);
if (IS_DEV_ENV) {
const [{ SwaggerModule }, { swaggerConfig }, { writeFileSync }] =
await Promise.all([
import('@nestjs/swagger'),
import('./config/swagger.config'),
import('fs'),
]);
const document = SwaggerModule.createDocument(app, swaggerConfig);
writeFileSync('swagger-document.json', JSON.stringify(document, null, 2));
SwaggerModule.setup('server', app, document);
}
await app.listen(ENV_VARIABLES.PORT);
} catch (err) {
Logger.debug(JSON.stringify({ err }, null, 2));
process.exit(1);
}
}
bootstrap();
env.config.ts:
import 'dotenv/config';
import { z } from 'zod';
import {
stringSchema,
optionalStringSchema,
optionalUrlStringSchema,
optionalStringToIntegerSchema,
} from 'src/shared/schemas.shared';
export const envSchema = z.object({
DATABASE_ROOT_PASSWORD: stringSchema,
DATABASE_DATABASE_NAME: stringSchema,
DB_PORT: optionalStringToIntegerSchema.default('5432'),
DATABASE_HOST: optionalStringSchema.default('localhost'),
// REDIS_HOST: optionalStringSchema.default('localhost'),
// REDIS_PASSWORD: stringSchema,
// REDIS_PORT: stringToIntegerSchema,
DB_USER: stringSchema,
JWT_SECRET: stringSchema,
JWT_REFRESH_SECRET: stringSchema,
JWT_REFRESH_EXPIRES_IN: stringSchema,
JWT_ISSUER: optionalUrlStringSchema,
JWT_AUDIENCE: optionalUrlStringSchema,
JWT_EXPIRES_IN: stringSchema,
PORT: optionalStringToIntegerSchema.default('5000'),
ENV: z.enum(['prod', 'dev']).default('dev'),
});
export type EnvType = z.infer<typeof envSchema>;
export const ENV_VARIABLES = envSchema.parse(process.env);
export const IS_DEV_ENV = ENV_VARIABLES.ENV === 'dev';