- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
4.9 KiB
JavaScript
Executable File
190 lines
4.9 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Environment Variable Validation Script
|
||
*
|
||
* Validates that all required environment variables are present
|
||
* and have correct values before building for production.
|
||
*
|
||
* Usage: node scripts/validate-env.js [--mode=production]
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
// ============================================================================
|
||
// CONFIGURATION
|
||
// ============================================================================
|
||
|
||
const REQUIRED_VARS = {
|
||
development: [
|
||
'VITE_API_URL',
|
||
],
|
||
production: [
|
||
'VITE_API_URL',
|
||
'VITE_APP_ENV',
|
||
],
|
||
};
|
||
|
||
const LOCALHOST_PATTERNS = [
|
||
'localhost',
|
||
'127.0.0.1',
|
||
'0.0.0.0',
|
||
];
|
||
|
||
// ============================================================================
|
||
// HELPERS
|
||
// ============================================================================
|
||
|
||
/**
|
||
* Load environment file
|
||
*/
|
||
function loadEnvFile(mode) {
|
||
const envFile = mode === 'production'
|
||
? path.join(__dirname, '../.env.production')
|
||
: path.join(__dirname, '../.env');
|
||
|
||
if (!fs.existsSync(envFile)) {
|
||
console.error(`❌ Environment file not found: ${envFile}`);
|
||
process.exit(1);
|
||
}
|
||
|
||
const content = fs.readFileSync(envFile, 'utf-8');
|
||
const env = {};
|
||
|
||
content.split('\n').forEach((line) => {
|
||
// Skip comments and empty lines
|
||
if (line.startsWith('#') || line.trim() === '') {
|
||
return;
|
||
}
|
||
|
||
// Parse KEY=VALUE
|
||
const match = line.match(/^([^=]+)=(.*)$/);
|
||
if (match) {
|
||
const key = match[1].trim();
|
||
const value = match[2].trim();
|
||
env[key] = value;
|
||
}
|
||
});
|
||
|
||
return env;
|
||
}
|
||
|
||
/**
|
||
* Check if value contains localhost patterns
|
||
*/
|
||
function containsLocalhost(value) {
|
||
if (!value) return false;
|
||
return LOCALHOST_PATTERNS.some(pattern =>
|
||
value.toLowerCase().includes(pattern)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Validate environment variables
|
||
*/
|
||
function validateEnv(env, mode) {
|
||
const errors = [];
|
||
const warnings = [];
|
||
|
||
console.log(`\n🔍 Validating environment for mode: ${mode}\n`);
|
||
|
||
// Check required variables
|
||
const required = REQUIRED_VARS[mode] || REQUIRED_VARS.development;
|
||
|
||
required.forEach((varName) => {
|
||
if (!env[varName]) {
|
||
errors.push(`Missing required variable: ${varName}`);
|
||
} else {
|
||
console.log(`✅ ${varName}: ${env[varName]}`);
|
||
}
|
||
});
|
||
|
||
// Production-specific validations
|
||
if (mode === 'production') {
|
||
// 1. Check API_URL doesn't point to localhost
|
||
if (env.VITE_API_URL && containsLocalhost(env.VITE_API_URL)) {
|
||
errors.push(
|
||
`VITE_API_URL points to localhost in production: ${env.VITE_API_URL}`
|
||
);
|
||
}
|
||
|
||
// 2. Check WS_URL doesn't point to localhost
|
||
if (env.VITE_WS_URL && containsLocalhost(env.VITE_WS_URL)) {
|
||
errors.push(
|
||
`VITE_WS_URL points to localhost in production: ${env.VITE_WS_URL}`
|
||
);
|
||
}
|
||
|
||
// 3. Check APP_ENV is set to production
|
||
if (env.VITE_APP_ENV !== 'production') {
|
||
warnings.push(
|
||
`VITE_APP_ENV is not set to 'production': ${env.VITE_APP_ENV}`
|
||
);
|
||
}
|
||
|
||
// 4. Check DEBUG flags are disabled
|
||
if (env.VITE_ENABLE_DEBUG === 'true') {
|
||
warnings.push('VITE_ENABLE_DEBUG is enabled in production');
|
||
}
|
||
|
||
if (env.VITE_MOCK_API === 'true') {
|
||
errors.push('VITE_MOCK_API is enabled in production');
|
||
}
|
||
|
||
// 5. Check analytics is enabled
|
||
if (env.VITE_ENABLE_ANALYTICS !== 'true') {
|
||
warnings.push('VITE_ENABLE_ANALYTICS is not enabled in production');
|
||
}
|
||
}
|
||
|
||
// Display results
|
||
console.log('\n' + '='.repeat(60));
|
||
|
||
if (warnings.length > 0) {
|
||
console.log('\n⚠️ WARNINGS:\n');
|
||
warnings.forEach((warning) => {
|
||
console.log(` - ${warning}`);
|
||
});
|
||
}
|
||
|
||
if (errors.length > 0) {
|
||
console.log('\n❌ ERRORS:\n');
|
||
errors.forEach((error) => {
|
||
console.log(` - ${error}`);
|
||
});
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('\n❌ Environment validation FAILED\n');
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log('\n✅ Environment validation PASSED\n');
|
||
console.log('='.repeat(60) + '\n');
|
||
}
|
||
|
||
// ============================================================================
|
||
// MAIN
|
||
// ============================================================================
|
||
|
||
function main() {
|
||
// Parse arguments
|
||
const args = process.argv.slice(2);
|
||
const modeArg = args.find(arg => arg.startsWith('--mode='));
|
||
const mode = modeArg ? modeArg.split('=')[1] : process.env.NODE_ENV || 'development';
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log(' GAMILIT Platform - Environment Validation');
|
||
console.log('='.repeat(60));
|
||
|
||
// Load and validate environment
|
||
const env = loadEnvFile(mode);
|
||
validateEnv(env, mode);
|
||
}
|
||
|
||
// Run if called directly
|
||
if (require.main === module) {
|
||
main();
|
||
}
|
||
|
||
module.exports = { loadEnvFile, validateEnv };
|