From andercore-toolkit-services
Unified app initialization with versioning, validation, CORS, shutdown. Use when setting up main.ts, configuring app init.
npx claudepluginhub andercore-labs/claudes-kitchen --plugin andercore-toolkit-servicesThis skill uses the workspace's default tool permissions.
| Feature | Pattern | Line |
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
| Feature | Pattern | Line |
|---|---|---|
| Init app | bootstrap({ ... }) | main.ts:5 |
| Global prefix | globalPrefix: 'api' | main.ts:8 |
| Versioning | versioning: { type: 'URI' } | main.ts:9 |
| Validation | validation: { transform: true } | main.ts:13 |
| Swagger | swagger: { title, ... } | main.ts:17 |
App initialization | main.ts setup | API versioning | global config | startup
main.ts:
import { bootstrap } from '@andercore/toolkit'
import { AppModule } from './app.module'
bootstrap({
appModule: AppModule,
port: 3000,
globalPrefix: 'api',
versioning: {
type: 'URI',
defaultVersion: ['0']
},
swagger: {
title: 'User Service API',
description: 'API Documentation',
version: '1.0.0',
path: 'api-docs',
supportedVersions: ['0', '1']
},
validation: {
transform: true,
whitelist: true,
forbidUnknownValues: true
},
cors: {
origin: ['https://app.example.com'],
credentials: true
},
shutdownHooks: true
})
Result: http://localhost:3000/api/v0/users
| Option | Required | Default | Purpose |
|---|---|---|---|
| appModule | ✓ | - | NestJS root module |
| port | ✗ | 3000 | Server port |
| globalPrefix | ✗ | - | API prefix (/api) |
| versioning | ✗ | - | API versioning config |
| swagger | ✗ | - | Swagger UI config |
| validation | ✗ | - | Global validation pipe |
| cors | ✗ | false | CORS configuration |
| shutdownHooks | ✗ | false | Graceful shutdown |
| nestOptions | ✗ | {} | Custom NestFactory options |
bootstrap({
appModule: AppModule,
globalPrefix: 'api'
})
Routes:
/api/users ✓/users ✗Exclude specific routes:
bootstrap({
appModule: AppModule,
globalPrefix: 'api',
nestOptions: {
globalPrefixOptions: {
exclude: ['health', 'metrics']
}
}
})
Routes:
/api/users ✓/health ✓ (excluded)/metrics ✓ (excluded)versioning: {
type: 'URI',
defaultVersion: ['0']
}
Routes:
/api/v0/users (default)/api/v1/users (explicit)Controller:
@Controller({ path: 'users', version: '1' })
export class UsersV1Controller {}
@Controller({ path: 'users', version: ['0', '1'] })
export class UsersController {}
versioning: {
type: 'URI',
defaultVersion: ['0', '1']
}
Both /api/v0/users and /api/v1/users serve default controllers
versioning: {
type: 'HEADER',
header: 'X-API-Version',
defaultVersion: '1'
}
Request:
GET /api/users HTTP/1.1
X-API-Version: 2
versioning: {
type: 'MEDIA_TYPE',
key: 'v=',
defaultVersion: '1'
}
Request:
GET /api/users HTTP/1.1
Accept: application/json;v=2
validation: {
transform: true,
whitelist: true,
forbidUnknownValues: true,
forbidNonWhitelisted: true,
transformOptions: {
enableImplicitConversion: true
}
}
| Option | Effect |
|---|---|
| transform | Auto DTO class instantiation |
| whitelist | Strip unknown properties |
| forbidUnknownValues | Reject unknown types |
| forbidNonWhitelisted | Throw on unknown props |
| enableImplicitConversion | Auto type conversion (string → number) |
Example:
class CreateUserDto {
@IsString()
name: string
@IsInt()
@Min(18)
age: number
@IsEmail()
email: string
}
// Request: { name: "John", age: "25", email: "john@example.com", hack: "xyz" }
// Transformed: { name: "John", age: 25, email: "john@example.com" }
// (hack stripped, age converted to number)
cors: true
Allows all origins (development only)
cors: {
origin: ['https://app.example.com', 'https://admin.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['X-Total-Count'],
maxAge: 86400
}
| Option | Purpose |
|---|---|
| origin | Allowed origins (array or function) |
| methods | Allowed HTTP methods |
| credentials | Allow cookies/credentials |
| allowedHeaders | Allowed request headers |
| exposedHeaders | Headers exposed to client |
| maxAge | Preflight cache duration (seconds) |
Dynamic origin:
cors: {
origin: (origin, callback) => {
const whitelist = ['https://app.example.com', 'https://admin.example.com']
if (!origin || whitelist.includes(origin)) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
credentials: true
}
swagger: {
title: 'User Service API',
description: 'Comprehensive API for user management',
version: '1.0.0',
path: 'api-docs',
supportedVersions: ['0', '1']
}
| Option | Required | Default | Purpose |
|---|---|---|---|
| title | ✓ | - | API title |
| description | ✓ | - | API description |
| version | ✗ | '1.0.0' | API version |
| path | ✗ | 'document' | Swagger UI path |
| supportedVersions | ✗ | - | Version filter |
Access: http://localhost:3000/api-docs
→ See swagger-recipe for comprehensive Swagger documentation patterns
shutdownHooks: true
Handles:
Cleanup sequence:
Custom cleanup:
@Injectable()
export class AppService implements OnApplicationShutdown {
async onApplicationShutdown(signal?: string) {
console.log(`Received shutdown signal: ${signal}`)
await this.cleanup()
}
private async cleanup() {
await this.db.close()
await this.cache.disconnect()
}
}
bootstrap({
appModule: AppModule,
nestOptions: {
logger: ['error', 'warn'],
abortOnError: false,
bufferLogs: true,
autoFlushLogs: true
}
})
import { bootstrapApp } from '@andercore/toolkit'
const app = await bootstrapApp({
appModule: AppModule,
port: 3000
})
// Custom configuration
app.useWebSocketAdapter(new WsAdapter(app))
app.useStaticAssets(join(__dirname, '..', 'public'))
await app.listen(3000)
// main.ts
import { bootstrap } from '@andercore/toolkit'
import { AppModule } from './app.module'
const isProduction = process.env.NODE_ENV === 'production'
bootstrap({
appModule: AppModule,
port: parseInt(process.env.PORT || '3000', 10),
globalPrefix: 'api',
versioning: {
type: 'URI',
defaultVersion: ['1']
},
validation: {
transform: true,
whitelist: true,
forbidUnknownValues: isProduction
},
cors: isProduction
? {
origin: process.env.ALLOWED_ORIGINS?.split(',') || [],
credentials: true
}
: true,
swagger: isProduction ? undefined : {
title: 'Dev API',
description: 'Development API',
version: '1.0.0'
},
shutdownHooks: isProduction
})
bootstrap({
appModule: AppModule,
port: 3001,
globalPrefix: 'api',
validation: {
transform: true,
whitelist: true
},
shutdownHooks: true
// No CORS (internal service)
// No Swagger (internal service)
})
→ typescript-services:test-code-recipe for patterns
E2E test setup:
import { bootstrapApp } from '@andercore/toolkit'
import { AppModule } from '../src/app.module'
describe('App (e2e)', () => {
let app: INestApplication
beforeAll(async () => {
app = await bootstrapApp({
appModule: AppModule,
port: 0 // Random port
})
})
afterAll(async () => {
await app.close()
})
it('/api/users (GET)', () => {
return request(app.getHttpServer())
.get('/api/users')
.expect(200)
})
})
CHECK:
- [ ] bootstrap() in main.ts?
- [ ] globalPrefix set (e.g., 'api')?
- [ ] Versioning enabled (URI preferred)?
- [ ] Validation pipe configured?
- [ ] transform: true for DTO instantiation?
- [ ] whitelist: true for security?
- [ ] CORS configured for production?
- [ ] shutdownHooks: true for graceful shutdown?
- [ ] Swagger disabled in production?
- [ ] Port from environment variable?
VIOLATIONS (CRITICAL):
- Manual NestFactory.create() without bootstrap() → MEDIUM
- No API versioning → HIGH
- No global validation → CRITICAL
- cors: true in production → CRITICAL
- Swagger enabled in production → MEDIUM
- No graceful shutdown → MEDIUM
- Hardcoded port → LOW
PASS → DONE | FAIL → cite violations with file:line
→ swagger-recipe for Swagger configuration → configuration-recipe for environment variables → typescript-services:nestjs-recipe for NestJS patterns