|
| 1 | +const { Command } = require('commander'); |
| 2 | +const inquirer = require('inquirer'); |
| 3 | +const path = require('path'); |
| 4 | +const fs = require('fs'); |
| 5 | +const { copyDir, writeProjectPackageJson, applyEstreuvOverlay, runCreateEstreui } = require('../utils'); |
| 6 | + |
| 7 | +const program = new Command('init'); |
| 8 | + |
| 9 | +program |
| 10 | + .description('Initialize a new EstreUV.js project') |
| 11 | + .argument('[project-name]', 'Project name') |
| 12 | + .option('--pure', 'Pure EstreUV app (no EstreUI)') |
| 13 | + .option('--pair', 'EstreUI + EstreUV pair app') |
| 14 | + .option('--no-install', 'Skip npm install') |
| 15 | + .action(async (projectName, options) => { |
| 16 | + // 1. Project name |
| 17 | + let { name } = { name: projectName }; |
| 18 | + if (!name) { |
| 19 | + ({ name } = await inquirer.prompt([{ |
| 20 | + type: 'input', name: 'name', |
| 21 | + message: 'Project name:', default: 'my-estreuv-app' |
| 22 | + }])); |
| 23 | + } |
| 24 | + |
| 25 | + // 2. Mode |
| 26 | + let mode = options.pure ? 'pure' : options.pair ? 'pair' : null; |
| 27 | + if (!mode) { |
| 28 | + ({ mode } = await inquirer.prompt([{ |
| 29 | + type: 'list', name: 'mode', message: 'Project type:', |
| 30 | + choices: [ |
| 31 | + { name: 'Pure EstreUV app (Lit micro-Rimwork, no build)', value: 'pure' }, |
| 32 | + { name: 'EstreUI + EstreUV pair app (EstreUI shell + EstreUV tiles)', value: 'pair' } |
| 33 | + ], |
| 34 | + default: 'pure' |
| 35 | + }])); |
| 36 | + } |
| 37 | + |
| 38 | + const projectPath = path.resolve(process.cwd(), name === '.' ? '' : name); |
| 39 | + const pkgName = name === '.' ? path.basename(process.cwd()) : name; |
| 40 | + |
| 41 | + try { |
| 42 | + if (mode === 'pure') { |
| 43 | + await scaffoldPure(projectPath, pkgName, options.install); |
| 44 | + } else { |
| 45 | + await scaffoldPair(projectPath, pkgName, name, options.install); |
| 46 | + } |
| 47 | + console.log('\n✓ Project initialized.'); |
| 48 | + console.log(`\n cd ${name}\n npm run dev\n`); |
| 49 | + } catch (error) { |
| 50 | + console.error('Error initializing project:', error); |
| 51 | + process.exit(1); |
| 52 | + } |
| 53 | + }); |
| 54 | + |
| 55 | +async function scaffoldPure(projectPath, pkgName, install) { |
| 56 | + console.log(`Initializing pure EstreUV app in ${projectPath}...`); |
| 57 | + fs.mkdirSync(projectPath, { recursive: true }); |
| 58 | + |
| 59 | + const templateDir = path.resolve(__dirname, '../../templates/pure'); |
| 60 | + await copyDir(templateDir, projectPath); |
| 61 | + console.log('✓ Copied template'); |
| 62 | + |
| 63 | + writeProjectPackageJson(projectPath, pkgName, { pair: false }); |
| 64 | + console.log('✓ Created package.json'); |
| 65 | + |
| 66 | + if (install) require('../utils').installDependencies(projectPath); |
| 67 | +} |
| 68 | + |
| 69 | +async function scaffoldPair(projectPath, pkgName, rawName, install) { |
| 70 | + console.log(`Initializing EstreUI + EstreUV pair app in ${projectPath}...`); |
| 71 | + |
| 72 | + // Delegate the EstreUI shell to create-estreui (max share — PM 008 R5). |
| 73 | + runCreateEstreui(rawName); |
| 74 | + |
| 75 | + if (!fs.existsSync(projectPath)) { |
| 76 | + throw new Error('create-estreui did not produce the project directory. Aborting overlay.'); |
| 77 | + } |
| 78 | + |
| 79 | + // Apply the EstreUV overlay on top of the EstreUI scaffold. |
| 80 | + const overlayDir = path.resolve(__dirname, '../../templates/pair-overlay'); |
| 81 | + applyEstreuvOverlay(projectPath, overlayDir); |
| 82 | + |
| 83 | + writeProjectPackageJson(projectPath, pkgName, { pair: true }); |
| 84 | + console.log('✓ Added estreuv / lit / @lit/context to package.json'); |
| 85 | + |
| 86 | + if (install) require('../utils').installDependencies(projectPath); |
| 87 | + console.log('✓ See ESTREUV-PAIR.md for the one manual page-handler step.'); |
| 88 | +} |
| 89 | + |
| 90 | +module.exports = program; |
0 commit comments