neura-cli-standalone
Version:
Command-line interface for the Neura programming language (standalone version)
334 lines (283 loc) • 11.6 kB
text/typescript
import { Command } from 'commander';
import * as fs from 'fs';
import * as path from 'path';
import * as chalk from 'chalk';
import * as child_process from 'child_process';
// Definimos una versión básica del núcleo de Neura para la CLI standalone
class StandaloneNeuraCore {
// Funciones básicas del lexer
static tokenize(code: string) {
return { tokens: code.split(/\s+/).filter(Boolean) };
}
// Función simple para compilar
static compile(code: string, target: string = 'typescript') {
console.log(chalk.blue(`Compilando código Neura a ${target}...`));
// Implementación básica
return `// Compiled from Neura to ${target}\n${code}`;
}
// Función simple para ejecutar
static execute(code: string) {
console.log(chalk.blue(`Ejecutando código Neura...`));
// Implementación básica
console.log(`Simulando ejecución del código: ${code.substring(0, 50)}...`);
return { success: true, output: "Ejecución simulada completada." };
}
}
// Definimos características AI-First básicas
class StandaloneNeuraAI {
// Implementación básica de watch
static watchFile(filePath: string) {
console.log(chalk.blue(`Iniciando modo watch para ${filePath}...`));
const fullPath = path.resolve(filePath);
if (!fs.existsSync(fullPath)) {
console.error(chalk.red(`Error: El archivo ${filePath} no existe.`));
return;
}
console.log(chalk.green(`Observando cambios en ${filePath}...`));
console.log('Presiona Ctrl+C para detener.');
fs.watch(fullPath, (eventType) => {
if (eventType === 'change') {
const timestamp = new Date().toLocaleTimeString();
console.log(chalk.green(`\n[${timestamp}] Cambios detectados en ${filePath}.`));
// Leemos el archivo
try {
const content = fs.readFileSync(fullPath, 'utf-8');
console.log(chalk.yellow(`Recargando módulo...`));
// Simulamos la recarga (en una implementación real recargaríamos el módulo)
console.log(chalk.green(`Módulo recargado correctamente.`));
} catch (error) {
console.error(chalk.red(`Error al leer el archivo: ${error}`));
}
}
});
}
// Simulación básica del gestor de paquetes
static packageManager(command: string, packageName?: string) {
switch (command) {
case 'add':
if (!packageName) {
console.error(chalk.red('Error: Debes especificar un nombre de paquete.'));
return;
}
console.log(chalk.green(`Simulando instalación del paquete ${packageName}...`));
break;
case 'remove':
if (!packageName) {
console.error(chalk.red('Error: Debes especificar un nombre de paquete.'));
return;
}
console.log(chalk.green(`Simulando desinstalación del paquete ${packageName}...`));
break;
case 'list':
console.log(chalk.yellow('Paquetes instalados (simulación):'));
console.log('- core@0.1.0-alpha.1');
console.log('- ai-features@0.1.0-alpha.1');
break;
case 'update':
console.log(chalk.green('Simulando actualización de todos los paquetes...'));
break;
default:
console.error(chalk.red(`Comando desconocido: ${command}`));
}
}
// Información sobre características AI-First
static showAIFeatures() {
console.log(chalk.blue.bold('\nNeura AI-First Features'));
console.log(chalk.blue('======================'));
console.log('\nNeura incluye características AI-First que aceleran el desarrollo:');
console.log('\n1. ' + chalk.green('@ai.optimize') + ' - Optimización de código con IA');
console.log(' Ejemplo: ' + chalk.yellow('@ai.optimize("reduce database calls")') + ' usecase GetOrders { ... }');
console.log('\n2. ' + chalk.green('@generate') + ' - Generación automática de código');
console.log(' Ejemplo: ' + chalk.yellow('@generate crud for entity User { ... }') + ' using persistence.postgres');
console.log('\n3. ' + chalk.green('scaffold') + ' - Estructuras de proyecto declarativas');
console.log(' Ejemplo: ' + chalk.yellow('scaffold api PaymentService { ... }'));
console.log('\n4. ' + chalk.green('macro') + ' - Plantillas parametrizables');
console.log(' Ejemplo: ' + chalk.yellow('macro RestEndpoint(path, method, usecase) { ... }'));
console.log('\nPara usar todas las características avanzadas, instala los paquetes completos:');
console.log(chalk.yellow('\nnpm install neura-core@alpha neura-ai-features@alpha'));
console.log('\nMás información: https://github.com/neura-lang/neura');
}
}
// Crear el asistente para instalación
function checkAndInstallDependencies() {
console.log(chalk.blue.bold('Neura CLI - Asistente de Instalación'));
console.log(chalk.blue('==============================='));
const packages = ['neura-core', 'neura-ai-features'];
let needsInstall = false;
packages.forEach(pkg => {
try {
require.resolve(pkg);
console.log(chalk.green(`✓ ${pkg} está instalado correctamente.`));
} catch (error) {
console.log(chalk.yellow(`✗ ${pkg} no está instalado.`));
needsInstall = true;
}
});
if (needsInstall) {
console.log(chalk.yellow('\nAlgunas dependencias no están instaladas. ¿Deseas instalarlas ahora? (s/n)'));
console.log('Para la experiencia completa de Neura, se recomienda instalar los paquetes completos.');
console.log('Nota: Esta versión standalone incluye funcionalidad básica que funciona sin dependencias.');
console.log('');
console.log('Para instalar manualmente las dependencias:');
console.log(chalk.green('npm install neura-core@alpha neura-ai-features@alpha'));
}
return !needsInstall;
}
// Definir el CLI principal
const program = new Command();
program
.name('neura')
.description('Neura programming language CLI (standalone version)')
.version('0.1.0-alpha.3');
program
.command('compile <file>')
.description('Compile a Neura file to the target language')
.option('-t, --target <target>', 'Target language (typescript, javascript, wasm)', 'typescript')
.option('-o, --output <o>', 'Output file')
.option('-s, --source-maps', 'Generate source maps')
.action((file: string, options: any) => {
console.log(`Compilando ${file} a ${options.target}...`);
try {
// Intentamos leer el archivo
const content = fs.readFileSync(file, 'utf-8');
const compiled = StandaloneNeuraCore.compile(content, options.target);
if (options.output) {
fs.writeFileSync(options.output, compiled);
console.log(chalk.green(`✓ Compilación guardada en ${options.output}`));
} else {
console.log(chalk.yellow('Resultado de la compilación:'));
console.log(compiled);
}
} catch (error) {
console.error(chalk.red(`Error al compilar: ${error}`));
}
});
program
.command('run <file>')
.description('Run a Neura file')
.action((file: string) => {
console.log(`Ejecutando ${file}...`);
try {
// Intentamos leer el archivo
const content = fs.readFileSync(file, 'utf-8');
const result = StandaloneNeuraCore.execute(content);
if (result.success) {
console.log(chalk.green(`✓ Ejecución completada.`));
console.log(result.output);
} else {
console.error(chalk.red(`Error durante la ejecución.`));
}
} catch (error) {
console.error(chalk.red(`Error al ejecutar: ${error}`));
}
});
program
.command('watch <file>')
.description('Watch a Neura file for changes and reload automatically')
.action((file: string) => {
// Usamos la implementación standalone
StandaloneNeuraAI.watchFile(file);
});
program
.command('pkg [command] [package]')
.description('Manage Neura packages')
.action((command: string = 'list', packageName?: string) => {
// Usamos la implementación standalone
StandaloneNeuraAI.packageManager(command, packageName);
});
program
.command('ai')
.description('Show information about Neura AI-First features')
.action(() => {
// Mostrar información sobre las características AI-First
StandaloneNeuraAI.showAIFeatures();
});
program
.command('setup')
.description('Setup Neura packages and dependencies')
.action(() => {
checkAndInstallDependencies();
});
// Comando para crear un nuevo proyecto
program
.command('new <projectName>')
.description('Create a new Neura project')
.option('-t, --template <template>', 'Project template (api, web, cli)', 'api')
.action((projectName: string, options: any) => {
console.log(chalk.blue(`Creando nuevo proyecto Neura: ${projectName}`));
try {
// Crear la estructura básica del proyecto
const projectDir = path.resolve(projectName);
// Verificar si el directorio ya existe
if (fs.existsSync(projectDir)) {
console.error(chalk.red(`Error: El directorio ${projectName} ya existe.`));
return;
}
// Crear el directorio del proyecto
fs.mkdirSync(projectDir);
// Crear la estructura según el template
const template = options.template || 'api';
console.log(chalk.yellow(`Usando template: ${template}`));
// Crear archivos básicos
fs.writeFileSync(
path.join(projectDir, 'main.neura'),
`// Neura ${template.toUpperCase()} Project
module ${projectName} {
// Main module
usecase HelloWorld {
execute() {
return "Hello from Neura!";
}
}
}
`);
fs.writeFileSync(
path.join(projectDir, 'package.json'),
JSON.stringify({
name: projectName,
version: '0.1.0',
description: `A Neura ${template} project`,
dependencies: {
"neura-core": "0.1.0-alpha.1",
"neura-ai-features": "0.1.0-alpha.1"
}
}, null, 2)
);
fs.writeFileSync(
path.join(projectDir, 'README.md'),
`# ${projectName}
A Neura ${template} project.
## Getting Started
\`\`\`bash
# Install dependencies
npm install
# Run the project
neura run main.neura
\`\`\`
`);
console.log(chalk.green(`✓ Proyecto ${projectName} creado exitosamente.`));
console.log(`Para comenzar:`);
console.log(chalk.yellow(`cd ${projectName}`));
console.log(chalk.yellow(`npm install`));
console.log(chalk.yellow(`neura run main.neura`));
} catch (error) {
console.error(chalk.red(`Error al crear el proyecto: ${error}`));
}
});
// Verificar si el usuario está ejecutando solo "neura"
if (process.argv.length <= 2) {
console.log(chalk.blue.bold('\nNeura Programming Language CLI (Standalone)'));
console.log(chalk.blue('======================================'));
console.log('\nUso básico:');
console.log(' neura compile <archivo> Compilar un archivo Neura');
console.log(' neura run <archivo> Ejecutar un archivo Neura');
console.log(' neura watch <archivo> Observar cambios en un archivo');
console.log(' neura new <nombre> Crear un nuevo proyecto Neura');
console.log(' neura pkg Gestionar paquetes');
console.log(' neura ai Ver información sobre AI-First');
console.log(' neura setup Configurar dependencias');
console.log('\nPara ver más opciones:');
console.log(' neura --help');
}
program.parse(process.argv);