Schema additions for issues #37-41: New models: - Domain (#37): Life domains (work, marriage, homelab, etc.) - Idea (#38): Brain dumps with pgvector embeddings - Relationship (#39): Generic entity linking (blocks, depends_on) - Agent (#40): ClawdBot agent tracking with metrics - AgentSession (#40): Conversation session tracking - WidgetDefinition (#41): HUD widget registry - UserLayout (#41): Per-user dashboard configuration Updated models: - Task, Event, Project: Added domainId foreign key - User, Workspace: Added new relations New enums: - IdeaStatus: CAPTURED, PROCESSING, ACTIONABLE, ARCHIVED, DISCARDED - RelationshipType: BLOCKS, BLOCKED_BY, DEPENDS_ON, etc. - AgentStatus: IDLE, WORKING, WAITING, ERROR, TERMINATED - EntityType: Added IDEA, DOMAIN Migration: 20260129182803_add_domains_ideas_agents_widgets
75 lines
1.8 KiB
TypeScript
75 lines
1.8 KiB
TypeScript
import { NestFactory } from "@nestjs/core";
|
|
import { ValidationPipe } from "@nestjs/common";
|
|
import { AppModule } from "./app.module";
|
|
import { GlobalExceptionFilter } from "./filters/global-exception.filter";
|
|
|
|
function getPort(): number {
|
|
const portEnv = process.env.PORT;
|
|
|
|
if (portEnv === undefined || portEnv === "") {
|
|
return 3001;
|
|
}
|
|
|
|
const port = parseInt(portEnv, 10);
|
|
|
|
if (isNaN(port)) {
|
|
throw new Error(`Invalid PORT environment variable: "${portEnv}". PORT must be a number.`);
|
|
}
|
|
|
|
if (port < 1 || port > 65535) {
|
|
throw new Error(
|
|
`Invalid PORT environment variable: ${String(port)}. PORT must be between 1 and 65535.`
|
|
);
|
|
}
|
|
|
|
return port;
|
|
}
|
|
|
|
async function bootstrap() {
|
|
const app = await NestFactory.create(AppModule);
|
|
|
|
// Enable global validation pipe with transformation
|
|
app.useGlobalPipes(
|
|
new ValidationPipe({
|
|
transform: true,
|
|
whitelist: true,
|
|
forbidNonWhitelisted: false,
|
|
transformOptions: {
|
|
enableImplicitConversion: false,
|
|
},
|
|
})
|
|
);
|
|
|
|
app.useGlobalFilters(new GlobalExceptionFilter());
|
|
app.enableCors();
|
|
|
|
const port = getPort();
|
|
await app.listen(port);
|
|
|
|
console.log(`API running on http://localhost:${String(port)}`);
|
|
}
|
|
|
|
bootstrap().catch((err: unknown) => {
|
|
const isProduction = process.env.NODE_ENV === "production";
|
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
const errorStack = err instanceof Error ? err.stack : undefined;
|
|
|
|
if (isProduction) {
|
|
console.error(
|
|
JSON.stringify({
|
|
level: "error",
|
|
message: "Failed to start application",
|
|
error: errorMessage,
|
|
timestamp: new Date().toISOString(),
|
|
})
|
|
);
|
|
} else {
|
|
console.error("Failed to start application:", errorMessage);
|
|
if (errorStack) {
|
|
console.error(errorStack);
|
|
}
|
|
}
|
|
|
|
process.exit(1);
|
|
});
|