@foal/cli
Version:
CLI tool for FoalTS
209 lines (208 loc) • 9.86 kB
JavaScript
"use strict";
/**
* FoalTS
* Copyright(c) 2017-2025 Loïc Poullain
* Released under the MIT License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
// 3p
const safe_1 = require("colors/safe");
const commander_1 = require("commander");
// FoalTS
const services_1 = require("./services");
const commands_1 = require("./commands");
function displayError(...lines) {
console.error();
lines.forEach(line => console.error((0, safe_1.red)(line)));
console.error();
process.exitCode = 1;
}
// tslint:disable-next-line:no-var-requires
const pkg = require('../package.json');
commander_1.program
.version(pkg.version, '-v, --version');
commander_1.program
.command('createapp')
.argument('<name>', 'Name of the application')
.description('Create a new project.')
.option('-G, --no-git', 'Don\'t initialize a git repository')
.option('-I, --no-install', 'Don\'t autoinstall packages using yarn or npm (uses first available)')
.option('-m, --mongodb', 'Generate a new project using MongoDB instead of SQLite', false)
.option('-y, --yaml', 'Generate a new project using YAML configuration instead of JSON', false)
.action(async (name, options) => {
const fileSystem = new services_1.FileSystemService();
const logger = new services_1.LoggerService();
const generator = new services_1.Generator(fileSystem, logger);
const createAppCommandService = new commands_1.CreateAppCommandService(generator);
await createAppCommandService.run({
autoInstall: options.install,
initRepo: options.git,
mongodb: options.mongodb,
name,
yaml: options.yaml
});
});
commander_1.program
.command('createsecret')
.description('Create a 256-bit random secret encoded in base64.')
.action(async () => {
const cryptoService = new services_1.CryptoService();
const loggerService = new services_1.LoggerService();
const createSecretCommandService = new commands_1.CreateSecretCommandService(cryptoService, loggerService);
await createSecretCommandService.run();
});
commander_1.program
.command('run')
.argument('<name>', 'Name of the script to run')
.argument('[args...]', 'Script arguments (key=value format)')
.description('Run a shell script.')
.action(async (name) => {
const utilService = new services_1.UtilService();
const runScriptCommandService = new commands_1.RunScriptCommandService(utilService);
await runScriptCommandService.run(name, process.argv);
});
commander_1.program
.command('connect')
.argument('<framework>', 'Frontend framework to connect to')
.argument('<path>', 'Path to the frontend project')
.description('Configure your frontend to interact with your application.')
.addHelpText('after', `
Available frameworks:
- angular
- react
- vue
`)
.action(async (framework, path) => {
switch (framework) {
case 'angular':
const fileSystem = new services_1.FileSystemService();
const logger = new services_1.LoggerService();
const generator = new services_1.Generator(fileSystem, logger);
const connectAngularCommandService = new commands_1.ConnectAngularCommandService(generator);
connectAngularCommandService.run(path);
break;
case 'react':
const reactFileSystem = new services_1.FileSystemService();
const reactLogger = new services_1.LoggerService();
const reactGenerator = new services_1.Generator(reactFileSystem, reactLogger);
const connectReactCommandService = new commands_1.ConnectReactCommandService(reactGenerator);
connectReactCommandService.run(path);
break;
case 'vue':
const vueFileSystem = new services_1.FileSystemService();
const vueLogger = new services_1.LoggerService();
const vueGenerator = new services_1.Generator(vueFileSystem, vueLogger);
const connectVueCommandService = new commands_1.ConnectVueCommandService(vueGenerator);
connectVueCommandService.run(path);
break;
default:
displayError(`Unknown framework ${(0, safe_1.yellow)(framework)}. Please provide a valid one:`, '', ' - angular', ' - react', ' - vue');
}
});
const generateTypes = [
'controller', 'entity', 'rest-api', 'hook', 'script', 'service'
];
commander_1.program
.command('generate')
.argument('<type>', 'Type of the file to generate')
.argument('<name>', 'Name of the file to generate')
.description('Generate and/or modify files.')
.option('-r, --register', 'Register the controller into app.controller.ts (only available if type=controller|rest-api)', false)
.option('-a, --auth', 'Add an owner to the entities of the generated REST API (only available if type=rest-api)', false)
.alias('g')
.addHelpText('after', `
Available types:
${generateTypes.map(t => ` - ${t}`).join('\n')}
`)
.action(async (type, name, options) => {
try {
switch (type) {
case 'controller':
const controllerFileSystem = new services_1.FileSystemService();
const controllerLogger = new services_1.LoggerService();
const controllerGenerator = new services_1.Generator(controllerFileSystem, controllerLogger);
const createControllerCommandService = new commands_1.CreateControllerCommandService(controllerGenerator);
createControllerCommandService.run({ name, register: options.register });
break;
case 'entity':
const entityFileSystem = new services_1.FileSystemService();
const entityLogger = new services_1.LoggerService();
const entityGenerator = new services_1.Generator(entityFileSystem, entityLogger);
const createEntityCommandService = new commands_1.CreateEntityCommandService(entityGenerator);
createEntityCommandService.run({ name });
break;
case 'rest-api':
const restApiFileSystem = new services_1.FileSystemService();
const restApiLogger = new services_1.LoggerService();
const restApiGenerator = new services_1.Generator(restApiFileSystem, restApiLogger);
const createRestApiCommandService = new commands_1.CreateRestApiCommandService(restApiGenerator);
createRestApiCommandService.run({ name, register: options.register, auth: options.auth });
break;
case 'hook':
const hookFileSystem = new services_1.FileSystemService();
const hookLogger = new services_1.LoggerService();
const hookGenerator = new services_1.Generator(hookFileSystem, hookLogger);
const createHookCommandService = new commands_1.CreateHookCommandService(hookGenerator);
createHookCommandService.run({ name });
break;
case 'script':
const scriptFileSystem = new services_1.FileSystemService();
const scriptLogger = new services_1.LoggerService();
const scriptGenerator = new services_1.Generator(scriptFileSystem, scriptLogger);
const createScriptCommandService = new commands_1.CreateScriptCommandService(scriptGenerator);
createScriptCommandService.run({ name });
break;
case 'service':
const serviceFileSystem = new services_1.FileSystemService();
const serviceLogger = new services_1.LoggerService();
const serviceGenerator = new services_1.Generator(serviceFileSystem, serviceLogger);
const createServiceCommandService = new commands_1.CreateServiceCommandService(serviceGenerator);
createServiceCommandService.run({ name });
break;
default:
displayError(`Unknown type ${(0, safe_1.yellow)(type)}. Please provide a valid one:`, '', ...generateTypes.map(t => ` - ${t}`));
}
}
catch (error) {
if (error instanceof services_1.ClientError) {
displayError(error.message);
return;
}
throw error;
}
});
commander_1.program
.command('rmdir')
.argument('<name>', 'Name of the directory to remove')
.description('Remove a directory and all its contents, including any subdirectories and files.')
.action(async (name) => {
try {
const rmdirCommandService = new commands_1.RmdirCommandService();
await rmdirCommandService.run(name);
}
catch (error) {
if (error.code === 'ENOTDIR') {
displayError(error.message);
return;
}
throw error;
}
});
commander_1.program
.command('upgrade')
.argument('[version]', 'Name of the specific version to upgrade to')
.description('Upgrade the project to the latest version of FoalTS. If a version is provided, upgrade to that version.')
.option('-I, --no-install', 'Don\'t autoinstall packages using yarn or npm (uses first available)')
.action(async (version, options) => {
const upgradeFileSystem = new services_1.FileSystemService();
const upgradeLogger = new services_1.LoggerService();
const upgradeGenerator = new services_1.Generator(upgradeFileSystem, upgradeLogger);
const upgradeCommandService = new commands_1.UpgradeCommandService(upgradeGenerator);
await upgradeCommandService.run({ version, autoInstall: options.install });
});
commander_1.program
.on('command:*', (commands) => {
commander_1.program.outputHelp();
displayError(`Unknown command ${(0, safe_1.yellow)(commands[0])}.`);
});
commander_1.program.parse(process.argv);