UNPKG

@orchard9ai/create-vite-vike-tauri

Version:
953 lines (945 loc) 35.2 kB
#!/usr/bin/env node var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/esm_shims.js import path from "path"; import { fileURLToPath } from "url"; var init_esm_shims = __esm({ "../../node_modules/.pnpm/tsup@8.5.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/esm_shims.js"() { "use strict"; } }); // src/utils/TemplateEngine.ts import path3 from "path"; import fs2 from "fs-extra"; import { fileURLToPath as fileURLToPath2 } from "url"; var TemplateEngine; var init_TemplateEngine = __esm({ "src/utils/TemplateEngine.ts"() { "use strict"; init_esm_shims(); TemplateEngine = class { constructor(context) { const __dirname3 = path3.dirname(fileURLToPath2(import.meta.url)); this.templatesDir = __dirname3.includes("/dist") ? path3.join(__dirname3, "../templates") : path3.join(__dirname3, "../../templates"); this.context = context; } /** * Process a template file and substitute variables */ processTemplate(templateContent) { let processed = templateContent; Object.entries(this.context).forEach(([key, value]) => { const placeholder = `{{${key}}}`; processed = processed.replace(new RegExp(placeholder, "g"), value); }); return processed; } /** * Copy base template files to target directory */ async copyBaseTemplate(targetDir) { const baseTemplateDir = path3.join(this.templatesDir, "base"); await this.copyTemplateDirectory(baseTemplateDir, targetDir); } /** * Copy Vike template files to target directory */ async copyVikeTemplate(targetDir) { const vikeTemplateDir = path3.join(this.templatesDir, "vike"); await this.copyTemplateDirectory(vikeTemplateDir, targetDir); await this.mergePackageJsonAdditions(targetDir, "vike"); } /** * Copy mobile template files to target directory */ async copyMobileTemplate(targetDir) { const mobileTemplateDir = path3.join(this.templatesDir, "mobile"); if (await fs2.pathExists(mobileTemplateDir)) { await this.copyTemplateDirectory(mobileTemplateDir, targetDir); await this.mergePackageJsonAdditions(targetDir, "mobile"); } } /** * Copy notification template files to target directory */ async copyNotificationTemplate(targetDir) { const notificationTemplateDir = path3.join(this.templatesDir, "notifications"); if (await fs2.pathExists(notificationTemplateDir)) { await this.copyTemplateDirectory(notificationTemplateDir, targetDir); await this.addNotificationDependencies(targetDir); await this.addNotificationCapabilities(targetDir); } } /** * Copy a template directory recursively, processing templates */ async copyTemplateDirectory(sourceDir, targetDir) { if (!await fs2.pathExists(sourceDir)) { return; } const items = await fs2.readdir(sourceDir, { withFileTypes: true }); for (const item of items) { const sourcePath = path3.join(sourceDir, item.name); const targetPath = path3.join(targetDir, this.getTargetFilename(item.name)); if (item.isDirectory()) { await fs2.ensureDir(targetPath); await this.copyTemplateDirectory(sourcePath, targetPath); } else { await fs2.ensureDir(path3.dirname(targetPath)); if (this.isTemplateFile(item.name)) { const templateContent = await fs2.readFile(sourcePath, "utf-8"); const processedContent = this.processTemplate(templateContent); await fs2.writeFile(targetPath, processedContent); } else { await fs2.copy(sourcePath, targetPath); } } } } /** * Merge package.json additions for a specific template type */ async mergePackageJsonAdditions(targetDir, templateType) { const additionsPath = path3.join(this.templatesDir, templateType, "package.json.additions.json"); if (await fs2.pathExists(additionsPath)) { const packageJsonPath = path3.join(targetDir, "package.json"); const additions = await fs2.readJson(additionsPath); const existingPackageJson = await fs2.readJson(packageJsonPath); if (additions.scripts) { existingPackageJson.scripts = { ...existingPackageJson.scripts, ...additions.scripts }; } if (additions.dependencies) { existingPackageJson.dependencies = { ...existingPackageJson.dependencies, ...additions.dependencies }; } if (additions.devDependencies) { existingPackageJson.devDependencies = { ...existingPackageJson.devDependencies, ...additions.devDependencies }; } await fs2.writeJson(packageJsonPath, existingPackageJson, { spaces: 2 }); } } /** * Add notification dependencies to package.json and Cargo.toml */ async addNotificationDependencies(targetDir) { const packageJsonPath = path3.join(targetDir, "package.json"); if (await fs2.pathExists(packageJsonPath)) { const packageJson2 = await fs2.readJson(packageJsonPath); if (!packageJson2.dependencies) { packageJson2.dependencies = {}; } packageJson2.dependencies["@tauri-apps/plugin-notification"] = "^2.0.0"; await fs2.writeJson(packageJsonPath, packageJson2, { spaces: 2 }); } const cargoTomlPath = path3.join(targetDir, "src-tauri", "Cargo.toml"); if (await fs2.pathExists(cargoTomlPath)) { let cargoContent = await fs2.readFile(cargoTomlPath, "utf-8"); if (!cargoContent.includes("tauri-plugin-notification")) { const dependenciesMatch = cargoContent.match(/\[dependencies\]/); if (dependenciesMatch) { const insertIndex = dependenciesMatch.index + dependenciesMatch[0].length; const beforeDeps = cargoContent.slice(0, insertIndex); const afterDeps = cargoContent.slice(insertIndex); cargoContent = beforeDeps + '\ntauri-plugin-notification = "2"' + afterDeps; await fs2.writeFile(cargoTomlPath, cargoContent); } } } const libRsPath = path3.join(targetDir, "src-tauri", "src", "lib.rs"); if (await fs2.pathExists(libRsPath)) { let libContent = await fs2.readFile(libRsPath, "utf-8"); if (!libContent.includes("tauri_plugin_notification::init()")) { libContent = libContent.replace( /\.plugin\(tauri_plugin_os::init\(\)\)/g, ".plugin(tauri_plugin_os::init())\n .plugin(tauri_plugin_notification::init())" ); await fs2.writeFile(libRsPath, libContent); } } } /** * Add notification capabilities by overwriting existing capabilities files */ async addNotificationCapabilities(targetDir) { const capabilitiesDir = path3.join(targetDir, "src-tauri", "capabilities"); const notificationCapabilitiesDir = path3.join( this.templatesDir, "notifications", "capabilities" ); if (await fs2.pathExists(notificationCapabilitiesDir)) { const files = await fs2.readdir(notificationCapabilitiesDir); for (const file of files) { const sourcePath = path3.join(notificationCapabilitiesDir, file); const targetPath = path3.join(capabilitiesDir, file); await fs2.copy(sourcePath, targetPath); } } } /** * Check if a file is a template file (ends with .template) */ isTemplateFile(filename) { return filename.endsWith(".template"); } /** * Get the target filename by removing .template extension */ getTargetFilename(filename) { if (this.isTemplateFile(filename)) { return filename.replace(/\.template$/, ""); } return filename; } /** * Get list of files that would be created (for dry run) */ async getFilesToCreate(options) { const files = []; await this.collectFiles(path3.join(this.templatesDir, "base"), "", files); if (options.vike) { await this.collectFiles(path3.join(this.templatesDir, "vike"), "", files); } if (options.mobile) { const mobileDir = path3.join(this.templatesDir, "mobile"); if (await fs2.pathExists(mobileDir)) { await this.collectFiles(mobileDir, "", files); } } if (options.notifications) { const notificationDir = path3.join(this.templatesDir, "notifications"); if (await fs2.pathExists(notificationDir)) { await this.collectFiles(notificationDir, "", files); } } return files.map((file) => this.getTargetFilename(file)); } /** * Recursively collect all files in a directory */ async collectFiles(dir, relativePath, files) { if (!await fs2.pathExists(dir)) { return; } const items = await fs2.readdir(dir, { withFileTypes: true }); for (const item of items) { const itemPath = path3.join(relativePath, item.name); if (item.isDirectory()) { await this.collectFiles(path3.join(dir, item.name), itemPath, files); } else if (!item.name.endsWith(".additions.json")) { files.push(itemPath); } } } }; } }); // src/generators/ProjectGenerator.ts var ProjectGenerator_exports = {}; __export(ProjectGenerator_exports, { ProjectGenerator: () => ProjectGenerator }); import path4 from "path"; import fs3 from "fs-extra"; import { spawn as spawn2 } from "child_process"; var ProjectGenerator; var init_ProjectGenerator = __esm({ "src/generators/ProjectGenerator.ts"() { "use strict"; init_esm_shims(); init_TemplateEngine(); ProjectGenerator = class { constructor(options) { this.options = options; const context = { PROJECT_NAME: options.name, PROJECT_IDENTIFIER: options.name.replace(/[^a-zA-Z0-9]/g, ""), PACKAGE_MANAGER: options.packageManager || "pnpm", BEFORE_DEV_COMMAND: options.vike ? "pnpm dev:vike" : "pnpm dev", BEFORE_BUILD_COMMAND: options.vike ? "pnpm build:vike" : "pnpm build", PROJECT_TITLE: options.seo?.title || "", PROJECT_DESCRIPTION: options.seo?.description || "", PROJECT_KEYWORDS: options.seo?.keywords || "", PROJECT_AUTHOR: options.seo?.author || "" }; this.templateEngine = new TemplateEngine(context); } async generate() { try { const { targetDir, dryRun } = this.options; if (dryRun) { return this.dryRun(); } await fs3.ensureDir(targetDir); await this.templateEngine.copyBaseTemplate(targetDir); if (this.options.vike) { await this.templateEngine.copyVikeTemplate(targetDir); } if (this.options.mobile) { await this.templateEngine.copyMobileTemplate(targetDir); } if (this.options.notifications) { await this.templateEngine.copyNotificationTemplate(targetDir); } if (!this.options.skipInstall) { await this.installDependencies(); } if (this.options.mobile && !this.options.skipInstall) { await this.initializeMobilePlatforms(); } if (!this.options.skipGit) { await this.initializeGit(); } return { projectPath: targetDir, success: true, nextSteps: this.getNextSteps() }; } catch (error) { return { projectPath: this.options.targetDir, success: false, errors: [error instanceof Error ? error.message : "Unknown error"], nextSteps: [] }; } } async dryRun() { const files = await this.templateEngine.getFilesToCreate({ vike: Boolean(this.options.vike), mobile: Boolean(this.options.mobile), notifications: Boolean(this.options.notifications) }); console.info("\n\u{1F4C1} Files that would be created:"); files.forEach((file) => { console.info(` ${path4.join(this.options.targetDir, file)}`); }); return { projectPath: this.options.targetDir, success: true, nextSteps: this.getNextSteps() }; } async installDependencies() { try { await this.runPackageCommand("install", []); } catch (error) { throw new Error(`Failed to install dependencies: ${error}`); } } async runPackageCommand(command, packages, isDev = false) { const { packageManager = "pnpm", targetDir } = this.options; const args = [command]; if (isDev) { args.push("-D"); } args.push(...packages); if (packageManager === "pnpm") { args.push("--ignore-workspace"); } const child = spawn2(packageManager, args, { cwd: targetDir, stdio: "inherit", shell: true }); return new Promise((resolve, reject) => { child.on("close", (code) => { if (code === 0) { resolve(); } else { reject(new Error(`${packageManager} ${command} failed with code ${code}`)); } }); }); } async initializeMobilePlatforms() { console.info("\n\u{1F4F1} Initializing mobile platforms..."); if (process.platform === "darwin") { try { console.info(" Initializing iOS platform..."); await this.runTauriCommand(["ios", "init"]); console.info(" \u2705 iOS platform initialized"); } catch (error) { console.warn( ` \u26A0\uFE0F iOS initialization failed: ${error instanceof Error ? error.message : String(error)}` ); console.warn(" Make sure Xcode is installed and try running: pnpm tauri ios init"); } } if (process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT) { try { console.info(" Initializing Android platform..."); await this.runTauriCommand(["android", "init"]); console.info(" \u2705 Android platform initialized"); } catch (error) { console.warn( ` \u26A0\uFE0F Android initialization failed: ${error instanceof Error ? error.message : String(error)}` ); console.warn(" Make sure Android SDK is installed and ANDROID_HOME is set"); console.warn(" Then try running: pnpm tauri android init"); } } else { console.warn(" \u26A0\uFE0F Android SDK not found (ANDROID_HOME not set)"); console.warn(" Install Android Studio and set ANDROID_HOME environment variable"); console.warn(" See MOBILE_SETUP.md for detailed setup instructions"); console.warn(" Then run: pnpm tauri android init"); } } async runTauriCommand(args) { const { packageManager = "pnpm", targetDir } = this.options; const command = packageManager === "npm" ? "npx" : packageManager; const fullArgs = command === "npx" ? ["tauri", ...args] : ["tauri", ...args]; const child = spawn2(command, fullArgs, { cwd: targetDir, stdio: "inherit", shell: true }); return new Promise((resolve, reject) => { child.on("close", (code) => { if (code === 0) { resolve(); } else { reject(new Error(`tauri ${args.join(" ")} failed with code ${code}`)); } }); }); } async initializeGit() { try { const child = spawn2("git", ["init"], { cwd: this.options.targetDir, stdio: "inherit", shell: true }); return new Promise((resolve, reject) => { child.on("close", (code) => { if (code === 0) { resolve(); } else { reject(new Error(`git init failed with code ${code}`)); } }); }); } catch (error) { throw new Error(`Failed to initialize git: ${error}`); } } getNextSteps() { const { name, packageManager = "pnpm", vike, mobile, skipInstall } = this.options; const steps = [`cd ${name}`]; if (skipInstall) { steps.push(`${packageManager} install`); } if (mobile && skipInstall) { if (process.platform === "darwin") { steps.push(`${packageManager} tauri ios init # Initialize iOS platform`); } steps.push(`${packageManager} tauri android init # Initialize Android platform`); } if (vike) { steps.push(`${packageManager} run dev:vike # Start Vike dev server`); steps.push(`${packageManager} run tauri:dev # Start Tauri app`); } else { steps.push(`${packageManager} run tauri:dev # Start development`); } if (mobile) { steps.push(""); steps.push("\u{1F4F1} Mobile Development:"); if (process.platform === "darwin") { steps.push(`${packageManager} tauri ios dev # Run on iOS simulator/device`); } steps.push(`${packageManager} tauri android dev # Run on Android emulator/device`); } steps.push(""); steps.push(`${packageManager} run tauri:build # Build for production`); return steps; } }; } }); // src/cli.ts init_esm_shims(); import { program } from "commander"; import chalk from "chalk"; import inquirer from "inquirer"; import ora from "ora"; import path5 from "path"; import fs4 from "fs-extra"; import { fileURLToPath as fileURLToPath3 } from "url"; // src/index.ts init_esm_shims(); // src/utils/validators.ts init_esm_shims(); import path2 from "path"; import fs from "fs-extra"; import { spawn } from "child_process"; import validateNpmName from "validate-npm-package-name"; function validateProjectName(name) { const errors = []; const warnings = []; if (!name || typeof name !== "string") { return { valid: false, errors: ["Project name is required"], warnings: [] }; } if (name.trim() !== name) { errors.push("Project name cannot have leading or trailing whitespace"); } if (name.length === 0) { errors.push("Project name cannot be empty"); } if (name.length > 214) { errors.push("Project name cannot be longer than 214 characters"); } const reservedNames = [ "node_modules", "favicon.ico", "package.json", "package-lock.json", "pnpm-lock.yaml", "yarn.lock", "npm", "pnpm", "yarn", "node", "git", "src", "dist", "build", "public", "static", "assets", "components", "pages", "styles", "scripts", "config", "test", "tests", "__tests__", "spec", "specs", "__spec__", ".git", ".gitignore", ".env", ".env.local", ".env.development", ".env.production", "readme", "readme.md", "license", "license.md", "changelog", "changelog.md", "contributing", "contributing.md" ]; if (reservedNames.includes(name.toLowerCase())) { errors.push(`Project name "${name}" is reserved and cannot be used`); } const invalidChars = /[<>:"/\\|?*\x00-\x1f]/; if (invalidChars.test(name)) { errors.push("Project name contains invalid characters for file systems"); } const windowsReserved = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i; if (windowsReserved.test(name)) { errors.push(`Project name "${name}" is reserved on Windows systems`); } const npmValidation = validateNpmName(name); if (!npmValidation.validForNewPackages) { errors.push(...npmValidation.errors || []); warnings.push(...npmValidation.warnings || []); } return { valid: errors.length === 0, errors, warnings }; } async function validateTargetPath(targetPath) { const errors = []; const warnings = []; if (!targetPath || typeof targetPath !== "string") { return { valid: false, errors: ["Target path is required"], warnings: [] }; } try { const resolvedPath = path2.resolve(targetPath); if (resolvedPath.length > 250) { warnings.push("Target path is very long and may cause issues on some systems"); } const parentDir = path2.dirname(resolvedPath); try { const parentStats = await fs.stat(parentDir); if (!parentStats.isDirectory()) { errors.push("Parent directory is not a directory"); } else { try { await fs.access(parentDir, fs.constants.W_OK); } catch { errors.push("Parent directory is not writable"); } } } catch { errors.push("Parent directory does not exist or is not accessible"); } if (await fs.pathExists(resolvedPath)) { const stats = await fs.stat(resolvedPath); if (stats.isDirectory()) { const items = await fs.readdir(resolvedPath); if (items.length > 0) { warnings.push("Target directory exists and is not empty"); } } else { errors.push("Target path exists but is not a directory"); } } const pathComponents = resolvedPath.split(path2.sep); for (const component of pathComponents) { if (component.startsWith(".") && component !== "." && component !== "..") { warnings.push("Path contains hidden directories"); break; } } } catch (error) { errors.push( `Path validation failed: ${error instanceof Error ? error.message : "Unknown error"}` ); } return { valid: errors.length === 0, errors, warnings }; } async function checkCommand(command) { return new Promise((resolve) => { const child = spawn(command, ["--version"], { stdio: "ignore", shell: true }); child.on("close", (code) => { resolve(code === 0); }); child.on("error", () => { resolve(false); }); setTimeout(() => { child.kill(); resolve(false); }, 5e3); }); } async function verifySystemRequirements(packageManager = "pnpm") { const errors = []; const warnings = []; let node = false; let rust = false; let packageManagerAvailable = false; try { const nodeVersion = process.version; const versionParts = nodeVersion.split("."); if (versionParts.length > 0 && versionParts[0]) { const major = parseInt(versionParts[0].substring(1)); if (major >= 18) { node = true; if (major < 20) { warnings.push(`Node.js ${nodeVersion} works but Node.js 20+ is recommended`); } } else { errors.push(`Node.js 18+ required (found ${nodeVersion})`); } } else { errors.push("Could not parse Node.js version"); } } catch { errors.push("Could not determine Node.js version"); } try { rust = await checkCommand("rustc"); if (!rust) { errors.push("Rust is required for Tauri development. Install from https://rustup.rs/"); } else { const cargoAvailable = await checkCommand("cargo"); if (!cargoAvailable) { warnings.push("Cargo not found, but Rust is available"); } } } catch { errors.push("Could not check Rust installation"); } try { packageManagerAvailable = await checkCommand(packageManager); if (!packageManagerAvailable) { errors.push(`${packageManager} is not installed or not available in PATH`); if (packageManager === "pnpm") { warnings.push("You can install pnpm with: npm install -g pnpm"); } else if (packageManager === "yarn") { warnings.push("You can install yarn with: npm install -g yarn"); } } } catch { errors.push(`Could not check ${packageManager} installation`); } if (process.platform === "linux") { warnings.push( "On Linux, you may need additional dependencies. See: https://tauri.app/v1/guides/getting-started/prerequisites#setting-up-linux" ); } return { node, rust, packageManager: packageManagerAvailable, errors, warnings }; } async function validateProjectOptions(options) { const errors = []; const warnings = []; const nameValidation = validateProjectName(options.name); errors.push(...nameValidation.errors); warnings.push(...nameValidation.warnings); const pathValidation = await validateTargetPath(options.targetDir); errors.push(...pathValidation.errors); warnings.push(...pathValidation.warnings); const systemValidation = await verifySystemRequirements(options.packageManager); errors.push(...systemValidation.errors); warnings.push(...systemValidation.warnings); return { valid: errors.length === 0, errors, warnings }; } // src/index.ts async function createApp(options) { const { ProjectGenerator: ProjectGenerator2 } = await Promise.resolve().then(() => (init_ProjectGenerator(), ProjectGenerator_exports)); const generator = new ProjectGenerator2(options); return await generator.generate(); } // src/cli.ts var __dirname2 = path5.dirname(fileURLToPath3(import.meta.url)); var packageJson = JSON.parse(fs4.readFileSync(path5.join(__dirname2, "../package.json"), "utf-8")); var version = packageJson.version; program.name("create-vite-vike-tauri").description("Create a new Vite + Vike + Tauri application with Orchard9 design system").version(version).argument("[name]", "project name").option("--vike", "add Vike SSR support").option("--mobile", "add mobile platform support (iOS/Android)").option("--notifications", "add native notification support with examples").option("--skip-install", "skip dependency installation").option("--skip-git", "skip git initialization").option("--dry-run", "preview what would be created without actually creating files").option("--pnpm", "use pnpm as package manager (default)").option("--npm", "use npm as package manager").option("--yarn", "use yarn as package manager").action(async (name, options) => { console.log( chalk.blue(` \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557 \u2551 Orchard9 Vite + Vike + Tauri Creator \u2551 \u2551 Version ${version} \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D `) ); try { let packageManager = "pnpm"; if (options.npm) packageManager = "npm"; if (options.yarn) packageManager = "yarn"; if (!name) { const { projectName } = await inquirer.prompt([ { type: "input", name: "projectName", message: "What is your project name?", default: "my-tauri-app", validate: (input) => { const validation = validateProjectName(input); if (!validation.valid) { return validation.errors.join(", "); } return true; } } ]); name = projectName; } const targetDir = path5.resolve(process.cwd(), name); const spinner = ora("Validating project options...").start(); try { const validation = await validateProjectOptions({ name, targetDir, packageManager }); if (!validation.valid) { spinner.fail("Validation failed"); console.error(chalk.red("\nValidation errors:")); validation.errors.forEach((err) => console.error(chalk.red(` - ${err}`))); if (validation.warnings.length > 0) { console.warn(chalk.yellow("\nWarnings:")); validation.warnings.forEach((warn) => console.warn(chalk.yellow(` - ${warn}`))); } process.exit(1); } if (validation.warnings.length > 0) { spinner.warn("Validation completed with warnings"); console.warn(chalk.yellow("\nWarnings:")); validation.warnings.forEach((warn) => console.warn(chalk.yellow(` - ${warn}`))); } else { spinner.succeed("Project options validated"); } } catch (error) { spinner.fail("Validation failed"); console.error( chalk.red( ` Validation error: ${error instanceof Error ? error.message : "Unknown error"}` ) ); process.exit(1); } const isCI = process.env["CI"] === "true" || process.env["NODE_ENV"] === "test"; const needsPrompts = !options.dryRun && !isCI && (options.vike === void 0 || options.mobile === void 0 || options.notifications === void 0); const answers = needsPrompts ? await inquirer.prompt([ { type: "confirm", name: "vike", message: "Add Vike SSR support?", default: false, when: () => options.vike === void 0 }, { type: "confirm", name: "mobile", message: "Add mobile platform support (iOS/Android)?", default: false, when: () => options.mobile === void 0 }, { type: "confirm", name: "notifications", message: "Add native notification support with examples?", default: false, when: () => options.notifications === void 0 } ]) : {}; const vikeEnabled = options.vike ?? answers["vike"] ?? false; const seoAnswers = needsPrompts && vikeEnabled ? await inquirer.prompt([ { type: "input", name: "title", message: "Project title (for SEO):", default: name.charAt(0).toUpperCase() + name.slice(1), validate: (input) => input.trim().length > 0 || "Title is required" }, { type: "input", name: "description", message: "Project description (for SEO):", default: `A modern Vite + Vike + Tauri application`, validate: (input) => input.trim().length > 0 || "Description is required" }, { type: "input", name: "keywords", message: "Keywords (comma-separated):", default: "vite,vike,tauri,react,typescript" }, { type: "input", name: "author", message: "Author name:", default: "Your Name" } ]) : {}; const finalOptions = { name, vike: vikeEnabled, mobile: options.mobile ?? answers["mobile"] ?? false, notifications: options.notifications ?? answers["notifications"] ?? false, skipInstall: options.skipInstall, skipGit: options.skipGit, dryRun: options.dryRun, packageManager, seo: { title: seoAnswers["title"] || name.charAt(0).toUpperCase() + name.slice(1), description: seoAnswers["description"] || `A modern Vite + Vike + Tauri application`, keywords: seoAnswers["keywords"] || "vite,vike,tauri,react,typescript", author: seoAnswers["author"] || "Your Name" } }; console.log(chalk.cyan("\nProject configuration:")); console.log(chalk.gray(` Name: ${finalOptions.name}`)); console.log(chalk.gray(` Location: ${targetDir}`)); console.log(chalk.gray(` Package Manager: ${finalOptions.packageManager}`)); console.log(chalk.gray(` Vike SSR: ${finalOptions.vike ? "Yes" : "No"}`)); console.log(chalk.gray(` Mobile Support: ${finalOptions.mobile ? "Yes" : "No"}`)); console.log(chalk.gray(` Notifications: ${finalOptions.notifications ? "Yes" : "No"}`)); if (finalOptions.dryRun) { console.log(chalk.yellow("\n\u{1F50D} Dry run mode - no files will be created")); } if (fs4.existsSync(targetDir) && !finalOptions.dryRun) { const { overwrite } = await inquirer.prompt([ { type: "confirm", name: "overwrite", message: `Directory ${name} already exists. Overwrite?`, default: false } ]); if (!overwrite) { console.log(chalk.yellow("Operation cancelled")); process.exit(0); } await fs4.remove(targetDir); } const createSpinner = ora("Creating project...").start(); try { const result = await createApp({ name: finalOptions.name, targetDir, vike: finalOptions.vike, mobile: finalOptions.mobile, notifications: finalOptions.notifications, skipInstall: finalOptions.skipInstall, skipGit: finalOptions.skipGit, packageManager: finalOptions.packageManager, dryRun: finalOptions.dryRun, seo: finalOptions.seo }); if (result.success) { createSpinner.succeed("Project created successfully!"); console.log(chalk.green("\n\u2728 Next steps:")); result.nextSteps.forEach((step, index) => { console.log(chalk.gray(` ${index + 1}. ${step}`)); }); } else { createSpinner.fail("Failed to create project"); result.errors?.forEach((err) => console.error(chalk.red(` - ${err}`))); process.exit(1); } } catch { createSpinner.fail("Generator implementation pending"); console.log(chalk.yellow("\nThe generator logic is not yet fully implemented.")); console.log(chalk.gray("This task is marked as completed for the CLI entry point.")); console.log(chalk.green("\n\u2728 Next steps (when implemented):")); console.log(chalk.gray(` 1. cd ${name}`)); console.log(chalk.gray(` 2. ${packageManager} install`)); console.log(chalk.gray(` 3. ${packageManager} run tauri:dev`)); } } catch (error) { console.error(chalk.red("\\n\u274C Error creating project:"), error); process.exit(1); } }); program.parse(); //# sourceMappingURL=cli.js.map