managarten/packages/shared-nestjs-cors
Wuesteon c5d662bb89 test(cors): add comprehensive unit tests for shared-nestjs-cors
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>
2025-12-17 18:11:13 +01:00
..
src test(cors): add comprehensive unit tests for shared-nestjs-cors 2025-12-17 18:11:13 +01:00
jest.config.js test(cors): add comprehensive unit tests for shared-nestjs-cors 2025-12-17 18:11:13 +01:00
package.json test(cors): add comprehensive unit tests for shared-nestjs-cors 2025-12-17 18:11:13 +01:00
README.md 1. Brevo email integration (API key, sender settings) 2025-12-17 18:11:13 +01:00
tsconfig.json 1. Brevo email integration (API key, sender settings) 2025-12-17 18:11:13 +01:00

@manacore/shared-nestjs-cors

Centralized CORS configuration utility for all ManaCore NestJS backends.

Problem

Every deployed app was encountering CORS errors because:

  1. Each backend had different CORS configuration patterns
  2. Missing CORS_ORIGINS environment variable in staging/production
  3. 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_ORIGINS env var
  • Handles mobile app origins (exp://, myapp://)
  • Prevents duplicate origin definitions
  • Provides consistent security settings

Usage

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 env
  • options.developmentOrigins (string[], optional): Custom dev origins
  • options.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