feat: complete tOS project with HR, LEAN, Dashboard and Integrations modules
Full enterprise web operating system including: - Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui - NestJS 10 backend with Prisma, JWT auth, Swagger docs - Keycloak 24 SSO with role-based access control - HR module (employees, time tracking, absences, org chart) - LEAN module (3S planning, morning meeting SQCDM, skill matrix) - Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs) - Dashboard with customizable drag & drop widget grid - Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
81
apps/api/src/config/config.validation.ts
Normal file
81
apps/api/src/config/config.validation.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import * as Joi from 'joi';
|
||||
|
||||
export const configValidationSchema = Joi.object({
|
||||
// Application
|
||||
NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
|
||||
PORT: Joi.number().default(3001),
|
||||
API_PREFIX: Joi.string().default('api'),
|
||||
|
||||
// Database
|
||||
DATABASE_URL: Joi.string().required(),
|
||||
|
||||
// JWT / Keycloak
|
||||
JWT_SECRET: Joi.string().when('NODE_ENV', {
|
||||
is: 'production',
|
||||
then: Joi.required(),
|
||||
otherwise: Joi.string().default('dev-secret-key-change-in-production'),
|
||||
}),
|
||||
KEYCLOAK_URL: Joi.string().uri().optional(),
|
||||
KEYCLOAK_REALM: Joi.string().optional(),
|
||||
KEYCLOAK_CLIENT_ID: Joi.string().optional(),
|
||||
KEYCLOAK_CLIENT_SECRET: Joi.string().optional(),
|
||||
|
||||
// CORS
|
||||
CORS_ORIGINS: Joi.string().default('http://localhost:3000'),
|
||||
|
||||
// Swagger
|
||||
SWAGGER_ENABLED: Joi.string().valid('true', 'false').default('true'),
|
||||
|
||||
// Encryption (Phase 3)
|
||||
ENCRYPTION_KEY: Joi.string().min(32).when('NODE_ENV', {
|
||||
is: 'production',
|
||||
then: Joi.required(),
|
||||
otherwise: Joi.optional(),
|
||||
}),
|
||||
|
||||
// Redis (Phase 3 - for BullMQ)
|
||||
REDIS_HOST: Joi.string().optional(),
|
||||
REDIS_PORT: Joi.number().optional(),
|
||||
|
||||
// Sync Jobs (Phase 3)
|
||||
ENABLE_SYNC_JOBS: Joi.string().valid('true', 'false').default('false'),
|
||||
SYNC_INTERVAL_PLENTYONE: Joi.number().min(1).default(15),
|
||||
SYNC_INTERVAL_ZULIP: Joi.number().min(1).default(5),
|
||||
SYNC_INTERVAL_TODOIST: Joi.number().min(1).default(10),
|
||||
SYNC_INTERVAL_FREESCOUT: Joi.number().min(1).default(10),
|
||||
SYNC_INTERVAL_NEXTCLOUD: Joi.number().min(1).default(30),
|
||||
SYNC_INTERVAL_ECODMS: Joi.number().min(1).default(60),
|
||||
SYNC_INTERVAL_GEMBADOCS: Joi.number().min(1).default(30),
|
||||
|
||||
// ============================================================================
|
||||
// Integration Credentials (Phase 3 - API Connectors)
|
||||
// ============================================================================
|
||||
|
||||
// PlentyONE (OAuth2 Client Credentials)
|
||||
PLENTYONE_BASE_URL: Joi.string().uri().optional(),
|
||||
PLENTYONE_CLIENT_ID: Joi.string().optional(),
|
||||
PLENTYONE_CLIENT_SECRET: Joi.string().optional(),
|
||||
|
||||
// ZULIP (Basic Auth with API Key)
|
||||
ZULIP_BASE_URL: Joi.string().uri().optional(),
|
||||
ZULIP_EMAIL: Joi.string().email().optional(),
|
||||
ZULIP_API_KEY: Joi.string().optional(),
|
||||
|
||||
// Todoist (Bearer Token)
|
||||
TODOIST_API_TOKEN: Joi.string().optional(),
|
||||
|
||||
// FreeScout (API Key)
|
||||
FREESCOUT_API_URL: Joi.string().uri().optional(),
|
||||
FREESCOUT_API_KEY: Joi.string().optional(),
|
||||
|
||||
// Nextcloud (Basic Auth / App Password)
|
||||
NEXTCLOUD_URL: Joi.string().uri().optional(),
|
||||
NEXTCLOUD_USERNAME: Joi.string().optional(),
|
||||
NEXTCLOUD_PASSWORD: Joi.string().optional(),
|
||||
|
||||
// ecoDMS (Session-based Auth)
|
||||
ECODMS_API_URL: Joi.string().uri().optional(),
|
||||
ECODMS_USERNAME: Joi.string().optional(),
|
||||
ECODMS_PASSWORD: Joi.string().optional(),
|
||||
ECODMS_API_VERSION: Joi.string().default('v1'),
|
||||
});
|
||||
Reference in New Issue
Block a user