main #2
@ -14,16 +14,8 @@ const gradient = require('gradient-string');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
// Configuration URLs - can be updated as needed
|
||||
const ENV_CONFIG_URLS = {
|
||||
internal: 'https://raw.githubusercontent.com/corradaf/env-configs/main/internal.env'
|
||||
};
|
||||
|
||||
// Internal access token for secure env access
|
||||
const INTERNAL_ACCESS_TOKEN = 'corrad_internal_2024_secure_token_af';
|
||||
|
||||
// Function to fetch content from URL with security
|
||||
function fetchFromUrl(url, token = null) {
|
||||
// Function to fetch content from URL
|
||||
function fetchFromUrl(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = url.startsWith('https') ? https : http;
|
||||
|
||||
@ -32,15 +24,9 @@ function fetchFromUrl(url, token = null) {
|
||||
hostname: urlObj.hostname,
|
||||
port: urlObj.port,
|
||||
path: urlObj.pathname + urlObj.search,
|
||||
method: 'GET',
|
||||
headers: {}
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
if (token) {
|
||||
options.headers['Authorization'] = `Bearer ${token}`;
|
||||
options.headers['X-Access-Token'] = token;
|
||||
}
|
||||
|
||||
const req = client.request(options, (res) => {
|
||||
let data = '';
|
||||
|
||||
@ -122,6 +108,30 @@ function createProgressBar(message, duration = 3000) {
|
||||
});
|
||||
}
|
||||
|
||||
// Clear screen and display ASCII art
|
||||
function displayHeader() {
|
||||
clearScreen();
|
||||
|
||||
// Show ASCII "CORRAD AF" with gradient
|
||||
const asciiText = figlet.textSync('CORRAD AF', {
|
||||
font: 'Big',
|
||||
horizontalLayout: 'default',
|
||||
verticalLayout: 'default'
|
||||
});
|
||||
|
||||
console.log(gradient.rainbow(asciiText));
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 Welcome to CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// Clear screen and position cursor at top
|
||||
function clearScreen() {
|
||||
console.clear();
|
||||
@ -163,73 +173,59 @@ function extractComment(line) {
|
||||
return commentMatch ? commentMatch[1].trim() : '';
|
||||
}
|
||||
|
||||
// Prompt for environment configurations
|
||||
async function promptForEnvConfig(envVars, projectName) {
|
||||
const envConfig = {};
|
||||
|
||||
console.log(chalk.cyan.bold('\n⚙️ Environment Configuration'));
|
||||
console.log(chalk.gray('Configure your project environment variables:\n'));
|
||||
|
||||
for (const envVar of envVars) {
|
||||
let message = `${envVar.key}`;
|
||||
if (envVar.description) {
|
||||
message += chalk.gray(` (${envVar.description})`);
|
||||
}
|
||||
|
||||
let defaultValue = envVar.defaultValue;
|
||||
|
||||
// Replace placeholder values
|
||||
if (defaultValue.includes('${projectName}') || defaultValue.includes('your-project')) {
|
||||
defaultValue = defaultValue.replace(/\${projectName}|your-project/g, projectName);
|
||||
}
|
||||
|
||||
const { value } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'value',
|
||||
message: message + ':',
|
||||
default: defaultValue,
|
||||
validate: function(input) {
|
||||
if (envVar.key.includes('SECRET') || envVar.key.includes('PASSWORD')) {
|
||||
if (input.trim().length < 8) {
|
||||
return 'Security values should be at least 8 characters long';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
envConfig[envVar.key] = value;
|
||||
// Create default .env.example file if it doesn't exist
|
||||
function createDefaultEnvExample() {
|
||||
const defaultEnvContent = `# Database Configuration
|
||||
DATABASE_URL="mysql://username:password@localhost:3306/database_name" # Your MySQL connection string
|
||||
|
||||
# Authentication
|
||||
JWT_SECRET="your-super-secret-jwt-key-change-this-in-production" # Secret key for JWT tokens
|
||||
AUTH_ORIGIN="http://localhost:3000" # Allowed origin for authentication
|
||||
|
||||
# Application
|
||||
NUXT_SECRET_KEY="your-nuxt-secret-key-for-session-encryption" # Nuxt secret key
|
||||
APP_NAME="Your Application Name" # Your application name
|
||||
APP_URL="http://localhost:3000" # Your application URL
|
||||
|
||||
# Email Configuration (Optional)
|
||||
MAIL_HOST="smtp.example.com" # SMTP server host
|
||||
MAIL_PORT="587" # SMTP server port
|
||||
MAIL_USERNAME="your-email@example.com" # SMTP username
|
||||
MAIL_PASSWORD="your-email-password" # SMTP password
|
||||
MAIL_FROM_ADDRESS="noreply@yourapp.com" # From email address
|
||||
MAIL_FROM_NAME="Your App Name" # From name
|
||||
|
||||
# Development
|
||||
NODE_ENV="development" # Environment (development, production)
|
||||
NUXT_HOST="localhost" # Nuxt host
|
||||
NUXT_PORT="3000" # Nuxt port
|
||||
`;
|
||||
|
||||
fs.writeFileSync('.env.example', defaultEnvContent);
|
||||
return defaultEnvContent;
|
||||
}
|
||||
|
||||
// Check if environment is properly configured
|
||||
function isEnvConfigured() {
|
||||
if (!fs.existsSync('.env')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return envConfig;
|
||||
const envContent = fs.readFileSync('.env', 'utf-8');
|
||||
// Check if DATABASE_URL is properly set (not empty or default)
|
||||
const dbUrlMatch = envContent.match(/DATABASE_URL\s*=\s*["'](.+?)["']/);
|
||||
|
||||
if (!dbUrlMatch) return false;
|
||||
|
||||
const dbUrl = dbUrlMatch[1];
|
||||
return dbUrl && !dbUrl.includes('username:password');
|
||||
}
|
||||
|
||||
// Main CLI function
|
||||
async function main() {
|
||||
try {
|
||||
// Clear console and show welcome screen (only once)
|
||||
clearScreen();
|
||||
|
||||
// Step 1: Show ASCII "CORRAD AF" with gradient (only once)
|
||||
const asciiText = figlet.textSync('CORRAD AF', {
|
||||
font: 'Big',
|
||||
horizontalLayout: 'default',
|
||||
verticalLayout: 'default'
|
||||
});
|
||||
|
||||
console.log(gradient.rainbow(asciiText));
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 Welcome to CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
// Show the header once at the beginning
|
||||
displayHeader();
|
||||
|
||||
// Check for existing project files
|
||||
const hasFiles = hasProjectFiles();
|
||||
@ -264,18 +260,8 @@ async function main() {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Clear screen and show project name prompt
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
// Display header again for consistency
|
||||
displayHeader();
|
||||
|
||||
// Get project name (only for new projects)
|
||||
let projectName = path.basename(process.cwd());
|
||||
@ -302,94 +288,32 @@ async function main() {
|
||||
projectName = inputProjectName;
|
||||
}
|
||||
|
||||
// Clear screen and show project type selection
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
// Display header again for consistency
|
||||
displayHeader();
|
||||
|
||||
// Step 3: Ask if public or internal project
|
||||
console.log(chalk.cyan.bold('\n🔐 Project Type'));
|
||||
const { projectType } = await inquirer.prompt([
|
||||
// Step 3: Ask about environment setup
|
||||
console.log(chalk.cyan.bold('\n🔐 Environment Setup'));
|
||||
const { envSetupType } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'projectType',
|
||||
message: 'Is this a public or internal project?',
|
||||
name: 'envSetupType',
|
||||
message: 'How would you like to set up your environment?',
|
||||
choices: [
|
||||
{
|
||||
name: chalk.green('🌍 Public') + chalk.gray(' - Configure environment manually'),
|
||||
value: 'public'
|
||||
name: chalk.green('🔧 Manual Setup') + chalk.gray(' - Configure environment later'),
|
||||
value: 'manual'
|
||||
},
|
||||
{
|
||||
name: chalk.red('🔒 Internal') + chalk.gray(' - Use company configuration'),
|
||||
value: 'internal'
|
||||
name: chalk.blue('🔗 Import from URL') + chalk.gray(' - Paste a configuration URL'),
|
||||
value: 'url'
|
||||
}
|
||||
],
|
||||
default: 0
|
||||
}
|
||||
]);
|
||||
|
||||
let isInternal = false;
|
||||
let useCompanyEnv = false;
|
||||
|
||||
if (projectType === 'internal') {
|
||||
isInternal = true;
|
||||
|
||||
// Clear screen and show password prompt
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
|
||||
// Password verification for internal projects
|
||||
console.log(chalk.yellow('\n🔒 Internal project detected - Password verification required'));
|
||||
const { password } = await inquirer.prompt([
|
||||
{
|
||||
type: 'password',
|
||||
name: 'password',
|
||||
message: 'Enter company password:',
|
||||
mask: '*'
|
||||
}
|
||||
]);
|
||||
|
||||
if (password !== 'Rahsia@123456') {
|
||||
console.log(chalk.red('❌ Incorrect password. Access denied.'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(chalk.green('✓ Password verified. Access granted.'));
|
||||
useCompanyEnv = true;
|
||||
|
||||
} else {
|
||||
console.log(chalk.green('✓ Public project setup selected.'));
|
||||
}
|
||||
|
||||
// Clear screen and show development tools prompt
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
// Display header again for consistency
|
||||
displayHeader();
|
||||
|
||||
// Step 4: Ask about Cursor rules
|
||||
console.log(chalk.cyan.bold('\n⚙️ Development Tools'));
|
||||
@ -406,18 +330,8 @@ async function main() {
|
||||
}
|
||||
]);
|
||||
|
||||
// Clear screen and show setup progress
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
// Display header again for consistency
|
||||
displayHeader();
|
||||
|
||||
// Step 5: Show loading screen and setup project
|
||||
console.log(chalk.cyan.bold('\n🚀 Setting up your project...'));
|
||||
@ -467,75 +381,83 @@ async function main() {
|
||||
}
|
||||
|
||||
// Setup environment file
|
||||
if (useCompanyEnv && isInternal) {
|
||||
const envSpinner = ora('Setting up company environment...').start();
|
||||
if (envSetupType === 'url') {
|
||||
// Display header for consistency
|
||||
displayHeader();
|
||||
|
||||
const { envUrl } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'envUrl',
|
||||
message: 'Enter the URL for your environment configuration:',
|
||||
validate: function(input) {
|
||||
if (!input.trim() || !input.startsWith('http')) {
|
||||
return 'Please enter a valid URL (starting with http:// or https://)';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
const envSpinner = ora('Fetching environment configuration from URL...').start();
|
||||
|
||||
try {
|
||||
// Fetch .env content from secure URL
|
||||
const envContent = await fetchFromUrl(ENV_CONFIG_URLS.internal, INTERNAL_ACCESS_TOKEN);
|
||||
// Fetch .env content from provided URL
|
||||
const envContent = await fetchFromUrl(envUrl);
|
||||
const processedContent = envContent.replace(/\${projectName}/g, projectName);
|
||||
|
||||
fs.writeFileSync('.env', processedContent);
|
||||
envSpinner.succeed('Company environment configured');
|
||||
envSpinner.succeed('Environment configuration imported successfully');
|
||||
|
||||
// Run Prisma commands if the env is properly configured
|
||||
if (isEnvConfigured()) {
|
||||
const prismaSpinner = ora('Setting up Prisma database...').start();
|
||||
if (fs.existsSync('prisma/schema.prisma')) {
|
||||
const prismaSuccess = runCommand('npx prisma generate', { stdio: 'pipe' });
|
||||
if (prismaSuccess) {
|
||||
prismaSpinner.succeed('Prisma database configured');
|
||||
} else {
|
||||
prismaSpinner.fail('Prisma setup failed - please check your DATABASE_URL');
|
||||
}
|
||||
} else {
|
||||
prismaSpinner.warn('No Prisma schema found - skipping database setup');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
envSpinner.fail('Failed to fetch company environment config');
|
||||
console.log(chalk.yellow('⚠️ Unable to access secure company environment.'));
|
||||
console.log(chalk.gray('Please contact your system administrator for access.'));
|
||||
process.exit(1);
|
||||
envSpinner.fail('Failed to fetch environment configuration');
|
||||
console.log(chalk.yellow(`⚠️ Unable to access URL: ${error.message}`));
|
||||
console.log(chalk.gray('Creating a basic .env file you can edit later...'));
|
||||
|
||||
// Create basic .env file from .env.example
|
||||
try {
|
||||
let exampleContent;
|
||||
if (fs.existsSync('.env.example')) {
|
||||
exampleContent = fs.readFileSync('.env.example', 'utf8');
|
||||
} else {
|
||||
exampleContent = createDefaultEnvExample();
|
||||
}
|
||||
fs.copyFileSync('.env.example', '.env');
|
||||
console.log(chalk.green('✓ Basic environment file created'));
|
||||
console.log(chalk.yellow('⚠️ Please edit the .env file and configure your DATABASE_URL before running Prisma commands'));
|
||||
} catch (error) {
|
||||
console.log(chalk.red(`Error creating .env file: ${error.message}`));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create environment file based on .env.example
|
||||
const envSpinner = ora('Setting up environment configuration...').start();
|
||||
// Manual environment setup
|
||||
const envSpinner = ora('Setting up environment files...').start();
|
||||
|
||||
try {
|
||||
if (fs.existsSync('.env.example')) {
|
||||
const exampleContent = fs.readFileSync('.env.example', 'utf8');
|
||||
const envVars = parseEnvExample(exampleContent);
|
||||
|
||||
envSpinner.succeed('Environment template loaded');
|
||||
|
||||
// Clear screen for env configuration
|
||||
clearScreen();
|
||||
console.log(boxen(
|
||||
chalk.white.bold('🚀 CORRAD Application Framework CLI\n') +
|
||||
chalk.gray('The fastest way to bootstrap your next project'),
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'cyan'
|
||||
}
|
||||
));
|
||||
|
||||
// Prompt for each environment variable
|
||||
const envConfig = await promptForEnvConfig(envVars, projectName);
|
||||
|
||||
// Generate .env file
|
||||
let envContent = '';
|
||||
for (const [key, value] of Object.entries(envConfig)) {
|
||||
envContent += `${key}="${value}"\n`;
|
||||
}
|
||||
|
||||
fs.writeFileSync('.env', envContent);
|
||||
console.log(chalk.green('✓ Environment file created'));
|
||||
} else {
|
||||
envSpinner.warn('No .env.example found - creating basic environment');
|
||||
|
||||
// Fallback to basic template
|
||||
const fallbackEnv = `# Basic Environment Configuration
|
||||
DATABASE_URL="postgresql://username:password@localhost:5432/database_name"
|
||||
JWT_SECRET="your-super-secret-jwt-key"
|
||||
AUTH_ORIGIN="http://localhost:3000"
|
||||
NUXT_SECRET_KEY="your-nuxt-secret-key"
|
||||
APP_NAME="${projectName}"
|
||||
APP_URL="http://localhost:3000"
|
||||
NODE_ENV="development"
|
||||
NUXT_HOST="localhost"
|
||||
NUXT_PORT="3000"
|
||||
`;
|
||||
fs.writeFileSync('.env', fallbackEnv);
|
||||
console.log(chalk.green('✓ Basic environment created'));
|
||||
// Create or ensure .env.example exists
|
||||
if (!fs.existsSync('.env.example')) {
|
||||
createDefaultEnvExample();
|
||||
}
|
||||
|
||||
// Copy .env.example to .env without filling in values
|
||||
fs.copyFileSync('.env.example', '.env');
|
||||
envSpinner.succeed('Environment files created');
|
||||
console.log(chalk.green('✓ Created .env file from .env.example'));
|
||||
console.log(chalk.yellow('⚠️ Please edit the .env file and configure your DATABASE_URL before running Prisma commands'));
|
||||
} catch (error) {
|
||||
envSpinner.fail('Failed to set up environment');
|
||||
console.log(chalk.red(`Error: ${error.message}`));
|
||||
@ -640,43 +562,37 @@ Security:
|
||||
yarnSpinner.succeed('Dependencies installed with Yarn');
|
||||
}
|
||||
|
||||
// Setup Prisma
|
||||
const prismaSpinner = ora('Setting up Prisma database...').start();
|
||||
try {
|
||||
// Check if Prisma is available and generate client
|
||||
if (fs.existsSync('prisma/schema.prisma')) {
|
||||
const prismaSuccess = runCommand('npx prisma generate', { stdio: 'pipe' });
|
||||
if (prismaSuccess) {
|
||||
prismaSpinner.succeed('Prisma database configured');
|
||||
} else {
|
||||
prismaSpinner.warn('Prisma setup incomplete - configure manually if needed');
|
||||
}
|
||||
} else {
|
||||
prismaSpinner.warn('No Prisma schema found - skipping database setup');
|
||||
}
|
||||
} catch (error) {
|
||||
prismaSpinner.warn('Prisma setup skipped');
|
||||
}
|
||||
|
||||
// Display header again for consistency at the end
|
||||
displayHeader();
|
||||
|
||||
// Step 6: Success message and next steps
|
||||
const prismaNotes = isEnvConfigured() ?
|
||||
'' :
|
||||
chalk.yellow('\n⚠️ Important: Edit your .env file and configure your DATABASE_URL before running:\n') +
|
||||
chalk.gray(' npx prisma generate\n');
|
||||
|
||||
const nextSteps = setupAction === 'new' ? [
|
||||
` cd ${projectName}`,
|
||||
' git init # Initialize git repository',
|
||||
' yarn dev # Start development server',
|
||||
' yarn build # Build for production',
|
||||
' yarn start # Start production server'
|
||||
' git init # Initialize git repository',
|
||||
' # Edit your .env file with proper configuration',
|
||||
' npx prisma generate # Generate Prisma client after configuring DATABASE_URL',
|
||||
' yarn dev # Start development server',
|
||||
' yarn build # Build for production',
|
||||
' yarn start # Start production server'
|
||||
] : [
|
||||
' yarn dev # Start development server',
|
||||
' yarn build # Build for production',
|
||||
' yarn start # Start production server'
|
||||
' # Edit your .env file with proper configuration',
|
||||
' npx prisma generate # Generate Prisma client after configuring DATABASE_URL',
|
||||
' yarn dev # Start development server',
|
||||
' yarn build # Build for production',
|
||||
' yarn start # Start production server'
|
||||
];
|
||||
|
||||
console.log('\n' + boxen(
|
||||
chalk.green.bold('🎉 Project setup completed successfully!\n\n') +
|
||||
chalk.white(`Project: ${chalk.cyan.bold(projectName)}\n`) +
|
||||
chalk.white(`Type: ${chalk.yellow.bold(projectType)}\n`) +
|
||||
chalk.white(`Action: ${chalk.yellow.bold(setupAction === 'new' ? 'New Project' : 'Updated Existing')}\n`) +
|
||||
chalk.white(`Location: ${chalk.gray(process.cwd())}\n\n`) +
|
||||
chalk.white(`Location: ${chalk.gray(process.cwd())}\n`) +
|
||||
prismaNotes +
|
||||
chalk.white.bold('Next steps:\n') +
|
||||
nextSteps.map(step => chalk.gray(step)).join('\n'),
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "corradaf",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"description": "CLI tool to quickly set up CORRAD Application Framework projects",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
@ -19,12 +19,12 @@
|
||||
"template"
|
||||
],
|
||||
"dependencies": {
|
||||
"figlet": "^1.7.0",
|
||||
"ora": "^5.4.1",
|
||||
"inquirer": "^8.2.6",
|
||||
"chalk": "^4.1.2",
|
||||
"boxen": "^5.1.2",
|
||||
"gradient-string": "^2.0.2"
|
||||
"chalk": "^4.1.2",
|
||||
"figlet": "^1.8.1",
|
||||
"gradient-string": "^2.0.2",
|
||||
"inquirer": "^8.2.6",
|
||||
"ora": "^5.4.1"
|
||||
},
|
||||
"author": "Corrad Team",
|
||||
"license": "MIT",
|
||||
@ -36,4 +36,4 @@
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user