Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2a3c956
chore: deploy api v2 on vercel
ThyMinimalDev Jan 12, 2026
d789511
fix: replace console.log with logger.log in Vercel handler
devin-ai-integration[bot] Jan 12, 2026
70f0def
chore: enable esModuleInterop
ThyMinimalDev Jan 12, 2026
554484b
Merge branch 'main' into deploy-api-v2-vercel
devin-ai-integration[bot] Jan 12, 2026
f200110
Merge branch 'deploy-api-v2-vercel' of https://git-manager.devin.ai/p…
devin-ai-integration[bot] Jan 12, 2026
6ac8ada
Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
45c704a
chore: deploy api v2 on vercel
ThyMinimalDev Jan 12, 2026
3b4d4f7
chore: deploy api v2 on vercel
ThyMinimalDev Jan 12, 2026
911d185
Update apps/api/v2/src/bootstrap.ts
ThyMinimalDev Jan 12, 2026
8a78551
Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
4959c88
fixup! Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
6b88ca0
Revert "chore: deploy api v2 on vercel"
ThyMinimalDev Jan 12, 2026
e81bcfd
chore: deploy api v2 on vercel
ThyMinimalDev Jan 12, 2026
f3474c2
fix: address Cubic AI review feedback in main.ts
devin-ai-integration[bot] Jan 12, 2026
89fb2b4
Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
7d26c97
fix: remove comma: true from qs.parse to maintain backward compatibility
devin-ai-integration[bot] Jan 12, 2026
0761b27
chore: deploy api v2 on vercel
ThyMinimalDev Jan 12, 2026
3aeaf83
Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
7a0b0c7
small fixes
ThyMinimalDev Jan 12, 2026
4b88ef0
chore: add try catch around bootstrap.ts
ThyMinimalDev Jan 12, 2026
f88b0d5
fix: use NestJS Logger and throw error instead of process.exit in boo…
devin-ai-integration[bot] Jan 12, 2026
ede63f9
chore: try log redis url
ThyMinimalDev Jan 12, 2026
67ed347
fix: sanitize REDIS_URL logging to avoid exposing credentials
devin-ai-integration[bot] Jan 12, 2026
98b3224
chore: remove unnecessary logs
ThyMinimalDev Jan 12, 2026
5bc5923
fix: prisma adapter
ThyMinimalDev Jan 12, 2026
198aebd
chore: handle USE_POOL platform libraries
ThyMinimalDev Jan 12, 2026
b23e109
Merge branch 'main' into deploy-api-v2-vercel
ThyMinimalDev Jan 12, 2026
621515b
fix: use JSON.stringify for Vite define value
devin-ai-integration[bot] Jan 12, 2026
e1b25f0
fix: docker file builds
ThyMinimalDev Jan 12, 2026
f0661dc
fix: correct Dockerfile build order for platform packages
devin-ai-integration[bot] Jan 12, 2026
97dfdae
fix: docker file builds
ThyMinimalDev Jan 12, 2026
865c076
Merge branch 'main' into deploy-api-v2-vercel
devin-ai-integration[bot] Jan 13, 2026
e287329
chore: add docker build
ThyMinimalDev Jan 13, 2026
83914bc
chore: upgrade nest/bull
ThyMinimalDev Jan 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/api/v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"license": "UNLICENSED",
"private": true,
"scripts": {
"build": "yarn dev:build && nest build",
"build": "nest build",
"format": "biome format --write src test",
"start": "nest start",
"dev:build:watch": "concurrently --names \"libraries,lru-fix,constants,enums,utils,types\" \"yarn _dev:build:watch:libraries\" \"yarn _dev:build:watch:libraries:lru-fix\" \"yarn _dev:build:watch:constants\" \"yarn _dev:build:watch:enums\" \"yarn _dev:build:watch:utils\" \"yarn _dev:build:watch:types\"",
Expand Down
6 changes: 4 additions & 2 deletions apps/api/v2/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import type { ValidationError } from "@nestjs/common";
import { BadRequestException, ValidationPipe, VersioningType } from "@nestjs/common";
import type { NestExpressApplication } from "@nestjs/platform-express";
import * as cookieParser from "cookie-parser";
import cookieParser from "cookie-parser";
import { Request } from "express";
import helmet from "helmet";
import { HttpExceptionFilter } from "@/filters/http-exception.filter";
Expand All @@ -22,7 +22,9 @@ import { CalendarServiceExceptionFilter } from "./filters/calendar-service-excep
import { TRPCExceptionFilter } from "./filters/trpc-exception.filter";

export const bootstrap = (app: NestExpressApplication): NestExpressApplication => {
app.enableShutdownHooks();
if (!process.env.VERCEL) {
app.enableShutdownHooks();
}
app.enableVersioning({
type: VersioningType.CUSTOM,
extractor: (request: unknown) => {
Expand Down
93 changes: 81 additions & 12 deletions apps/api/v2/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,67 @@
import "dotenv/config";

import { IncomingMessage, Server, ServerResponse } from "node:http";
import process from "node:process";
import { Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { NestFactory } from "@nestjs/core";
import type { NestExpressApplication } from "@nestjs/platform-express";
import type { Express, Request, Response } from "express";
import { WinstonModule } from "nest-winston";
import * as qs from "qs";

import type { AppConfig } from "@/config/type";

import { AppModule } from "./app.module";
import { bootstrap } from "./bootstrap";
import { loggerConfig } from "./lib/logger";

run().catch((error: Error) => {
console.error("Failed to start Cal Platform API", { error: error.stack });
process.exit(1);
});
const logger: Logger = new Logger("App");

/**
* Singleton Class to manage the NestJS App instance.
* Ensures we only initialize the app once per container lifecycle.
*/
class NestServer {
private static server: Express; // The underlying Express instance

private constructor() {}

/**
* Returns the cached server instance.
* If it doesn't exist, it creates, bootstraps, and initializes it.
*/
public static async getInstance(): Promise<Express> {
if (!NestServer.server) {
const app = await createNestApp();

// Execute bootstrap (Pipes, Interceptors, CORS, etc.)
bootstrap(app);

// Initialize the app (connects to DB, resolves modules)
await app.init();

// extract the Express instance to pass to Vercel
NestServer.server = app.getHttpAdapter().getInstance();
}
return NestServer.server;
}
}

// -----------------------------------------------------------------------------
// LOCAL DEVELOPMENT STARTUP
// -----------------------------------------------------------------------------
if (!process.env.VERCEL) {
console.log("CALL RUN STARTUP");
run().catch((error: Error) => {
logger.error("Failed to start Cal Platform API", { error: error.stack });
process.exit(1);
});
}

async function run(): Promise<void> {
console.log("RUN LOCAL/FlightControl STARTUP");
const app = await createNestApp();
const logger = new Logger("App");

try {
bootstrap(app);
const config = app.get(ConfigService<AppConfig, true>);
Expand All @@ -32,24 +73,52 @@ async function run(): Promise<void> {
}

await app.listen(port);
logger.log(`Application started on port: ${port}`);
logger.log(`Application started locally on port: ${port}`);
} catch (error) {
console.error(error);
logger.error("Application crashed", {
error,
});
logger.error("Application crashed during local startup", { error });
}
}

// -----------------------------------------------------------------------------
// VERCEL SERVERLESS HANDLER
// -----------------------------------------------------------------------------
export default async (req: Request, res: Response): Promise<void> => {
console.log("VERCEL SERVERLESS HANDLER", process.env.VERCEL);
try {
const server = await NestServer.getInstance();

// Vercel/AWS specific: Re-parse query strings to support array formats
// (e.g., ?ids[]=1&ids[]=2) which Vercel's native parser might simplify.
if (req.url) {
const [_path, queryString] = req.url.split("?");
if (queryString) {
req.query = qs.parse(queryString, { arrayLimit: 1000, comma: true });
}
}

// Delegate request to the cached Express instance
return server(req, res);
} catch (error) {
console.error("Critical: Failed to initialize NestJS Serverless instance", error);
res.statusCode = 500;
res.end("Internal Server Error: Initialization Failed");
}
};

// -----------------------------------------------------------------------------
// APP FACTORY
// -----------------------------------------------------------------------------
export async function createNestApp(): Promise<
NestExpressApplication<Server<typeof IncomingMessage, typeof ServerResponse>>
> {
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
logger: WinstonModule.createLogger(loggerConfig()),
// Preserved as requested:
bodyParser: false,
});

app.set("query parser", (str: string) => qs.parse(str, { arrayLimit: 1000 }));
// Custom query parser configuration for the underlying Express app
app.set("query parser", (str: string) => qs.parse(str, { arrayLimit: 1000, comma: true }));

return app;
}
16 changes: 4 additions & 12 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
{
"includes": [
"apps/api/v2/src/config/app.ts",
"apps/api/v2/src/config/bootstrap.ts",
"apps/api/v2/src/bootstrap.ts",
"apps/api/v2/src/config/env.ts",
"apps/api/v2/src/env.ts",
"apps/api/v2/test/setEnvVars.ts"
Expand Down Expand Up @@ -325,9 +325,7 @@
}
},
{
"includes": [
"packages/platform/atoms/**/*.{ts,tsx,js,jsx,mts,mjs,cjs,cts}"
],
"includes": ["packages/platform/atoms/**/*.{ts,tsx,js,jsx,mts,mjs,cjs,cts}"],
"linter": {
"rules": {
"style": {
Expand All @@ -336,17 +334,11 @@
"options": {
"patterns": [
{
"group": [
"@calcom/trpc/react",
"@calcom/trpc/react/**"
],
"group": ["@calcom/trpc/react", "@calcom/trpc/react/**"],
"message": "atoms package should not import from @calcom/trpc/react."
},
{
"group": [
"../../trpc/react",
"../../trpc/react/**"
],
"group": ["../../trpc/react", "../../trpc/react/**"],
"message": "atoms package should not import from trpc/react."
}
]
Expand Down
1 change: 1 addition & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@
},
"@calcom/api-v2#build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"],
"env": [
"NODE_ENV",
"API_PORT",
Expand Down
Loading