kira-crud
Version:
Intelligent CRUD Generator for Laravel and Angular
458 lines (397 loc) • 13.3 kB
JavaScript
/**
* Project Manager
* Manage Kira projects and their configuration
*/
const chalk = require('chalk');
const inquirer = require('inquirer');
const ora = require('ora');
const path = require('path');
const projectConfig = require('./project-config');
/**
* Display a styled section header
* @param {string} title - The section title
*/
function displaySectionHeader(title) {
console.log(
"\n" +
chalk.bold.blue(
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
)
);
console.log(chalk.bold.blue("✨ ") + chalk.bold.white(title));
console.log(
chalk.bold.blue(
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
) + "\n"
);
}
/**
* Configure a new project
* @returns {Promise<void>}
*/
async function configureNewProject() {
console.log(chalk.blue('\nProject Configuration'));
console.log(chalk.blue('====================='));
// Detect Laravel and Angular projects
const spinner = ora('Scanning for Laravel and Angular projects...').start();
const detectedProjects = await projectConfig.detectProjects(process.cwd());
spinner.succeed('Scan complete');
console.log(`${chalk.green('✓')} Found ${detectedProjects.laravel.length} Laravel projects`);
console.log(`${chalk.green('✓')} Found ${detectedProjects.angular.length} Angular projects`);
// Load existing configuration
const config = await projectConfig.loadConfig();
// Check if projects were detected
if (detectedProjects.laravel.length === 0 && detectedProjects.angular.length === 0) {
console.log(chalk.yellow('\nNo Laravel or Angular projects detected in the current directory.'));
console.log('You will need to provide the paths manually.');
// Call the configuration function
await projectConfig.configureProject(config);
return;
}
// If projects were detected, offer to use them
console.log('\nDetected projects:');
if (detectedProjects.laravel.length > 0) {
console.log(chalk.blue('\nLaravel projects:'));
detectedProjects.laravel.forEach((project, index) => {
console.log(` ${index + 1}. ${chalk.green(project)}`);
});
}
if (detectedProjects.angular.length > 0) {
console.log(chalk.blue('\nAngular projects:'));
detectedProjects.angular.forEach((project, index) => {
console.log(` ${index + 1}. ${chalk.green(project)}`);
});
}
// Ask if user wants to use detected projects
const { useDetected } = await inquirer.prompt([
{
type: 'confirm',
name: 'useDetected',
message: 'Would you like to use one of the detected projects?',
default: true
}
]);
if (useDetected) {
// Choose Laravel project
let laravelPath = '';
if (detectedProjects.laravel.length === 1) {
laravelPath = detectedProjects.laravel[0];
console.log(chalk.green(`Using Laravel project at: ${laravelPath}`));
} else if (detectedProjects.laravel.length > 1) {
const { selectedLaravel } = await inquirer.prompt([
{
type: 'list',
name: 'selectedLaravel',
message: 'Select a Laravel project:',
choices: detectedProjects.laravel.map((project, index) => ({
name: `${index + 1}. ${project}`,
value: project
}))
}
]);
laravelPath = selectedLaravel;
} else {
// No Laravel projects detected
const { manualLaravel } = await inquirer.prompt([
{
type: 'input',
name: 'manualLaravel',
message: 'Enter the path to your Laravel project:',
validate: async (input) => {
const fullPath = path.resolve(input);
if (await projectConfig.isLaravelProject(fullPath)) {
return true;
}
return 'Path does not contain a valid Laravel project';
}
}
]);
laravelPath = path.resolve(manualLaravel);
}
// Choose Angular project
let angularPath = '';
if (detectedProjects.angular.length === 1) {
angularPath = detectedProjects.angular[0];
console.log(chalk.green(`Using Angular project at: ${angularPath}`));
} else if (detectedProjects.angular.length > 1) {
const { selectedAngular } = await inquirer.prompt([
{
type: 'list',
name: 'selectedAngular',
message: 'Select an Angular project:',
choices: detectedProjects.angular.map((project, index) => ({
name: `${index + 1}. ${project}`,
value: project
}))
}
]);
angularPath = selectedAngular;
} else {
// No Angular projects detected
const { manualAngular } = await inquirer.prompt([
{
type: 'input',
name: 'manualAngular',
message: 'Enter the path to your Angular project:',
validate: async (input) => {
const fullPath = path.resolve(input);
if (await projectConfig.isAngularProject(fullPath)) {
return true;
}
return 'Path does not contain a valid Angular project';
}
}
]);
angularPath = path.resolve(manualAngular);
}
// Ask for project name
const { projectName } = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Enter a name for this project:',
default: path.basename(process.cwd()),
validate: (input) => input.trim() !== '' ? true : 'Project name is required'
}
]);
// Ask for default settings path
const { settingsPath } = await inquirer.prompt([
{
type: 'input',
name: 'settingsPath',
message: 'Enter the default path for settings components (relative to Angular src):',
default: 'app/pages/admin/settings'
}
]);
// Update configuration
config.projects[projectName] = {
laravel: {
path: laravelPath
},
angular: {
path: angularPath,
settingsPath
},
createdAt: new Date().toISOString()
};
// Set as default if first project
if (!config.defaultProject) {
config.defaultProject = projectName;
} else {
// Ask if it should be the default
const { makeDefault } = await inquirer.prompt([
{
type: 'confirm',
name: 'makeDefault',
message: 'Set this as the default project?',
default: false
}
]);
if (makeDefault) {
config.defaultProject = projectName;
}
}
// Save configuration
await projectConfig.saveConfig(config);
console.log(chalk.green(`\nProject '${projectName}' configured successfully!`));
} else {
// Manual configuration
await projectConfig.configureProject(config);
}
}
/**
* Switch active project
* @returns {Promise<void>}
*/
async function switchProject() {
// Load existing configuration
const config = await projectConfig.loadConfig();
// Get list of projects
const projects = Object.keys(config.projects);
if (projects.length === 0) {
console.log(chalk.yellow('\nNo projects configured yet.'));
await configureNewProject();
return;
}
// Display project list
console.log(chalk.blue('\nAvailable Projects:'));
const projectChoices = projects.map(project => ({
name: `${project}${project === config.defaultProject ? ' (default)' : ''}`,
value: project
}));
projectChoices.push({
name: 'Add a new project',
value: 'new'
});
// Ask user to select a project
const { selectedProject } = await inquirer.prompt([
{
type: 'list',
name: 'selectedProject',
message: 'Select a project:',
choices: projectChoices
}
]);
if (selectedProject === 'new') {
await configureNewProject();
return;
}
// Ask if it should be the default
const { makeDefault } = await inquirer.prompt([
{
type: 'confirm',
name: 'makeDefault',
message: 'Set this as the default project?',
default: selectedProject !== config.defaultProject
}
]);
if (makeDefault) {
config.defaultProject = selectedProject;
await projectConfig.saveConfig(config);
console.log(chalk.green(`\nProject '${selectedProject}' set as default.`));
}
}
/**
* Display project information
* @returns {Promise<void>}
*/
async function showProjectInfo() {
try {
// Get active project
const project = await projectConfig.getActiveProject();
console.log(chalk.blue('\nActive Project Information:'));
console.log(chalk.blue('==========================='));
console.log(`${chalk.bold('Name:')} ${project.name}`);
console.log(`${chalk.bold('Laravel Path:')} ${project.laravel.path}`);
console.log(`${chalk.bold('Angular Path:')} ${project.angular.path}`);
console.log(`${chalk.bold('Settings Path:')} ${project.angular.settingsPath}`);
console.log(`${chalk.bold('Created:')} ${new Date(project.createdAt).toLocaleString()}`);
// Verify paths are valid
const laravelValid = await projectConfig.isLaravelProject(project.laravel.path);
const angularValid = await projectConfig.isAngularProject(project.angular.path);
console.log(`\n${chalk.bold('Status:')}`);
console.log(`Laravel Project: ${laravelValid ? chalk.green('Valid') : chalk.red('Invalid')}`);
console.log(`Angular Project: ${angularValid ? chalk.green('Valid') : chalk.red('Invalid')}`);
if (!laravelValid || !angularValid) {
console.log(chalk.yellow('\nOne or more project paths are invalid. You may need to reconfigure this project.'));
}
} catch (error) {
console.log(chalk.red(`\nError: ${error.message}`));
}
}
/**
* Remove a project
* @returns {Promise<void>}
*/
async function removeProject() {
// Load existing configuration
const config = await projectConfig.loadConfig();
// Get list of projects
const projects = Object.keys(config.projects);
if (projects.length === 0) {
console.log(chalk.yellow('\nNo projects configured yet.'));
return;
}
// Display project list
console.log(chalk.blue('\nAvailable Projects:'));
const projectChoices = projects.map(project => ({
name: `${project}${project === config.defaultProject ? ' (default)' : ''}`,
value: project
}));
projectChoices.push({
name: 'Cancel',
value: 'cancel'
});
// Ask user to select a project
const { selectedProject } = await inquirer.prompt([
{
type: 'list',
name: 'selectedProject',
message: 'Select a project to remove:',
choices: projectChoices
}
]);
if (selectedProject === 'cancel') {
return;
}
// Confirm deletion
const { confirmDelete } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirmDelete',
message: `Are you sure you want to remove project '${selectedProject}'?`,
default: false
}
]);
if (!confirmDelete) {
console.log(chalk.yellow('\nProject removal cancelled.'));
return;
}
// Remove project
delete config.projects[selectedProject];
// Update default project if necessary
if (config.defaultProject === selectedProject) {
const remainingProjects = Object.keys(config.projects);
if (remainingProjects.length > 0) {
config.defaultProject = remainingProjects[0];
console.log(chalk.yellow(`\nDefault project set to '${config.defaultProject}'.`));
} else {
config.defaultProject = null;
}
}
// Save configuration
await projectConfig.saveConfig(config);
console.log(chalk.green(`\nProject '${selectedProject}' removed successfully.`));
}
/**
* Show project settings menu
* @returns {Promise<void>}
*/
async function projectSettingsMenu() {
displaySectionHeader('Project Settings');
const { action } = await inquirer.prompt([
{
type: 'list',
name: 'action',
message: 'Select an action:',
choices: [
{ name: 'Configure a new project', value: 'new' },
{ name: 'Switch active project', value: 'switch' },
{ name: 'Show active project information', value: 'info' },
{ name: 'Remove a project', value: 'remove' },
{ name: 'Back to main menu', value: 'back' }
]
}
]);
switch (action) {
case 'new':
await configureNewProject();
break;
case 'switch':
await switchProject();
break;
case 'info':
await showProjectInfo();
break;
case 'remove':
await removeProject();
break;
}
if (action !== 'back') {
// Press any key to continue
await inquirer.prompt([
{
type: 'input',
name: 'continue',
message: 'Press Enter to continue...'
}
]);
}
}
module.exports = {
configureNewProject,
switchProject,
showProjectInfo,
removeProject,
projectSettingsMenu
};