Add 63 unit tests with 100% code coverage for CORS configuration utilities. **Test Coverage:** - createCorsConfig() function (24 tests) - Default behavior and configuration structure - Environment variable parsing (comma-separated, trimming) - includeAllManaApps flag functionality - Custom development origins - Additional origins (mobile apps) - Origin deduplication across all sources - Combined options integration - createCorsConfigWithCallback() function (15 tests) - Callback mode for mobile app support - No origin handling (server-to-server) - Valid/invalid origin validation - Security: protocol-sensitive matching - Callback return value validation - Origin constants (24 tests) - MANACORE_STAGING_ORIGINS validation - MANACORE_PRODUCTION_ORIGINS validation - MANACORE_ALL_APP_ORIGINS combination - URL format validation - Duplicate detection - Consistency between environments **Results:** - 63 tests passing - 100% code coverage (statements, branches, functions, lines) - All edge cases covered (empty values, whitespace, duplicates) **Setup:** - Added Jest with ts-jest for TypeScript support - Added test scripts: test, test:watch, test:coverage - Created jest.config.js with coverage configuration - Proper TypeScript types for callback functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| src | ||
| jest.config.js | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
@manacore/shared-nestjs-cors
Centralized CORS configuration utility for all ManaCore NestJS backends.
Problem
Every deployed app was encountering CORS errors because:
- Each backend had different CORS configuration patterns
- Missing
CORS_ORIGINSenvironment variable in staging/production - No consistent way to handle development vs production origins
Solution
This package provides a standardized CORS configuration that:
- ✅ Works in development without configuration
- ✅ Supports staging/production via
CORS_ORIGINSenv var - ✅ Handles mobile app origins (exp://, myapp://)
- ✅ Prevents duplicate origin definitions
- ✅ Provides consistent security settings
Usage
Basic Setup (Recommended)
import { NestFactory } from '@nestjs/core';
import { createCorsConfig } from '@manacore/shared-nestjs-cors';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Enable CORS with automatic origin detection
app.enableCors(createCorsConfig({
corsOriginsEnv: process.env.CORS_ORIGINS
}));
await app.listen(3000);
}
bootstrap();
With Custom Development Origins
app.enableCors(createCorsConfig({
corsOriginsEnv: process.env.CORS_ORIGINS,
developmentOrigins: [
'http://localhost:3000',
'http://localhost:5173'
]
}));
With Mobile App Support
app.enableCors(createCorsConfig({
corsOriginsEnv: process.env.CORS_ORIGINS,
additionalOrigins: [
'exp://localhost:8081', // Expo development
'myapp://', // Custom mobile scheme
]
}));
Advanced: Callback-based CORS
For advanced scenarios (e.g., allowing server-to-server calls):
import { createCorsConfigWithCallback } from '@manacore/shared-nestjs-cors';
app.enableCors(createCorsConfigWithCallback({
corsOriginsEnv: process.env.CORS_ORIGINS
}));
Environment Variables
Development (.env.development)
No configuration needed! Default origins cover common ports:
http://localhost:3000-3020(backends)http://localhost:5173-5190(web apps)http://localhost:8081(mobile)exp://localhost:8081(Expo)
Staging/Production
Set CORS_ORIGINS environment variable in your docker-compose.yml:
chat-backend:
environment:
CORS_ORIGINS: https://chat.staging.manacore.ai,https://chat-api.staging.manacore.ai,https://staging.manacore.ai
Default Configuration
The utility applies these NestJS CORS settings:
{
origin: [...], // From corsOriginsEnv + developmentOrigins + additionalOrigins
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
}
Migration Guide
Before (Manual CORS)
// ❌ Old way - different in every backend
const corsOrigins = process.env.CORS_ORIGINS?.split(',').map(o => o.trim()) || [
'http://localhost:3000',
'http://localhost:5173',
// ... different defaults in each app
];
app.enableCors({
origin: corsOrigins,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
credentials: true,
});
After (Centralized)
// ✅ New way - consistent everywhere
import { createCorsConfig } from '@manacore/shared-nestjs-cors';
app.enableCors(createCorsConfig({
corsOriginsEnv: process.env.CORS_ORIGINS
}));
Troubleshooting
CORS error in staging/production
Symptom: "Access to fetch has been blocked by CORS policy"
Solution: Ensure CORS_ORIGINS is set in docker-compose:
environment:
CORS_ORIGINS: https://your-app.staging.manacore.ai,https://staging.manacore.ai
Mobile app not connecting
Symptom: Mobile app fails to connect to backend
Solution: Add mobile origins:
app.enableCors(createCorsConfig({
corsOriginsEnv: process.env.CORS_ORIGINS,
additionalOrigins: ['exp://localhost:8081']
}));
API Reference
createCorsConfig(options?)
Creates standard CORS configuration.
Parameters:
options.corsOriginsEnv(string, optional): Comma-separated origins from envoptions.developmentOrigins(string[], optional): Custom dev originsoptions.additionalOrigins(string[], optional): Additional origins to allow
Returns: NestJS CorsOptions object
createCorsConfigWithCallback(options?)
Creates CORS configuration with callback for advanced use cases.
Parameters: Same as createCorsConfig
Returns: NestJS CorsOptions object with origin callback
License
Private - ManaCore Monorepo