@exiloncms/cli 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -166,6 +166,11 @@ php "${composerPharPath}" "$@"
|
|
|
166
166
|
process.env.PATH = `${localBin}:${process.env.PATH}`;
|
|
167
167
|
}
|
|
168
168
|
spinner.succeed("Composer install\xE9");
|
|
169
|
+
if (isWindows) {
|
|
170
|
+
console.log(chalk.yellow('\n\u26A0\uFE0F NOTE: Composer a \xE9t\xE9 install\xE9 mais pour utiliser la commande "composer"'));
|
|
171
|
+
console.log(chalk.yellow("dans tout votre syst\xE8me, vous devez red\xE9marrer ce terminal.\n"));
|
|
172
|
+
console.log(chalk.gray("Pour ce projet, le CLI utilisera le chemin complet automatiquement.\n"));
|
|
173
|
+
}
|
|
169
174
|
} catch (error) {
|
|
170
175
|
spinner.fail("Erreur lors de l'installation de Composer");
|
|
171
176
|
console.error(error);
|
|
@@ -572,13 +577,32 @@ async function installDependencies(config, targetDir, spinner) {
|
|
|
572
577
|
spinner.info("Installation des d\xE9pendances skip\xE9e");
|
|
573
578
|
return;
|
|
574
579
|
}
|
|
580
|
+
const isWindows = process.platform === "win32";
|
|
581
|
+
let composerCommand = "composer";
|
|
582
|
+
let needsCleanup = false;
|
|
583
|
+
if (isWindows) {
|
|
584
|
+
const composerBat = path.join(process.env.LOCALAPPDATA || "", "Composer", "composer.bat");
|
|
585
|
+
if (await fs.pathExists(composerBat)) {
|
|
586
|
+
const tempComposer = path.join(targetDir, "composer.bat");
|
|
587
|
+
await fs.copy(composerBat, tempComposer);
|
|
588
|
+
composerCommand = `"${tempComposer}"`;
|
|
589
|
+
needsCleanup = true;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
575
592
|
spinner.start("Installation des d\xE9pendances PHP (Composer)...");
|
|
576
593
|
try {
|
|
577
|
-
await execaCommand(
|
|
594
|
+
await execaCommand(`${composerCommand} install --no-interaction --quiet`, { cwd: targetDir });
|
|
578
595
|
spinner.succeed("D\xE9pendances PHP install\xE9es");
|
|
579
596
|
} catch (error) {
|
|
580
597
|
spinner.fail("Erreur lors de l'installation Composer");
|
|
581
598
|
throw error;
|
|
599
|
+
} finally {
|
|
600
|
+
if (needsCleanup) {
|
|
601
|
+
const tempComposer = path.join(targetDir, "composer.bat");
|
|
602
|
+
if (await fs.pathExists(tempComposer)) {
|
|
603
|
+
await fs.remove(tempComposer);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
582
606
|
}
|
|
583
607
|
spinner.start("Installation des d\xE9pendances Node.js...");
|
|
584
608
|
try {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport prompts from 'prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { execaCommand } from 'execa';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport degit from 'degit';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst packageJson = await fs.readJson(path.join(__dirname, '../package.json'));\n\n// ASCII Art Banner\nconst banner = `\n${chalk.cyan('╔═══════════════════════════════════════════════════════════╗')}\n${chalk.cyan('║')} ${chalk.bold.white('ExilonCMS CLI')} ${chalk.gray(`v${packageJson.version}`)} ${' '.repeat(36)} ${chalk.cyan('║')}\n${chalk.cyan('║')} ${chalk.white('Create modern ExilonCMS projects with ease')} ${' '.repeat(24)} ${chalk.cyan('║')}\n${chalk.cyan('╚═══════════════════════════════════════════════════════════╝')}\n`;\n\n// Marketplace Registry URL\nconst MARKETPLACE_REGISTRY_URL = 'https://raw.githubusercontent.com/Exilon-Studios/ExilonCMS-marketplace/main/registry.json';\n\n// Marketplace Registry Types\ninterface MarketplacePlugin {\n id: number;\n extension_id: string;\n name: string;\n description: string;\n version: string;\n author: string;\n url: string;\n repo_url?: string;\n hash: string;\n}\n\ninterface MarketplaceTheme {\n id: number;\n extension_id: string;\n name: string;\n description: string;\n version: string;\n author: string;\n url: string;\n hash: string;\n}\n\ninterface MarketplaceRegistry {\n plugins: MarketplacePlugin[];\n themes: MarketplaceTheme[];\n games: any[];\n alerts: any[];\n}\n\n// Fetch marketplace registry\nasync function fetchMarketplaceRegistry(): Promise<MarketplaceRegistry | null> {\n const spinner = ora();\n try {\n spinner.start('Récupération du marketplace...');\n const response = await fetch(MARKETPLACE_REGISTRY_URL);\n if (!response.ok) {\n spinner.warn('Impossible de récupérer le marketplace, utilisation des options par défaut');\n return null;\n }\n const registry: MarketplaceRegistry = await response.json();\n spinner.succeed(`Marketplace connecté - ${registry.plugins.length} plugins, ${registry.themes.length} thèmes`);\n return registry;\n } catch (error) {\n spinner.warn('Impossible de connecter au marketplace, utilisation des options par défaut');\n return null;\n }\n}\n\n// Database options\nconst databaseOptions = [\n { title: 'SQLite (Recommandé - Pas de configuration)', value: 'sqlite', description: 'Base de données fichier, aucune configuration requise' },\n { title: 'PostgreSQL', value: 'postgresql', description: 'Base de données serveur, performante et robuste' },\n { title: 'MySQL', value: 'mysql', description: 'Base de données serveur, populaire et répandue' },\n];\n\ninterface ProjectConfig {\n projectName: string;\n database: string;\n theme: string;\n plugins: string[];\n siteName: string;\n adminName: string;\n adminEmail: string;\n adminPassword: string;\n installDeps: boolean;\n runMigrations: boolean;\n}\n\nfunction validateProjectName(name: string): boolean {\n return /^[a-zA-Z0-9_-]+$/.test(name);\n}\n\n// Check if a command exists on the system\nasync function checkCommandExists(command: string): Promise<boolean> {\n try {\n const isWindows = process.platform === 'win32';\n const checkCmd = isWindows ? `where ${command}` : `which ${command}`;\n await execaCommand(checkCmd, { stdio: 'pipe' });\n return true;\n } catch {\n // On Windows, also check standard installation paths\n if (process.platform === 'win32') {\n try {\n const standardPaths: Record<string, string[]> = {\n 'composer': [\n path.join(process.env.LOCALAPPDATA || '', 'Composer', 'composer.bat'),\n path.join(process.env.LOCALAPPDATA || '', 'Composer', 'composer.phar'),\n 'C:\\\\ProgramData\\\\ComposerSetup\\\\bin\\\\composer.bat',\n 'C:\\\\Program Files\\\\Composer\\\\composer.bat',\n ],\n 'php': [\n 'C:\\\\php\\\\php.exe',\n 'C:\\\\Program Files\\\\PHP\\\\php.exe',\n path.join(process.env.LOCALAPPDATA || '', 'Programs', 'PHP', 'php.exe'),\n ],\n 'node': [\n 'C:\\\\Program Files\\\\nodejs\\\\node.exe',\n path.join(process.env.APPDATA || '', 'npm', 'node.exe'),\n ],\n 'npm': [\n 'C:\\\\Program Files\\\\nodejs\\\\npm.cmd',\n 'C:\\\\Program Files\\\\nodejs\\\\npm',\n ],\n };\n\n const paths = standardPaths[command] || [];\n for (const filePath of paths) {\n if (await fs.pathExists(filePath)) {\n return true;\n }\n }\n } catch {\n return false;\n }\n }\n return false;\n }\n}\n\n// Install Composer automatically using official method\nasync function installComposer(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de Composer...');\n try {\n const composerDir = path.join(process.env.LOCALAPPDATA || '', 'Composer');\n await fs.ensureDir(composerDir);\n\n // Download composer.phar directly using Node.js (most reliable method)\n spinner.text = 'Téléchargement de Composer...';\n\n const composerPharPath = path.join(composerDir, 'composer.phar');\n\n try {\n // Download with proper redirect handling\n const response = await fetch('https://getcomposer.org/composer-stable.phar', {\n redirect: 'follow',\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n // Check if we got HTML instead of PHAR (common error)\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('text/html')) {\n throw new Error('Le serveur a retourné une page HTML au lieu du fichier PHAR');\n }\n\n const buffer = await response.arrayBuffer();\n const content = Buffer.from(buffer);\n\n // Verify it's a valid PHAR file (must start with __HALT_COMPILER();)\n const pharSignature = '__HALT_COMPILER';\n const contentStart = content.toString('utf8', 0, Math.min(100, content.length));\n if (!contentStart.includes(pharSignature)) {\n throw new Error('Le fichier téléchargé n\\'est pas un fichier PHAR valide');\n }\n\n await fs.writeFile(composerPharPath, content);\n spinner.succeed('Composer téléchargé');\n } catch (error) {\n throw new Error(`Impossible de télécharger Composer: ${(error as Error).message}`);\n }\n\n // Verify composer.phar was created\n if (!(await fs.pathExists(composerPharPath))) {\n throw new Error('composer.phar n\\'a pas été téléchargé correctement');\n }\n\n // Test that composer.phar works\n spinner.text = 'Vérification de Composer...';\n try {\n const { stdout } = await execaCommand(`php \"${composerPharPath}\" --version`, { stdio: 'pipe' });\n if (!stdout.includes('Composer')) {\n throw new Error('La commande php composer.phar n\\'a pas retourné \"Composer\"');\n }\n } catch (error) {\n throw new Error(`Le fichier composer.phar ne fonctionne pas: ${(error as Error).message}`);\n }\n\n // Create composer.bat wrapper on Windows\n const isWindows = process.platform === 'win32';\n if (isWindows) {\n const composerBat = path.join(composerDir, 'composer.bat');\n const batContent = `@ECHO OFF\\r\\nphp \"${composerPharPath}\" %*\\r\\n`;\n await fs.writeFile(composerBat, batContent);\n\n // Add to PATH (for current session and future sessions)\n try {\n await execaCommand(\n `powershell -Command \"[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path', 'User') + ';${composerDir}', 'User')\"`,\n { stdio: 'pipe' }\n );\n } catch {\n // Ignore PATH update errors\n }\n\n // Add to current session\n process.env.PATH = `${composerDir};${process.env.PATH}`;\n } else {\n // Linux/macOS: Create a wrapper script\n const composerWrapper = path.join(composerDir, 'composer');\n const wrapperContent = `#!/bin/bash\\nphp \"${composerPharPath}\" \"$@\"\\n`;\n await fs.writeFile(composerWrapper, wrapperContent);\n await execaCommand(`chmod +x \"${composerWrapper}\"`, { stdio: 'pipe' });\n\n // Add to PATH\n const localBin = path.join(process.env.HOME || '', '.local', 'bin');\n await fs.ensureDir(localBin);\n const composerBin = path.join(localBin, 'composer');\n await fs.copy(composerWrapper, composerBin);\n\n try {\n await execaCommand(\n `export PATH=\"${localBin}:$PATH\"`,\n { stdio: 'pipe' }\n );\n } catch {\n // Ignore\n }\n\n process.env.PATH = `${localBin}:${process.env.PATH}`;\n }\n\n spinner.succeed('Composer installé');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de Composer');\n console.error(error);\n throw error;\n }\n}\n\n// Install Node.js automatically\nasync function installNodejs(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de Node.js...');\n try {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Windows: Download and install Node.js LTS using winget if available, else download installer\n try {\n await execaCommand('winget install OpenJS.NodeJS.LTS', { stdio: 'inherit' });\n } catch {\n // Fallback: Download installer\n const installerPath = path.join(targetDir, 'nodejs-installer.msi');\n await execaCommand(\n `powershell -Command \"Invoke-WebRequest -Uri 'https://nodejs.org/dist/latest-v20.x/' -OutFile '${installerPath}'\"`,\n { stdio: 'inherit' }\n );\n spinner.info('Veuillez installer Node.js manuellement depuis: https://nodejs.org/');\n }\n } else {\n // Linux: Use NodeSource repository\n await execaCommand(\n 'curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -',\n { stdio: 'inherit' }\n );\n await execaCommand('sudo apt-get install -y nodejs', { stdio: 'inherit' });\n }\n\n spinner.succeed('Node.js installé');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de Node.js');\n throw error;\n }\n}\n\n// Install PHP automatically\nasync function installPHP(spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de PHP...');\n try {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Windows: Use winget or provide manual instructions\n try {\n await execaCommand('winget install PHP.PHP.8.2', { stdio: 'inherit' });\n } catch {\n spinner.info('PHP doit être installé manuellement sur Windows');\n console.log(chalk.yellow('\\nVeuillez télécharger et installer PHP depuis:'));\n console.log(chalk.cyan('https://windows.php.net/download/\\n'));\n console.log(chalk.gray('Choisissez la version 8.2 ou supérieure (VC15 x64 Non Thread Safe)\\n'));\n throw new Error('PHP installation manuelle requise');\n }\n } else {\n // Linux: Install via package manager\n await execaCommand('sudo apt update && sudo apt install -y php8.2 php8.2-cli php8.2-common php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-mysql php8.2-pgsql php8.2-sqlite3', { stdio: 'inherit' });\n }\n\n spinner.succeed('PHP installé');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de PHP');\n throw error;\n }\n}\n\n// Install a missing dependency\nasync function installDependency(dep: { name: string; command: string }, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n switch (dep.command) {\n case 'php':\n await installPHP(spinner);\n break;\n case 'composer':\n await installComposer(targetDir, spinner);\n break;\n case 'node':\n await installNodejs(targetDir, spinner);\n break;\n case 'npm':\n // npm comes with Node.js\n break;\n }\n}\n\n// Check all required dependencies\nasync function checkDependencies(spinner: ReturnType<typeof ora>): Promise<void> {\n const requiredDeps = [\n { name: 'PHP', command: 'php', install: 'https://php.net/downloads.php' },\n { name: 'Composer', command: 'composer', install: 'https://getcomposer.org/download/' },\n { name: 'Node.js', command: 'node', install: 'https://nodejs.org/' },\n { name: 'npm', command: 'npm', install: 'https://nodejs.org/' },\n ];\n\n const missing: typeof requiredDeps = [];\n\n for (const dep of requiredDeps) {\n const exists = await checkCommandExists(dep.command);\n if (!exists) {\n missing.push(dep);\n }\n }\n\n if (missing.length > 0) {\n console.log(chalk.bold('\\n⚠️ Dépendances manquantes:\\n'));\n\n for (const dep of missing) {\n console.log(chalk.red(` ❌ ${dep.name}`));\n }\n\n console.log(chalk.bold('\\n💡 Voulez-vous installer automatiquement les dépendances manquantes? (Recommandé)\\n'));\n\n const { autoInstall } = await prompts({\n type: 'confirm',\n name: 'autoInstall',\n message: 'Installer automatiquement?',\n initial: true,\n });\n\n if (!autoInstall) {\n console.log(chalk.bold('\\n📋 Instructions d\\'installation manuelle:\\n'));\n\n for (const dep of missing) {\n console.log(chalk.cyan(`${dep.name}:`));\n console.log(chalk.gray(` ${dep.install}\\n`));\n }\n\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n console.log(chalk.bold('Windows:\\n'));\n console.log(chalk.gray(' 1. PHP: https://windows.php.net/download/ (v8.2+)'));\n console.log(chalk.gray(' 2. Composer: https://getcomposer.org/Composer-Setup.exe'));\n console.log(chalk.gray(' 3. Node.js: https://nodejs.org/ (LTS version)\\n'));\n } else {\n console.log(chalk.bold('Linux/macOS:\\n'));\n console.log(chalk.gray(' Ubuntu/Debian: sudo apt install php composer nodejs npm'));\n console.log(chalk.gray(' macOS: brew install php composer node\\n'));\n }\n\n console.log(chalk.yellow('💡 Installez les dépendances puis relancez le CLI.\\n'));\n\n throw new Error('Dépendances manquantes');\n }\n\n // Install missing dependencies\n const tempDir = path.join(process.cwd(), '.exiloncms-temp');\n await fs.ensureDir(tempDir);\n\n try {\n for (const dep of missing) {\n await installDependency(dep, tempDir, spinner);\n }\n } finally {\n // Cleanup temp directory\n await fs.remove(tempDir);\n }\n\n // Verify installations\n console.log(chalk.bold('\\n✅ Vérification des installations...\\n'));\n\n const stillMissing: typeof requiredDeps = [];\n for (const dep of missing) {\n const exists = await checkCommandExists(dep.command);\n if (!exists) {\n stillMissing.push(dep);\n }\n }\n\n if (stillMissing.length > 0) {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // On Windows, this is likely a PATH issue - installations succeeded but terminal needs restart\n console.log(chalk.yellow('\\n⚠️ Les dépendances ont été installées mais ne sont pas encore détectées.\\n'));\n console.log(chalk.bold('Cela arrive souvent sur Windows - le PATH doit être rafraîchi.\\n'));\n console.log(chalk.bold('🔄 Solutions:\\n'));\n console.log(chalk.cyan(' Option 1 - Redémarrer le terminal (Recommandé):'));\n console.log(chalk.gray(' 1. Fermez ce terminal'));\n console.log(chalk.gray(' 2. Rouvrez un nouveau terminal'));\n console.log(chalk.gray(` 3. Relancez: npx @exiloncms/cli create ${process.argv[3] || 'mon-projet'}\\n`));\n\n console.log(chalk.cyan(' Option 2 - Continuer quand même:'));\n console.log(chalk.gray(' Les outils sont installés mais le CLI ne peut pas les exécuter directement.'));\n console.log(chalk.gray(' Vous pourrez continuer manuellement plus tard.\\n'));\n\n const { choice } = await prompts({\n type: 'select',\n name: 'choice',\n message: 'Que voulez-vous faire?',\n choices: [\n { title: '🔄 Redémarrer le terminal (Recommandé)', value: 'restart' },\n { title: '⏭️ Continuer quand même (Risqué)', value: 'continue' },\n { title: '❌ Annuler', value: 'cancel' },\n ],\n initial: 0,\n });\n\n if (choice === 'restart') {\n console.log(chalk.bold('\\n✅ Installation terminée!\\n'));\n console.log(chalk.cyan('Actions à effectuer:\\n'));\n console.log(chalk.gray(' 1. Fermez ce terminal'));\n console.log(chalk.gray(' 2. Ouvrez un NOUVEAU terminal'));\n console.log(chalk.gray(` 3. Relancez: npx @exiloncms/cli create ${process.argv[3] || 'mon-projet'}\\n`));\n console.log(chalk.green('PHP et Composer sont installés et prêts à être utilisés!\\n'));\n process.exit(0);\n } else if (choice === 'cancel') {\n console.log(chalk.yellow('\\nInstallation annulée.\\n'));\n process.exit(0);\n } else {\n console.log(chalk.yellow('\\n⚠️ Continuation malgré la détection manquante...\\n'));\n console.log(chalk.gray('Note: Vous devrez peut-être utiliser les chemins complets pour exécuter les commandes.\\n'));\n }\n } else {\n console.log(chalk.red('\\n⚠️ Certaines dépendances n\\'ont pas pu être installées automatiquement:\\n'));\n for (const dep of stillMissing) {\n console.log(chalk.red(` ❌ ${dep.name}`));\n }\n console.log(chalk.yellow('\\nVeuillez les installer manuellement.\\n'));\n throw new Error('Installation automatique incomplète');\n }\n } else {\n spinner.succeed('Toutes les dépendances sont installées');\n }\n } else {\n spinner.succeed('Toutes les dépendances sont installées');\n }\n}\n\nasync function promptForConfig(args: Partial<ProjectConfig> = {}, registry: MarketplaceRegistry | null): Promise<ProjectConfig> {\n console.log(banner);\n\n const config: ProjectConfig = {\n projectName: '',\n database: 'sqlite',\n theme: 'default',\n plugins: [],\n siteName: 'Mon Site ExilonCMS',\n adminName: 'Admin',\n adminEmail: 'admin@example.com',\n adminPassword: 'password',\n installDeps: true,\n runMigrations: true,\n };\n\n // Build theme options from registry or defaults\n const themeOptions = registry && registry.themes.length > 0\n ? [\n ...registry.themes.map(theme => ({\n title: `${theme.name} v${theme.version}`,\n value: theme.extension_id,\n description: `${theme.description} par ${theme.author}`,\n })),\n { title: 'Aucun thème (minimal)', value: 'none', description: 'Installation sans thème personnalisé' },\n ]\n : [\n { title: 'Thème par défaut', value: 'default', description: 'Thème par défaut d\\'ExilonCMS' },\n { title: 'Aucun thème (minimal)', value: 'none', description: 'Installation sans thème personnalisé' },\n ];\n\n // Build plugin options from registry or defaults\n const pluginOptions = registry && registry.plugins.length > 0\n ? registry.plugins.map(plugin => ({\n title: `${plugin.name} v${plugin.version}`,\n value: plugin.extension_id,\n description: plugin.description,\n }))\n : [];\n\n // Project Name\n if (!args.projectName) {\n const nameResponse = await prompts({\n type: 'text',\n name: 'projectName',\n message: 'Nom du projet:',\n initial: 'mon-site-exiloncms',\n validate: (value: string) => {\n if (!value) return 'Le nom du projet est requis';\n if (!validateProjectName(value)) return 'Le nom ne peut contenir que des lettres, chiffres, tirets et underscores';\n return true;\n },\n });\n config.projectName = nameResponse.projectName;\n } else {\n config.projectName = args.projectName;\n }\n\n // Database Selection\n if (!args.database) {\n const dbResponse = await prompts({\n type: 'select',\n name: 'database',\n message: 'Choisissez la base de données:',\n choices: databaseOptions,\n initial: 0,\n });\n config.database = dbResponse.database;\n } else {\n config.database = args.database;\n }\n\n // Theme Selection - only if themes are available\n if (!args.theme && themeOptions.length > 0) {\n const themeResponse = await prompts({\n type: 'select',\n name: 'theme',\n message: 'Choisissez un thème:',\n choices: themeOptions,\n initial: 0,\n });\n config.theme = themeResponse.theme;\n } else {\n config.theme = args.theme || 'default';\n }\n\n // Plugin Selection - only if plugins are available\n if ((!args.plugins || args.plugins.length === 0) && pluginOptions.length > 0) {\n const pluginResponse = await prompts({\n type: 'multiselect',\n name: 'plugins',\n message: 'Choisissez les plugins à installer (Espace pour sélectionner, Entrée pour valider):',\n choices: pluginOptions,\n instructions: false,\n });\n config.plugins = pluginResponse.plugins || [];\n } else {\n config.plugins = args.plugins || [];\n }\n\n // Site Configuration\n if (!args.siteName || !args.adminName || !args.adminEmail || !args.adminPassword) {\n console.log(chalk.bold('\\n📝 Configuration du site:\\n'));\n\n const siteResponse = await prompts([\n {\n type: 'text',\n name: 'siteName',\n message: 'Nom du site:',\n initial: config.siteName,\n },\n {\n type: 'text',\n name: 'adminName',\n message: 'Nom de l\\'administrateur:',\n initial: config.adminName,\n },\n {\n type: 'text',\n name: 'adminEmail',\n message: 'Email de l\\'administrateur:',\n initial: config.adminEmail,\n validate: (value: string) => {\n if (!value) return 'L\\'email est requis';\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) return 'Email invalide';\n return true;\n },\n },\n {\n type: 'password',\n name: 'adminPassword',\n message: 'Mot de passe administrateur:',\n validate: (value: string) => {\n if (!value || value.length < 6) return 'Le mot de passe doit contenir au moins 6 caractères';\n return true;\n },\n },\n ]);\n\n config.siteName = siteResponse.siteName || config.siteName;\n config.adminName = siteResponse.adminName || config.adminName;\n config.adminEmail = siteResponse.adminEmail || config.adminEmail;\n config.adminPassword = siteResponse.adminPassword || config.adminPassword;\n } else {\n config.siteName = args.siteName;\n config.adminName = args.adminName;\n config.adminEmail = args.adminEmail;\n config.adminPassword = args.adminPassword;\n }\n\n // Post-install options\n if (args.installDeps === undefined || args.runMigrations === undefined) {\n console.log(chalk.bold('\\n⚙️ Options d\\'installation:\\n'));\n\n const installResponse = await prompts([\n {\n type: 'confirm',\n name: 'installDeps',\n message: 'Installer les dépendances (composer & npm)?',\n initial: true,\n },\n {\n type: 'confirm',\n name: 'runMigrations',\n message: 'Exécuter les migrations et seeder la base de données?',\n initial: true,\n },\n ]);\n\n config.installDeps = installResponse.installDeps !== undefined ? installResponse.installDeps : true;\n config.runMigrations = installResponse.runMigrations !== undefined ? installResponse.runMigrations : true;\n } else {\n config.installDeps = args.installDeps;\n config.runMigrations = args.runMigrations;\n }\n\n return config;\n}\n\nasync function downloadProject(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Téléchargement d\\'ExilonCMS...');\n\n const emitter = degit('Exilon-Studios/ExilonCMS', {\n cache: false,\n force: true,\n verbose: false,\n });\n\n try {\n await emitter.clone(targetDir);\n spinner.succeed('ExilonCMS téléchargé avec succès');\n } catch (error) {\n spinner.fail('Erreur lors du téléchargement');\n throw error;\n }\n}\n\nasync function configureProject(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Configuration du projet...');\n\n try {\n // Configure .env file\n const envPath = path.join(targetDir, '.env');\n const envExamplePath = path.join(targetDir, '.env.example');\n\n if (await fs.pathExists(envExamplePath)) {\n let envContent = await fs.readFile(envExamplePath, 'utf-8');\n\n // Set database configuration\n if (config.database === 'sqlite') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=sqlite');\n envContent = envContent.replace(/#DB_DATABASE=.*/, 'DB_DATABASE=' + path.join(targetDir, 'database', 'database.sqlite'));\n } else if (config.database === 'postgresql') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=pgsql');\n envContent = envContent.replace(/DB_DATABASE=.*/, 'DB_DATABASE=exiloncms');\n envContent = envContent.replace(/DB_USERNAME=.*/, 'DB_USERNAME=postgres');\n } else if (config.database === 'mysql') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=mysql');\n envContent = envContent.replace(/DB_DATABASE=.*/, 'DB_DATABASE=exiloncms');\n envContent = envContent.replace(/DB_USERNAME=.*/, 'DB_USERNAME=root');\n }\n\n // Set app name\n envContent = envContent.replace(/APP_NAME=.*/, `APP_NAME=\"${config.siteName}\"`);\n\n await fs.writeFile(envPath, envContent);\n }\n\n // Create SQLite database if selected\n if (config.database === 'sqlite') {\n const dbDir = path.join(targetDir, 'database');\n await fs.ensureDir(dbDir);\n const dbPath = path.join(dbDir, 'database.sqlite');\n if (!(await fs.pathExists(dbPath))) {\n await fs.writeFile(dbPath, '');\n }\n }\n\n // Create required directories\n const themesDir = path.join(targetDir, 'resources', 'themes');\n await fs.ensureDir(themesDir);\n\n const pluginsDir = path.join(targetDir, 'plugins');\n await fs.ensureDir(pluginsDir);\n\n // Generate APP_KEY\n spinner.text = 'Génération de la clé d\\'application...';\n await execaCommand('php artisan key:generate --force', { cwd: targetDir, stdio: 'inherit' });\n\n spinner.succeed('Projet configuré avec succès');\n } catch (error) {\n spinner.fail('Erreur lors de la configuration');\n throw error;\n }\n}\n\nasync function installDependencies(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n if (!config.installDeps) {\n spinner.info('Installation des dépendances skipée');\n return;\n }\n\n // Composer\n spinner.start('Installation des dépendances PHP (Composer)...');\n try {\n await execaCommand('composer install --no-interaction --quiet', { cwd: targetDir });\n spinner.succeed('Dépendances PHP installées');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation Composer');\n throw error;\n }\n\n // NPM\n spinner.start('Installation des dépendances Node.js...');\n try {\n await execaCommand('npm install --silent', { cwd: targetDir });\n spinner.succeed('Dépendances Node.js installées');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation NPM');\n throw error;\n }\n\n // Build assets\n spinner.start('Construction des assets...');\n try {\n await execaCommand('npm run build', { cwd: targetDir });\n spinner.succeed('Assets construits');\n } catch (error) {\n spinner.warn('Erreur lors du build des assets (non-critique)');\n }\n}\n\nasync function runMigrationsAndSeed(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n if (!config.runMigrations) {\n spinner.info('Migrations skipées');\n return;\n }\n\n spinner.start('Exécution des migrations et seeder...');\n try {\n // For SQLite, we use migrate:fresh which is safe for fresh install\n const command = config.database === 'sqlite'\n ? 'php artisan migrate:fresh --seed --force'\n : 'php artisan migrate --seed --force';\n\n await execaCommand(command, {\n cwd: targetDir,\n stdio: 'inherit',\n });\n\n spinner.succeed('Base de données initialisée');\n } catch (error) {\n spinner.fail('Erreur lors des migrations');\n throw error;\n }\n}\n\nasync function createAdminUser(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Création de l\\'utilisateur admin...');\n try {\n await execaCommand(\n `php artisan user:create --admin --name=\"${config.adminName}\" --email=\"${config.adminEmail}\" --password=\"${config.adminPassword}\"`,\n { cwd: targetDir, stdio: 'inherit' }\n );\n spinner.succeed('Utilisateur admin créé');\n } catch (error) {\n spinner.warn('Erreur lors de la création de l\\'admin (peut-être déjà créé via seeder)');\n }\n}\n\n// Create custom admin seeder to override default credentials\nasync function createCustomAdminSeeder(config: ProjectConfig, targetDir: string): Promise<void> {\n const seederPath = path.join(targetDir, 'database/seeders/CustomAdminSeeder.php');\n const seederContent = `<?php\n\nnamespace Database\\\\Seeders;\n\nuse ExilonCMS\\\\Models\\\\User;\nuse ExilonCMS\\\\Models\\\\Role;\nuse ExilonCMS\\\\Models\\\\Permission;\nuse Illuminate\\\\Database\\\\Console\\\\Seeds\\\\WithoutModelEvents;\nuse Illuminate\\\\Database\\\\Seeder;\nuse Illuminate\\\\Support\\\\Facades\\\\Hash;\n\nclass CustomAdminSeeder extends Seeder\n{\n use WithoutModelEvents;\n\n public function run(): void\n {\n // Create admin role if it doesn't exist\n $adminRole = Role::firstOrCreate(\n ['name' => 'admin'],\n [\n 'color' => 'FF0000',\n 'is_admin' => true,\n 'power' => 100,\n ]\n );\n\n // Create admin user with custom credentials\n $admin = User::firstOrCreate(\n ['email' => '${config.adminEmail}'],\n [\n 'name' => '${config.adminName}',\n 'password' => Hash::make('${config.adminPassword}'),\n 'role_id' => $adminRole->id,\n 'email_verified_at' => now(),\n 'password_changed_at' => now(),\n ]\n );\n\n // Create all permissions for admin role\n if ($adminRole->permissions()->count() === 0) {\n foreach (Permission::permissions() as $permission) {\n Permission::create([\n 'permission' => $permission,\n 'role_id' => $adminRole->id,\n ]);\n }\n }\n }\n}\n`;\n\n await fs.writeFile(seederPath, seederContent);\n\n // Update DatabaseSeeder to use CustomAdminSeeder instead of AdminUserSeeder\n const databaseSeederPath = path.join(targetDir, 'database/seeders/DatabaseSeeder.php');\n let databaseSeederContent = await fs.readFile(databaseSeederPath, 'utf-8');\n\n // Replace AdminUserSeeder with CustomAdminSeeder in the call array\n databaseSeederContent = databaseSeederContent.replace(\n /AdminUserSeeder::class/,\n 'CustomAdminSeeder::class'\n );\n\n await fs.writeFile(databaseSeederPath, databaseSeederContent);\n}\n\n// Install plugins from marketplace\nasync function installPlugins(config: ProjectConfig, targetDir: string, registry: MarketplaceRegistry | null, spinner: ReturnType<typeof ora>): Promise<void> {\n if (config.plugins.length === 0) {\n return;\n }\n\n if (!registry) {\n spinner.warn('Marketplace non disponible, impossible d\\'installer les plugins');\n return;\n }\n\n for (const pluginId of config.plugins) {\n const plugin = registry.plugins.find(p => p.extension_id === pluginId);\n if (!plugin) {\n spinner.warn(`Plugin ${pluginId} non trouvé dans le marketplace`);\n continue;\n }\n\n spinner.start(`Installation du plugin ${plugin.name}...`);\n try {\n // Download plugin zip\n const pluginZipPath = path.join(targetDir, 'temp_plugin.zip');\n const response = await fetch(plugin.url);\n const buffer = await response.arrayBuffer();\n await fs.writeFile(pluginZipPath, Buffer.from(buffer));\n\n // Extract using platform-specific command\n const pluginsDir = path.join(targetDir, 'plugins');\n await fs.ensureDir(pluginsDir);\n\n // Detect platform and use appropriate unzip command\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Use PowerShell's Expand-Archive on Windows\n await execaCommand(\n `powershell -Command \"Expand-Archive -Path '${pluginZipPath}' -DestinationPath '${pluginsDir}' -Force\"`,\n { cwd: targetDir }\n );\n } else {\n // Use unzip command on Linux/Mac\n await execaCommand(`unzip -o \"${pluginZipPath}\" -d \"${pluginsDir}\"`, { cwd: targetDir });\n }\n\n // Clean up\n await fs.remove(pluginZipPath);\n\n spinner.succeed(`Plugin ${plugin.name} installé`);\n } catch (error) {\n spinner.fail(`Erreur lors de l'installation du plugin ${plugin.name}`);\n console.error(error);\n }\n }\n}\n\nfunction printSuccessMessage(config: ProjectConfig, targetDir: string): void {\n console.log(chalk.bold('\\n✨ Installation terminée avec succès!\\n'));\n\n console.log(chalk.cyan(' Projet créé dans: ') + chalk.white(targetDir));\n console.log(chalk.cyan(' Base de données: ') + chalk.white(config.database));\n console.log(chalk.cyan(' Thème: ') + chalk.white(config.theme));\n\n if (config.plugins.length > 0) {\n console.log(chalk.cyan(' Plugins installés: ') + chalk.white(config.plugins.join(', ')));\n }\n\n console.log(chalk.bold('\\n🚀 Prochaines étapes:\\n'));\n\n console.log(` ${chalk.cyan('1.')} Aller dans le dossier du projet:`);\n console.log(` ${chalk.gray(`cd ${config.projectName}`)}\\n`);\n\n if (!config.installDeps) {\n console.log(` ${chalk.cyan('2.')} Installer les dépendances:`);\n console.log(` ${chalk.gray('composer install')}`);\n console.log(` ${chalk.gray('npm install')}`);\n console.log(` ${chalk.gray('npm run build')}\\n`);\n }\n\n if (!config.runMigrations) {\n console.log(` ${chalk.cyan('3.')} Configurer la base de données et lancer les migrations:`);\n if (config.database !== 'sqlite') {\n console.log(` ${chalk.yellow('⚠️ Configurez votre base de données dans .env d\\'abord')}`);\n }\n console.log(` ${chalk.gray('php artisan migrate:fresh --seed')}\\n`);\n }\n\n console.log(` ${chalk.cyan('4.')} Démarrer le serveur de développement:`);\n console.log(` ${chalk.gray('php artisan serve')}\\n`);\n\n if (config.database === 'sqlite') {\n console.log(` ${chalk.green('✓')} SQLite utilisé - aucune configuration de base de données nécessaire!\\n`);\n } else {\n console.log(` ${chalk.yellow('⚠️ ')} Configurez votre base de données ${config.database} dans ${chalk.gray('.env')}\\n`);\n }\n\n console.log(chalk.bold('📧 Identifiants admin:\\n'));\n console.log(` Email: ${chalk.cyan(config.adminEmail)}`);\n console.log(` Password: ${chalk.cyan(config.adminPassword)}\\n`);\n\n console.log(chalk.gray(' ' + '─'.repeat(60) + '\\n'));\n\n console.log(` ${chalk.cyan('Documentation:')} https://github.com/Exilon-Studios/ExilonCMS/wiki\\n`);\n}\n\nasync function createCommand(projectName: string, options: any): Promise<void> {\n const spinner = ora();\n\n try {\n // Check dependencies first\n console.log(chalk.bold('\\n🔍 Vérification des dépendances...\\n'));\n await checkDependencies(spinner);\n\n // Fetch marketplace registry\n const registry = await fetchMarketplaceRegistry();\n\n const config = await promptForConfig({\n projectName,\n database: options.database,\n theme: options.theme,\n plugins: options.plugins ? options.plugins.split(',') : [],\n siteName: options.siteName,\n adminName: options.adminName,\n adminEmail: options.adminEmail,\n adminPassword: options.adminPassword,\n installDeps: options.installDeps,\n runMigrations: options.runMigrations,\n }, registry);\n\n const targetDir = path.resolve(process.cwd(), config.projectName);\n\n // Check if directory exists\n if (await fs.pathExists(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Le dossier ${config.projectName} existe déjà. Écraser?`,\n initial: false,\n });\n\n if (!overwrite) {\n console.log(chalk.yellow('\\nInstallation annulée.'));\n process.exit(0);\n }\n\n await fs.remove(targetDir);\n }\n\n // Download project\n await downloadProject(targetDir, spinner);\n\n // Install dependencies FIRST\n await installDependencies(config, targetDir, spinner);\n\n // Configure project (needs artisan which needs composer dependencies)\n await configureProject(config, targetDir, spinner);\n\n // Create custom admin seeder with user's credentials\n await createCustomAdminSeeder(config, targetDir);\n\n // Run migrations (will use custom admin seeder)\n await runMigrationsAndSeed(config, targetDir, spinner);\n\n // Install plugins from marketplace\n await installPlugins(config, targetDir, registry, spinner);\n\n // Print success message\n printSuccessMessage(config, targetDir);\n\n } catch (error: any) {\n if (error.message === 'user cancelled') {\n console.log(chalk.yellow('\\nInstallation annulée.'));\n process.exit(0);\n }\n\n console.error(chalk.red('\\n✖ Erreur:'), error.message);\n process.exit(1);\n }\n}\n\n// CLI Program\nconst program = new Command();\n\nprogram\n .name('exiloncms')\n .description('Create a new ExilonCMS project')\n .version(packageJson.version);\n\nprogram\n .command('create [project-name]')\n .description('Create a new ExilonCMS project')\n .option('-d, --database <type>', 'Database type (sqlite, postgresql, mysql)', 'sqlite')\n .option('-t, --theme <name>', 'Theme name', 'default')\n .option('-p, --plugins <list>', 'Comma-separated list of plugins')\n .option('--site-name <name>', 'Site name')\n .option('--admin-name <name>', 'Admin name')\n .option('--admin-email <email>', 'Admin email')\n .option('--admin-password <password>', 'Admin password')\n .option('--no-install-deps', 'Skip installing dependencies')\n .option('--no-run-migrations', 'Skip running migrations')\n .action(createCommand);\n\nprogram\n .command('new [project-name]')\n .description('Alias for create')\n .option('-d, --database <type>', 'Database type (sqlite, postgresql, mysql)', 'sqlite')\n .option('-t, --theme <name>', 'Theme name', 'default')\n .option('-p, --plugins <list>', 'Comma-separated list of plugins')\n .option('--site-name <name>', 'Site name')\n .option('--admin-name <name>', 'Admin name')\n .option('--admin-email <email>', 'Admin email')\n .option('--admin-password <password>', 'Admin password')\n .option('--no-install-deps', 'Skip installing dependencies')\n .option('--no-run-migrations', 'Skip running migrations')\n .action(createCommand);\n\nprogram.parse();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport prompts from 'prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { execaCommand } from 'execa';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport degit from 'degit';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst packageJson = await fs.readJson(path.join(__dirname, '../package.json'));\n\n// ASCII Art Banner\nconst banner = `\n${chalk.cyan('╔═══════════════════════════════════════════════════════════╗')}\n${chalk.cyan('║')} ${chalk.bold.white('ExilonCMS CLI')} ${chalk.gray(`v${packageJson.version}`)} ${' '.repeat(36)} ${chalk.cyan('║')}\n${chalk.cyan('║')} ${chalk.white('Create modern ExilonCMS projects with ease')} ${' '.repeat(24)} ${chalk.cyan('║')}\n${chalk.cyan('╚═══════════════════════════════════════════════════════════╝')}\n`;\n\n// Marketplace Registry URL\nconst MARKETPLACE_REGISTRY_URL = 'https://raw.githubusercontent.com/Exilon-Studios/ExilonCMS-marketplace/main/registry.json';\n\n// Marketplace Registry Types\ninterface MarketplacePlugin {\n id: number;\n extension_id: string;\n name: string;\n description: string;\n version: string;\n author: string;\n url: string;\n repo_url?: string;\n hash: string;\n}\n\ninterface MarketplaceTheme {\n id: number;\n extension_id: string;\n name: string;\n description: string;\n version: string;\n author: string;\n url: string;\n hash: string;\n}\n\ninterface MarketplaceRegistry {\n plugins: MarketplacePlugin[];\n themes: MarketplaceTheme[];\n games: any[];\n alerts: any[];\n}\n\n// Fetch marketplace registry\nasync function fetchMarketplaceRegistry(): Promise<MarketplaceRegistry | null> {\n const spinner = ora();\n try {\n spinner.start('Récupération du marketplace...');\n const response = await fetch(MARKETPLACE_REGISTRY_URL);\n if (!response.ok) {\n spinner.warn('Impossible de récupérer le marketplace, utilisation des options par défaut');\n return null;\n }\n const registry: MarketplaceRegistry = await response.json();\n spinner.succeed(`Marketplace connecté - ${registry.plugins.length} plugins, ${registry.themes.length} thèmes`);\n return registry;\n } catch (error) {\n spinner.warn('Impossible de connecter au marketplace, utilisation des options par défaut');\n return null;\n }\n}\n\n// Database options\nconst databaseOptions = [\n { title: 'SQLite (Recommandé - Pas de configuration)', value: 'sqlite', description: 'Base de données fichier, aucune configuration requise' },\n { title: 'PostgreSQL', value: 'postgresql', description: 'Base de données serveur, performante et robuste' },\n { title: 'MySQL', value: 'mysql', description: 'Base de données serveur, populaire et répandue' },\n];\n\ninterface ProjectConfig {\n projectName: string;\n database: string;\n theme: string;\n plugins: string[];\n siteName: string;\n adminName: string;\n adminEmail: string;\n adminPassword: string;\n installDeps: boolean;\n runMigrations: boolean;\n}\n\nfunction validateProjectName(name: string): boolean {\n return /^[a-zA-Z0-9_-]+$/.test(name);\n}\n\n// Check if a command exists on the system\nasync function checkCommandExists(command: string): Promise<boolean> {\n try {\n const isWindows = process.platform === 'win32';\n const checkCmd = isWindows ? `where ${command}` : `which ${command}`;\n await execaCommand(checkCmd, { stdio: 'pipe' });\n return true;\n } catch {\n // On Windows, also check standard installation paths\n if (process.platform === 'win32') {\n try {\n const standardPaths: Record<string, string[]> = {\n 'composer': [\n path.join(process.env.LOCALAPPDATA || '', 'Composer', 'composer.bat'),\n path.join(process.env.LOCALAPPDATA || '', 'Composer', 'composer.phar'),\n 'C:\\\\ProgramData\\\\ComposerSetup\\\\bin\\\\composer.bat',\n 'C:\\\\Program Files\\\\Composer\\\\composer.bat',\n ],\n 'php': [\n 'C:\\\\php\\\\php.exe',\n 'C:\\\\Program Files\\\\PHP\\\\php.exe',\n path.join(process.env.LOCALAPPDATA || '', 'Programs', 'PHP', 'php.exe'),\n ],\n 'node': [\n 'C:\\\\Program Files\\\\nodejs\\\\node.exe',\n path.join(process.env.APPDATA || '', 'npm', 'node.exe'),\n ],\n 'npm': [\n 'C:\\\\Program Files\\\\nodejs\\\\npm.cmd',\n 'C:\\\\Program Files\\\\nodejs\\\\npm',\n ],\n };\n\n const paths = standardPaths[command] || [];\n for (const filePath of paths) {\n if (await fs.pathExists(filePath)) {\n return true;\n }\n }\n } catch {\n return false;\n }\n }\n return false;\n }\n}\n\n// Install Composer automatically using official method\nasync function installComposer(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de Composer...');\n try {\n const composerDir = path.join(process.env.LOCALAPPDATA || '', 'Composer');\n await fs.ensureDir(composerDir);\n\n // Download composer.phar directly using Node.js (most reliable method)\n spinner.text = 'Téléchargement de Composer...';\n\n const composerPharPath = path.join(composerDir, 'composer.phar');\n\n try {\n // Download with proper redirect handling\n const response = await fetch('https://getcomposer.org/composer-stable.phar', {\n redirect: 'follow',\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n // Check if we got HTML instead of PHAR (common error)\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('text/html')) {\n throw new Error('Le serveur a retourné une page HTML au lieu du fichier PHAR');\n }\n\n const buffer = await response.arrayBuffer();\n const content = Buffer.from(buffer);\n\n // Verify it's a valid PHAR file (must start with __HALT_COMPILER();)\n const pharSignature = '__HALT_COMPILER';\n const contentStart = content.toString('utf8', 0, Math.min(100, content.length));\n if (!contentStart.includes(pharSignature)) {\n throw new Error('Le fichier téléchargé n\\'est pas un fichier PHAR valide');\n }\n\n await fs.writeFile(composerPharPath, content);\n spinner.succeed('Composer téléchargé');\n } catch (error) {\n throw new Error(`Impossible de télécharger Composer: ${(error as Error).message}`);\n }\n\n // Verify composer.phar was created\n if (!(await fs.pathExists(composerPharPath))) {\n throw new Error('composer.phar n\\'a pas été téléchargé correctement');\n }\n\n // Test that composer.phar works\n spinner.text = 'Vérification de Composer...';\n try {\n const { stdout } = await execaCommand(`php \"${composerPharPath}\" --version`, { stdio: 'pipe' });\n if (!stdout.includes('Composer')) {\n throw new Error('La commande php composer.phar n\\'a pas retourné \"Composer\"');\n }\n } catch (error) {\n throw new Error(`Le fichier composer.phar ne fonctionne pas: ${(error as Error).message}`);\n }\n\n // Create composer.bat wrapper on Windows\n const isWindows = process.platform === 'win32';\n if (isWindows) {\n const composerBat = path.join(composerDir, 'composer.bat');\n const batContent = `@ECHO OFF\\r\\nphp \"${composerPharPath}\" %*\\r\\n`;\n await fs.writeFile(composerBat, batContent);\n\n // Add to PATH (for current session and future sessions)\n try {\n await execaCommand(\n `powershell -Command \"[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path', 'User') + ';${composerDir}', 'User')\"`,\n { stdio: 'pipe' }\n );\n } catch {\n // Ignore PATH update errors\n }\n\n // Add to current session\n process.env.PATH = `${composerDir};${process.env.PATH}`;\n } else {\n // Linux/macOS: Create a wrapper script\n const composerWrapper = path.join(composerDir, 'composer');\n const wrapperContent = `#!/bin/bash\\nphp \"${composerPharPath}\" \"$@\"\\n`;\n await fs.writeFile(composerWrapper, wrapperContent);\n await execaCommand(`chmod +x \"${composerWrapper}\"`, { stdio: 'pipe' });\n\n // Add to PATH\n const localBin = path.join(process.env.HOME || '', '.local', 'bin');\n await fs.ensureDir(localBin);\n const composerBin = path.join(localBin, 'composer');\n await fs.copy(composerWrapper, composerBin);\n\n try {\n await execaCommand(\n `export PATH=\"${localBin}:$PATH\"`,\n { stdio: 'pipe' }\n );\n } catch {\n // Ignore\n }\n\n process.env.PATH = `${localBin}:${process.env.PATH}`;\n }\n\n spinner.succeed('Composer installé');\n\n // On Windows, inform user that terminal restart is needed\n if (isWindows) {\n console.log(chalk.yellow('\\n⚠️ NOTE: Composer a été installé mais pour utiliser la commande \"composer\"'));\n console.log(chalk.yellow('dans tout votre système, vous devez redémarrer ce terminal.\\n'));\n console.log(chalk.gray('Pour ce projet, le CLI utilisera le chemin complet automatiquement.\\n'));\n }\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de Composer');\n console.error(error);\n throw error;\n }\n}\n\n// Install Node.js automatically\nasync function installNodejs(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de Node.js...');\n try {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Windows: Download and install Node.js LTS using winget if available, else download installer\n try {\n await execaCommand('winget install OpenJS.NodeJS.LTS', { stdio: 'inherit' });\n } catch {\n // Fallback: Download installer\n const installerPath = path.join(targetDir, 'nodejs-installer.msi');\n await execaCommand(\n `powershell -Command \"Invoke-WebRequest -Uri 'https://nodejs.org/dist/latest-v20.x/' -OutFile '${installerPath}'\"`,\n { stdio: 'inherit' }\n );\n spinner.info('Veuillez installer Node.js manuellement depuis: https://nodejs.org/');\n }\n } else {\n // Linux: Use NodeSource repository\n await execaCommand(\n 'curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -',\n { stdio: 'inherit' }\n );\n await execaCommand('sudo apt-get install -y nodejs', { stdio: 'inherit' });\n }\n\n spinner.succeed('Node.js installé');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de Node.js');\n throw error;\n }\n}\n\n// Install PHP automatically\nasync function installPHP(spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Installation de PHP...');\n try {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Windows: Use winget or provide manual instructions\n try {\n await execaCommand('winget install PHP.PHP.8.2', { stdio: 'inherit' });\n } catch {\n spinner.info('PHP doit être installé manuellement sur Windows');\n console.log(chalk.yellow('\\nVeuillez télécharger et installer PHP depuis:'));\n console.log(chalk.cyan('https://windows.php.net/download/\\n'));\n console.log(chalk.gray('Choisissez la version 8.2 ou supérieure (VC15 x64 Non Thread Safe)\\n'));\n throw new Error('PHP installation manuelle requise');\n }\n } else {\n // Linux: Install via package manager\n await execaCommand('sudo apt update && sudo apt install -y php8.2 php8.2-cli php8.2-common php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-mysql php8.2-pgsql php8.2-sqlite3', { stdio: 'inherit' });\n }\n\n spinner.succeed('PHP installé');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation de PHP');\n throw error;\n }\n}\n\n// Install a missing dependency\nasync function installDependency(dep: { name: string; command: string }, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n switch (dep.command) {\n case 'php':\n await installPHP(spinner);\n break;\n case 'composer':\n await installComposer(targetDir, spinner);\n break;\n case 'node':\n await installNodejs(targetDir, spinner);\n break;\n case 'npm':\n // npm comes with Node.js\n break;\n }\n}\n\n// Check all required dependencies\nasync function checkDependencies(spinner: ReturnType<typeof ora>): Promise<void> {\n const requiredDeps = [\n { name: 'PHP', command: 'php', install: 'https://php.net/downloads.php' },\n { name: 'Composer', command: 'composer', install: 'https://getcomposer.org/download/' },\n { name: 'Node.js', command: 'node', install: 'https://nodejs.org/' },\n { name: 'npm', command: 'npm', install: 'https://nodejs.org/' },\n ];\n\n const missing: typeof requiredDeps = [];\n\n for (const dep of requiredDeps) {\n const exists = await checkCommandExists(dep.command);\n if (!exists) {\n missing.push(dep);\n }\n }\n\n if (missing.length > 0) {\n console.log(chalk.bold('\\n⚠️ Dépendances manquantes:\\n'));\n\n for (const dep of missing) {\n console.log(chalk.red(` ❌ ${dep.name}`));\n }\n\n console.log(chalk.bold('\\n💡 Voulez-vous installer automatiquement les dépendances manquantes? (Recommandé)\\n'));\n\n const { autoInstall } = await prompts({\n type: 'confirm',\n name: 'autoInstall',\n message: 'Installer automatiquement?',\n initial: true,\n });\n\n if (!autoInstall) {\n console.log(chalk.bold('\\n📋 Instructions d\\'installation manuelle:\\n'));\n\n for (const dep of missing) {\n console.log(chalk.cyan(`${dep.name}:`));\n console.log(chalk.gray(` ${dep.install}\\n`));\n }\n\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n console.log(chalk.bold('Windows:\\n'));\n console.log(chalk.gray(' 1. PHP: https://windows.php.net/download/ (v8.2+)'));\n console.log(chalk.gray(' 2. Composer: https://getcomposer.org/Composer-Setup.exe'));\n console.log(chalk.gray(' 3. Node.js: https://nodejs.org/ (LTS version)\\n'));\n } else {\n console.log(chalk.bold('Linux/macOS:\\n'));\n console.log(chalk.gray(' Ubuntu/Debian: sudo apt install php composer nodejs npm'));\n console.log(chalk.gray(' macOS: brew install php composer node\\n'));\n }\n\n console.log(chalk.yellow('💡 Installez les dépendances puis relancez le CLI.\\n'));\n\n throw new Error('Dépendances manquantes');\n }\n\n // Install missing dependencies\n const tempDir = path.join(process.cwd(), '.exiloncms-temp');\n await fs.ensureDir(tempDir);\n\n try {\n for (const dep of missing) {\n await installDependency(dep, tempDir, spinner);\n }\n } finally {\n // Cleanup temp directory\n await fs.remove(tempDir);\n }\n\n // Verify installations\n console.log(chalk.bold('\\n✅ Vérification des installations...\\n'));\n\n const stillMissing: typeof requiredDeps = [];\n for (const dep of missing) {\n const exists = await checkCommandExists(dep.command);\n if (!exists) {\n stillMissing.push(dep);\n }\n }\n\n if (stillMissing.length > 0) {\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // On Windows, this is likely a PATH issue - installations succeeded but terminal needs restart\n console.log(chalk.yellow('\\n⚠️ Les dépendances ont été installées mais ne sont pas encore détectées.\\n'));\n console.log(chalk.bold('Cela arrive souvent sur Windows - le PATH doit être rafraîchi.\\n'));\n console.log(chalk.bold('🔄 Solutions:\\n'));\n console.log(chalk.cyan(' Option 1 - Redémarrer le terminal (Recommandé):'));\n console.log(chalk.gray(' 1. Fermez ce terminal'));\n console.log(chalk.gray(' 2. Rouvrez un nouveau terminal'));\n console.log(chalk.gray(` 3. Relancez: npx @exiloncms/cli create ${process.argv[3] || 'mon-projet'}\\n`));\n\n console.log(chalk.cyan(' Option 2 - Continuer quand même:'));\n console.log(chalk.gray(' Les outils sont installés mais le CLI ne peut pas les exécuter directement.'));\n console.log(chalk.gray(' Vous pourrez continuer manuellement plus tard.\\n'));\n\n const { choice } = await prompts({\n type: 'select',\n name: 'choice',\n message: 'Que voulez-vous faire?',\n choices: [\n { title: '🔄 Redémarrer le terminal (Recommandé)', value: 'restart' },\n { title: '⏭️ Continuer quand même (Risqué)', value: 'continue' },\n { title: '❌ Annuler', value: 'cancel' },\n ],\n initial: 0,\n });\n\n if (choice === 'restart') {\n console.log(chalk.bold('\\n✅ Installation terminée!\\n'));\n console.log(chalk.cyan('Actions à effectuer:\\n'));\n console.log(chalk.gray(' 1. Fermez ce terminal'));\n console.log(chalk.gray(' 2. Ouvrez un NOUVEAU terminal'));\n console.log(chalk.gray(` 3. Relancez: npx @exiloncms/cli create ${process.argv[3] || 'mon-projet'}\\n`));\n console.log(chalk.green('PHP et Composer sont installés et prêts à être utilisés!\\n'));\n process.exit(0);\n } else if (choice === 'cancel') {\n console.log(chalk.yellow('\\nInstallation annulée.\\n'));\n process.exit(0);\n } else {\n console.log(chalk.yellow('\\n⚠️ Continuation malgré la détection manquante...\\n'));\n console.log(chalk.gray('Note: Vous devrez peut-être utiliser les chemins complets pour exécuter les commandes.\\n'));\n }\n } else {\n console.log(chalk.red('\\n⚠️ Certaines dépendances n\\'ont pas pu être installées automatiquement:\\n'));\n for (const dep of stillMissing) {\n console.log(chalk.red(` ❌ ${dep.name}`));\n }\n console.log(chalk.yellow('\\nVeuillez les installer manuellement.\\n'));\n throw new Error('Installation automatique incomplète');\n }\n } else {\n spinner.succeed('Toutes les dépendances sont installées');\n }\n } else {\n spinner.succeed('Toutes les dépendances sont installées');\n }\n}\n\nasync function promptForConfig(args: Partial<ProjectConfig> = {}, registry: MarketplaceRegistry | null): Promise<ProjectConfig> {\n console.log(banner);\n\n const config: ProjectConfig = {\n projectName: '',\n database: 'sqlite',\n theme: 'default',\n plugins: [],\n siteName: 'Mon Site ExilonCMS',\n adminName: 'Admin',\n adminEmail: 'admin@example.com',\n adminPassword: 'password',\n installDeps: true,\n runMigrations: true,\n };\n\n // Build theme options from registry or defaults\n const themeOptions = registry && registry.themes.length > 0\n ? [\n ...registry.themes.map(theme => ({\n title: `${theme.name} v${theme.version}`,\n value: theme.extension_id,\n description: `${theme.description} par ${theme.author}`,\n })),\n { title: 'Aucun thème (minimal)', value: 'none', description: 'Installation sans thème personnalisé' },\n ]\n : [\n { title: 'Thème par défaut', value: 'default', description: 'Thème par défaut d\\'ExilonCMS' },\n { title: 'Aucun thème (minimal)', value: 'none', description: 'Installation sans thème personnalisé' },\n ];\n\n // Build plugin options from registry or defaults\n const pluginOptions = registry && registry.plugins.length > 0\n ? registry.plugins.map(plugin => ({\n title: `${plugin.name} v${plugin.version}`,\n value: plugin.extension_id,\n description: plugin.description,\n }))\n : [];\n\n // Project Name\n if (!args.projectName) {\n const nameResponse = await prompts({\n type: 'text',\n name: 'projectName',\n message: 'Nom du projet:',\n initial: 'mon-site-exiloncms',\n validate: (value: string) => {\n if (!value) return 'Le nom du projet est requis';\n if (!validateProjectName(value)) return 'Le nom ne peut contenir que des lettres, chiffres, tirets et underscores';\n return true;\n },\n });\n config.projectName = nameResponse.projectName;\n } else {\n config.projectName = args.projectName;\n }\n\n // Database Selection\n if (!args.database) {\n const dbResponse = await prompts({\n type: 'select',\n name: 'database',\n message: 'Choisissez la base de données:',\n choices: databaseOptions,\n initial: 0,\n });\n config.database = dbResponse.database;\n } else {\n config.database = args.database;\n }\n\n // Theme Selection - only if themes are available\n if (!args.theme && themeOptions.length > 0) {\n const themeResponse = await prompts({\n type: 'select',\n name: 'theme',\n message: 'Choisissez un thème:',\n choices: themeOptions,\n initial: 0,\n });\n config.theme = themeResponse.theme;\n } else {\n config.theme = args.theme || 'default';\n }\n\n // Plugin Selection - only if plugins are available\n if ((!args.plugins || args.plugins.length === 0) && pluginOptions.length > 0) {\n const pluginResponse = await prompts({\n type: 'multiselect',\n name: 'plugins',\n message: 'Choisissez les plugins à installer (Espace pour sélectionner, Entrée pour valider):',\n choices: pluginOptions,\n instructions: false,\n });\n config.plugins = pluginResponse.plugins || [];\n } else {\n config.plugins = args.plugins || [];\n }\n\n // Site Configuration\n if (!args.siteName || !args.adminName || !args.adminEmail || !args.adminPassword) {\n console.log(chalk.bold('\\n📝 Configuration du site:\\n'));\n\n const siteResponse = await prompts([\n {\n type: 'text',\n name: 'siteName',\n message: 'Nom du site:',\n initial: config.siteName,\n },\n {\n type: 'text',\n name: 'adminName',\n message: 'Nom de l\\'administrateur:',\n initial: config.adminName,\n },\n {\n type: 'text',\n name: 'adminEmail',\n message: 'Email de l\\'administrateur:',\n initial: config.adminEmail,\n validate: (value: string) => {\n if (!value) return 'L\\'email est requis';\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) return 'Email invalide';\n return true;\n },\n },\n {\n type: 'password',\n name: 'adminPassword',\n message: 'Mot de passe administrateur:',\n validate: (value: string) => {\n if (!value || value.length < 6) return 'Le mot de passe doit contenir au moins 6 caractères';\n return true;\n },\n },\n ]);\n\n config.siteName = siteResponse.siteName || config.siteName;\n config.adminName = siteResponse.adminName || config.adminName;\n config.adminEmail = siteResponse.adminEmail || config.adminEmail;\n config.adminPassword = siteResponse.adminPassword || config.adminPassword;\n } else {\n config.siteName = args.siteName;\n config.adminName = args.adminName;\n config.adminEmail = args.adminEmail;\n config.adminPassword = args.adminPassword;\n }\n\n // Post-install options\n if (args.installDeps === undefined || args.runMigrations === undefined) {\n console.log(chalk.bold('\\n⚙️ Options d\\'installation:\\n'));\n\n const installResponse = await prompts([\n {\n type: 'confirm',\n name: 'installDeps',\n message: 'Installer les dépendances (composer & npm)?',\n initial: true,\n },\n {\n type: 'confirm',\n name: 'runMigrations',\n message: 'Exécuter les migrations et seeder la base de données?',\n initial: true,\n },\n ]);\n\n config.installDeps = installResponse.installDeps !== undefined ? installResponse.installDeps : true;\n config.runMigrations = installResponse.runMigrations !== undefined ? installResponse.runMigrations : true;\n } else {\n config.installDeps = args.installDeps;\n config.runMigrations = args.runMigrations;\n }\n\n return config;\n}\n\nasync function downloadProject(targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Téléchargement d\\'ExilonCMS...');\n\n const emitter = degit('Exilon-Studios/ExilonCMS', {\n cache: false,\n force: true,\n verbose: false,\n });\n\n try {\n await emitter.clone(targetDir);\n spinner.succeed('ExilonCMS téléchargé avec succès');\n } catch (error) {\n spinner.fail('Erreur lors du téléchargement');\n throw error;\n }\n}\n\nasync function configureProject(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Configuration du projet...');\n\n try {\n // Configure .env file\n const envPath = path.join(targetDir, '.env');\n const envExamplePath = path.join(targetDir, '.env.example');\n\n if (await fs.pathExists(envExamplePath)) {\n let envContent = await fs.readFile(envExamplePath, 'utf-8');\n\n // Set database configuration\n if (config.database === 'sqlite') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=sqlite');\n envContent = envContent.replace(/#DB_DATABASE=.*/, 'DB_DATABASE=' + path.join(targetDir, 'database', 'database.sqlite'));\n } else if (config.database === 'postgresql') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=pgsql');\n envContent = envContent.replace(/DB_DATABASE=.*/, 'DB_DATABASE=exiloncms');\n envContent = envContent.replace(/DB_USERNAME=.*/, 'DB_USERNAME=postgres');\n } else if (config.database === 'mysql') {\n envContent = envContent.replace(/DB_CONNECTION=.*/, 'DB_CONNECTION=mysql');\n envContent = envContent.replace(/DB_DATABASE=.*/, 'DB_DATABASE=exiloncms');\n envContent = envContent.replace(/DB_USERNAME=.*/, 'DB_USERNAME=root');\n }\n\n // Set app name\n envContent = envContent.replace(/APP_NAME=.*/, `APP_NAME=\"${config.siteName}\"`);\n\n await fs.writeFile(envPath, envContent);\n }\n\n // Create SQLite database if selected\n if (config.database === 'sqlite') {\n const dbDir = path.join(targetDir, 'database');\n await fs.ensureDir(dbDir);\n const dbPath = path.join(dbDir, 'database.sqlite');\n if (!(await fs.pathExists(dbPath))) {\n await fs.writeFile(dbPath, '');\n }\n }\n\n // Create required directories\n const themesDir = path.join(targetDir, 'resources', 'themes');\n await fs.ensureDir(themesDir);\n\n const pluginsDir = path.join(targetDir, 'plugins');\n await fs.ensureDir(pluginsDir);\n\n // Generate APP_KEY\n spinner.text = 'Génération de la clé d\\'application...';\n await execaCommand('php artisan key:generate --force', { cwd: targetDir, stdio: 'inherit' });\n\n spinner.succeed('Projet configuré avec succès');\n } catch (error) {\n spinner.fail('Erreur lors de la configuration');\n throw error;\n }\n}\n\nasync function installDependencies(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n if (!config.installDeps) {\n spinner.info('Installation des dépendances skipée');\n return;\n }\n\n // Get Composer path - always use full path on Windows\n const isWindows = process.platform === 'win32';\n let composerCommand = 'composer';\n let needsCleanup = false;\n\n if (isWindows) {\n const composerBat = path.join(process.env.LOCALAPPDATA || '', 'Composer', 'composer.bat');\n if (await fs.pathExists(composerBat)) {\n // Create a temporary composer wrapper in the project directory\n const tempComposer = path.join(targetDir, 'composer.bat');\n await fs.copy(composerBat, tempComposer);\n composerCommand = `\"${tempComposer}\"`;\n needsCleanup = true;\n }\n }\n\n // Composer\n spinner.start('Installation des dépendances PHP (Composer)...');\n try {\n await execaCommand(`${composerCommand} install --no-interaction --quiet`, { cwd: targetDir });\n spinner.succeed('Dépendances PHP installées');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation Composer');\n throw error;\n } finally {\n // Cleanup temporary composer wrapper\n if (needsCleanup) {\n const tempComposer = path.join(targetDir, 'composer.bat');\n if (await fs.pathExists(tempComposer)) {\n await fs.remove(tempComposer);\n }\n }\n }\n\n // NPM\n spinner.start('Installation des dépendances Node.js...');\n try {\n await execaCommand('npm install --silent', { cwd: targetDir });\n spinner.succeed('Dépendances Node.js installées');\n } catch (error) {\n spinner.fail('Erreur lors de l\\'installation NPM');\n throw error;\n }\n\n // Build assets\n spinner.start('Construction des assets...');\n try {\n await execaCommand('npm run build', { cwd: targetDir });\n spinner.succeed('Assets construits');\n } catch (error) {\n spinner.warn('Erreur lors du build des assets (non-critique)');\n }\n}\n\nasync function runMigrationsAndSeed(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n if (!config.runMigrations) {\n spinner.info('Migrations skipées');\n return;\n }\n\n spinner.start('Exécution des migrations et seeder...');\n try {\n // For SQLite, we use migrate:fresh which is safe for fresh install\n const command = config.database === 'sqlite'\n ? 'php artisan migrate:fresh --seed --force'\n : 'php artisan migrate --seed --force';\n\n await execaCommand(command, {\n cwd: targetDir,\n stdio: 'inherit',\n });\n\n spinner.succeed('Base de données initialisée');\n } catch (error) {\n spinner.fail('Erreur lors des migrations');\n throw error;\n }\n}\n\nasync function createAdminUser(config: ProjectConfig, targetDir: string, spinner: ReturnType<typeof ora>): Promise<void> {\n spinner.start('Création de l\\'utilisateur admin...');\n try {\n await execaCommand(\n `php artisan user:create --admin --name=\"${config.adminName}\" --email=\"${config.adminEmail}\" --password=\"${config.adminPassword}\"`,\n { cwd: targetDir, stdio: 'inherit' }\n );\n spinner.succeed('Utilisateur admin créé');\n } catch (error) {\n spinner.warn('Erreur lors de la création de l\\'admin (peut-être déjà créé via seeder)');\n }\n}\n\n// Create custom admin seeder to override default credentials\nasync function createCustomAdminSeeder(config: ProjectConfig, targetDir: string): Promise<void> {\n const seederPath = path.join(targetDir, 'database/seeders/CustomAdminSeeder.php');\n const seederContent = `<?php\n\nnamespace Database\\\\Seeders;\n\nuse ExilonCMS\\\\Models\\\\User;\nuse ExilonCMS\\\\Models\\\\Role;\nuse ExilonCMS\\\\Models\\\\Permission;\nuse Illuminate\\\\Database\\\\Console\\\\Seeds\\\\WithoutModelEvents;\nuse Illuminate\\\\Database\\\\Seeder;\nuse Illuminate\\\\Support\\\\Facades\\\\Hash;\n\nclass CustomAdminSeeder extends Seeder\n{\n use WithoutModelEvents;\n\n public function run(): void\n {\n // Create admin role if it doesn't exist\n $adminRole = Role::firstOrCreate(\n ['name' => 'admin'],\n [\n 'color' => 'FF0000',\n 'is_admin' => true,\n 'power' => 100,\n ]\n );\n\n // Create admin user with custom credentials\n $admin = User::firstOrCreate(\n ['email' => '${config.adminEmail}'],\n [\n 'name' => '${config.adminName}',\n 'password' => Hash::make('${config.adminPassword}'),\n 'role_id' => $adminRole->id,\n 'email_verified_at' => now(),\n 'password_changed_at' => now(),\n ]\n );\n\n // Create all permissions for admin role\n if ($adminRole->permissions()->count() === 0) {\n foreach (Permission::permissions() as $permission) {\n Permission::create([\n 'permission' => $permission,\n 'role_id' => $adminRole->id,\n ]);\n }\n }\n }\n}\n`;\n\n await fs.writeFile(seederPath, seederContent);\n\n // Update DatabaseSeeder to use CustomAdminSeeder instead of AdminUserSeeder\n const databaseSeederPath = path.join(targetDir, 'database/seeders/DatabaseSeeder.php');\n let databaseSeederContent = await fs.readFile(databaseSeederPath, 'utf-8');\n\n // Replace AdminUserSeeder with CustomAdminSeeder in the call array\n databaseSeederContent = databaseSeederContent.replace(\n /AdminUserSeeder::class/,\n 'CustomAdminSeeder::class'\n );\n\n await fs.writeFile(databaseSeederPath, databaseSeederContent);\n}\n\n// Install plugins from marketplace\nasync function installPlugins(config: ProjectConfig, targetDir: string, registry: MarketplaceRegistry | null, spinner: ReturnType<typeof ora>): Promise<void> {\n if (config.plugins.length === 0) {\n return;\n }\n\n if (!registry) {\n spinner.warn('Marketplace non disponible, impossible d\\'installer les plugins');\n return;\n }\n\n for (const pluginId of config.plugins) {\n const plugin = registry.plugins.find(p => p.extension_id === pluginId);\n if (!plugin) {\n spinner.warn(`Plugin ${pluginId} non trouvé dans le marketplace`);\n continue;\n }\n\n spinner.start(`Installation du plugin ${plugin.name}...`);\n try {\n // Download plugin zip\n const pluginZipPath = path.join(targetDir, 'temp_plugin.zip');\n const response = await fetch(plugin.url);\n const buffer = await response.arrayBuffer();\n await fs.writeFile(pluginZipPath, Buffer.from(buffer));\n\n // Extract using platform-specific command\n const pluginsDir = path.join(targetDir, 'plugins');\n await fs.ensureDir(pluginsDir);\n\n // Detect platform and use appropriate unzip command\n const isWindows = process.platform === 'win32';\n\n if (isWindows) {\n // Use PowerShell's Expand-Archive on Windows\n await execaCommand(\n `powershell -Command \"Expand-Archive -Path '${pluginZipPath}' -DestinationPath '${pluginsDir}' -Force\"`,\n { cwd: targetDir }\n );\n } else {\n // Use unzip command on Linux/Mac\n await execaCommand(`unzip -o \"${pluginZipPath}\" -d \"${pluginsDir}\"`, { cwd: targetDir });\n }\n\n // Clean up\n await fs.remove(pluginZipPath);\n\n spinner.succeed(`Plugin ${plugin.name} installé`);\n } catch (error) {\n spinner.fail(`Erreur lors de l'installation du plugin ${plugin.name}`);\n console.error(error);\n }\n }\n}\n\nfunction printSuccessMessage(config: ProjectConfig, targetDir: string): void {\n console.log(chalk.bold('\\n✨ Installation terminée avec succès!\\n'));\n\n console.log(chalk.cyan(' Projet créé dans: ') + chalk.white(targetDir));\n console.log(chalk.cyan(' Base de données: ') + chalk.white(config.database));\n console.log(chalk.cyan(' Thème: ') + chalk.white(config.theme));\n\n if (config.plugins.length > 0) {\n console.log(chalk.cyan(' Plugins installés: ') + chalk.white(config.plugins.join(', ')));\n }\n\n console.log(chalk.bold('\\n🚀 Prochaines étapes:\\n'));\n\n console.log(` ${chalk.cyan('1.')} Aller dans le dossier du projet:`);\n console.log(` ${chalk.gray(`cd ${config.projectName}`)}\\n`);\n\n if (!config.installDeps) {\n console.log(` ${chalk.cyan('2.')} Installer les dépendances:`);\n console.log(` ${chalk.gray('composer install')}`);\n console.log(` ${chalk.gray('npm install')}`);\n console.log(` ${chalk.gray('npm run build')}\\n`);\n }\n\n if (!config.runMigrations) {\n console.log(` ${chalk.cyan('3.')} Configurer la base de données et lancer les migrations:`);\n if (config.database !== 'sqlite') {\n console.log(` ${chalk.yellow('⚠️ Configurez votre base de données dans .env d\\'abord')}`);\n }\n console.log(` ${chalk.gray('php artisan migrate:fresh --seed')}\\n`);\n }\n\n console.log(` ${chalk.cyan('4.')} Démarrer le serveur de développement:`);\n console.log(` ${chalk.gray('php artisan serve')}\\n`);\n\n if (config.database === 'sqlite') {\n console.log(` ${chalk.green('✓')} SQLite utilisé - aucune configuration de base de données nécessaire!\\n`);\n } else {\n console.log(` ${chalk.yellow('⚠️ ')} Configurez votre base de données ${config.database} dans ${chalk.gray('.env')}\\n`);\n }\n\n console.log(chalk.bold('📧 Identifiants admin:\\n'));\n console.log(` Email: ${chalk.cyan(config.adminEmail)}`);\n console.log(` Password: ${chalk.cyan(config.adminPassword)}\\n`);\n\n console.log(chalk.gray(' ' + '─'.repeat(60) + '\\n'));\n\n console.log(` ${chalk.cyan('Documentation:')} https://github.com/Exilon-Studios/ExilonCMS/wiki\\n`);\n}\n\nasync function createCommand(projectName: string, options: any): Promise<void> {\n const spinner = ora();\n\n try {\n // Check dependencies first\n console.log(chalk.bold('\\n🔍 Vérification des dépendances...\\n'));\n await checkDependencies(spinner);\n\n // Fetch marketplace registry\n const registry = await fetchMarketplaceRegistry();\n\n const config = await promptForConfig({\n projectName,\n database: options.database,\n theme: options.theme,\n plugins: options.plugins ? options.plugins.split(',') : [],\n siteName: options.siteName,\n adminName: options.adminName,\n adminEmail: options.adminEmail,\n adminPassword: options.adminPassword,\n installDeps: options.installDeps,\n runMigrations: options.runMigrations,\n }, registry);\n\n const targetDir = path.resolve(process.cwd(), config.projectName);\n\n // Check if directory exists\n if (await fs.pathExists(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Le dossier ${config.projectName} existe déjà. Écraser?`,\n initial: false,\n });\n\n if (!overwrite) {\n console.log(chalk.yellow('\\nInstallation annulée.'));\n process.exit(0);\n }\n\n await fs.remove(targetDir);\n }\n\n // Download project\n await downloadProject(targetDir, spinner);\n\n // Install dependencies FIRST\n await installDependencies(config, targetDir, spinner);\n\n // Configure project (needs artisan which needs composer dependencies)\n await configureProject(config, targetDir, spinner);\n\n // Create custom admin seeder with user's credentials\n await createCustomAdminSeeder(config, targetDir);\n\n // Run migrations (will use custom admin seeder)\n await runMigrationsAndSeed(config, targetDir, spinner);\n\n // Install plugins from marketplace\n await installPlugins(config, targetDir, registry, spinner);\n\n // Print success message\n printSuccessMessage(config, targetDir);\n\n } catch (error: any) {\n if (error.message === 'user cancelled') {\n console.log(chalk.yellow('\\nInstallation annulée.'));\n process.exit(0);\n }\n\n console.error(chalk.red('\\n✖ Erreur:'), error.message);\n process.exit(1);\n }\n}\n\n// CLI Program\nconst program = new Command();\n\nprogram\n .name('exiloncms')\n .description('Create a new ExilonCMS project')\n .version(packageJson.version);\n\nprogram\n .command('create [project-name]')\n .description('Create a new ExilonCMS project')\n .option('-d, --database <type>', 'Database type (sqlite, postgresql, mysql)', 'sqlite')\n .option('-t, --theme <name>', 'Theme name', 'default')\n .option('-p, --plugins <list>', 'Comma-separated list of plugins')\n .option('--site-name <name>', 'Site name')\n .option('--admin-name <name>', 'Admin name')\n .option('--admin-email <email>', 'Admin email')\n .option('--admin-password <password>', 'Admin password')\n .option('--no-install-deps', 'Skip installing dependencies')\n .option('--no-run-migrations', 'Skip running migrations')\n .action(createCommand);\n\nprogram\n .command('new [project-name]')\n .description('Alias for create')\n .option('-d, --database <type>', 'Database type (sqlite, postgresql, mysql)', 'sqlite')\n .option('-t, --theme <name>', 'Theme name', 'default')\n .option('-p, --plugins <list>', 'Comma-separated list of plugins')\n .option('--site-name <name>', 'Site name')\n .option('--admin-name <name>', 'Admin name')\n .option('--admin-email <email>', 'Admin email')\n .option('--admin-password <password>', 'Admin password')\n .option('--no-install-deps', 'Skip installing dependencies')\n .option('--no-run-migrations', 'Skip running migrations')\n .action(createCommand);\n\nprogram.parse();\n"],"mappings":"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","names":[]}
|