UNPKG

@mondaycom/apps-cli

Version:

A cli tool to manage apps (and monday-code projects) in monday.com

113 lines (112 loc) 4.99 kB
import * as path from 'node:path'; import { Args, Flags } from '@oclif/core'; import { Listr } from 'listr2'; import { BaseCommand } from '../../commands-base/base-command.js'; import { PROJECT_TEMPLATES } from '../../consts/scaffold.js'; import { PromptService } from '../../services/prompt-service.js'; import { downloadTemplateTask, editEnvFileTask, installDependenciesTask, openSetupFileTask, runProjectTask, validateDestination, } from '../../services/scaffold-service.js'; import logger from '../../utils/logger.js'; export default class AppScaffold extends BaseCommand { static description = 'Scaffold a monday app from a template, install dependencies, and start the project automatically.'; static examples = [ '<%= config.bin %> <%= command.id %>', '<%= config.bin %> <%= command.id %> ./my-app quickstart-react', '<%= config.bin %> <%= command.id %> ./my-app slack-node --signingSecret YOUR_SECRET', '<%= config.bin %> <%= command.id %> ./my-app word-cloud --command dev', ]; static args = { destination: Args.string({ description: 'The destination directory for the scaffolded project', required: false, }), project: Args.string({ description: 'The name of the template project to scaffold', required: false, }), }; static flags = AppScaffold.serializeFlags({ signingSecret: Flags.string({ char: 's', description: 'monday signing secret (for .env configuration)', required: false, }), command: Flags.string({ char: 'c', description: 'npm script command to run after installation (default: start)', required: false, default: 'start', }), }); DEBUG_TAG = 'app_scaffold'; async run() { try { const { args, flags } = await this.parse(AppScaffold); // Get project let project; if (args.project) { const foundProject = PROJECT_TEMPLATES.find(p => p.name === args.project); if (!foundProject) { throw new Error(`Project "${args.project}" not found. Available projects: ${PROJECT_TEMPLATES.map(p => p.name).join(', ')}`); } project = foundProject; } else { const projectName = await PromptService.promptList('Which project do you want to start from?', PROJECT_TEMPLATES.map(p => p.name)); project = PROJECT_TEMPLATES.find(p => p.name === projectName); } // Get destination let destination; if (args.destination) { destination = path.resolve(args.destination); } else { const destInput = await PromptService.promptInput('Choose destination folder', false); destination = path.resolve(destInput || './'); } // Validate destination await validateDestination(destination); // Get signing secret if needed let signingSecret = flags.signingSecret; if (!signingSecret && project.isWithSigningSecret) { signingSecret = await PromptService.promptInput('Enter signing secret (optional, press Enter to skip)', false, true); } const projectPath = path.join(destination, project.name); // Use command flag (defaults to 'start') const startCommand = flags.command; this.preparePrintCommand(this, flags, args); const context = { project, destination, signingSecret, projectPath, startCommand, }; await this.executeScaffold(context); } catch (error) { logger.debug(error, this.DEBUG_TAG); throw error; } } async executeScaffold(ctx) { const tasks = new Listr([ { title: 'Downloading template', task: downloadTemplateTask }, { title: 'Configuring environment', task: editEnvFileTask }, { title: 'Opening setup documentation', task: openSetupFileTask, enabled: () => Boolean(ctx.project.openSetupMd), }, { title: 'Installing dependencies', task: installDependenciesTask }, { title: 'Starting project', task: runProjectTask }, ]); await tasks.run(ctx); logger.success(`Project is running at: ${ctx.projectPath}\n` + `To run manually later:\n` + ` cd ${ctx.project.name}\n` + ` npm run ${ctx.startCommand}\n\n` + `Press Enter to provide your access token and view the tunnel URL\n`); // Keep scaffold process alive so dev server continues running await new Promise(() => { }); } }