UNPKG

@agametis/create-app-for-fm

Version:

Tool for selecting a starter project for FileMaker applications

248 lines (227 loc) 7.75 kB
import fs from "fs-extra"; import path from "path"; import prompts from "prompts"; import {GITHUB_CONFIG} from "../config.js"; import {t} from "../i18n.js"; import { cloneRepository, initializePackageManager, installDependencies, cleanupAndExit, cancelOnce, } from "../utils.js"; // Function to initialize the current directory as a project export async function initProject() { try { console.log(t("init.initializingCurrentDirectory")); // Check if directory is empty const currentDir = process.cwd(); const dirContents = fs.readdirSync(currentDir); const isEmpty = dirContents.length === 0; const projectDir = process.cwd(); // If directory is not empty, ask for confirmation if (!isEmpty) { let confirmResponse; try { confirmResponse = await prompts({ type: "confirm", name: "confirm", message: t("common.directoryNotEmpty"), initial: false, }, { onCancel: () => { cancelOnce(1); return true; }, }); } catch (e) { if (e instanceof Error && e.message === "canceled") { cancelOnce(1); return; // cancelled during confirm } throw e; } // Check if user aborted (ESC or empty answers) if ( !confirmResponse || Object.values(confirmResponse).length === 0 || Object.values(confirmResponse).some((v) => v === undefined) ) { cancelOnce(1); return; // ensure no further execution } const { confirm } = confirmResponse; if (!confirm) { console.log(t("common.operationCancelled")); return; } } // Always use npm as the package manager let responses; const packageManager = "npm"; console.log(`${t("common.selectedPackageManager")}${packageManager}`); responses = await prompts([ { type: "select", name: "template", message: t("common.selectTemplate"), choices: GITHUB_CONFIG.repositories.map((repo) => ({ title: repo.name, value: `${GITHUB_CONFIG.baseUrl}${repo.path}`, })), initial: 0, }, ], { onCancel: () => { cancelOnce(1); return true; }, }); if (!responses.template) { console.log(t("common.operationCancelled")); return; // do not proceed without a template } // Skip initialization - we'll check if we need it after cloning the template console.log(t("common.preparingTemplate")); // Klone und kopiere Vorlagendateien console.log(t("init.downloadingTemplateFiles")); // Klone das Repository mit Helper-Funktion const tempCloneDir = path.join(process.cwd(), "temp-clone"); const cloneSuccess = await cloneRepository( responses.template, tempCloneDir ); if (!cloneSuccess) { return; // cloning failed; abort } // Check if the template has a package.json const templatePackageJsonPath = path.join(tempCloneDir, "package.json"); const hasTemplatePackageJson = fs.existsSync(templatePackageJsonPath); // Copy files from the cloned repo fs.copySync(tempCloneDir, projectDir, { filter: (src) => { const relativePath = path.relative(tempCloneDir, src); // Only skip package.json if we already have one AND the template has one const shouldSkipPackageJson = relativePath === "package.json" && fs.existsSync(path.join(projectDir, "package.json")) && hasTemplatePackageJson; return !src.includes(".git") && !shouldSkipPackageJson; }, overwrite: true, }); // Räume auf fs.removeSync(tempCloneDir); console.log(t("common.templateCopied")); console.log(t("init.projectInitialized")); // Check if package.json exists after copying const packageJsonPath = path.join(projectDir, "package.json"); // If no package.json exists, initialize one if (!fs.existsSync(packageJsonPath)) { console.log(t("init.noPackageJsonFound")); initializePackageManager(packageManager, projectDir); } else { // If package.json exists, install dependencies installDependencies(packageManager, projectDir); } // Show next steps console.log(t("common.nextSteps")); // Only show installation step if it wasn't already done if ( !fs.existsSync(packageJsonPath) || !fs.existsSync(path.join(projectDir, "node_modules")) ) { console.log( t("init.installDependenciesStep", { packageManager: packageManager, }) ); // Check if package.json contains scripts if (fs.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse( fs.readFileSync(packageJsonPath, "utf8") ); if ( packageJson.scripts && Object.keys(packageJson.scripts).length > 0 ) { console.log(t("common.availableScripts", { stepNumber: 2 })); let scriptNumber = 1; for (const [scriptName, scriptCommand] of Object.entries( packageJson.scripts )) { console.log( ` - ${scriptName}: ${packageManager} ${ packageManager === "npm" ? "run " : "" }${scriptName}` ); scriptNumber++; } } } catch (error) { // Ignore errors when reading package.json } } } else { let stepNumber = 1; // Check if package.json contains scripts if (fs.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse( fs.readFileSync(packageJsonPath, "utf8") ); if ( packageJson.scripts && Object.keys(packageJson.scripts).length > 0 ) { // Check if there's a dev or start script const hasDevScript = packageJson.scripts.dev !== undefined; const hasStartScript = packageJson.scripts.start !== undefined; const hasServeScript = packageJson.scripts.serve !== undefined; if (hasDevScript || hasStartScript || hasServeScript) { // Prefer dev, then start, then serve const devCommand = hasDevScript ? "dev" : hasStartScript ? "start" : "serve"; console.log( ` ${stepNumber}. ${t( "common.startDevServer" )}: ${packageManager} ${ packageManager === "npm" ? "run " : "" }${devCommand}` ); } else { // If no dev/start script, show available scripts console.log(t("common.availableScripts", { stepNumber })); for (const [scriptName, scriptCommand] of Object.entries( packageJson.scripts )) { console.log( ` - ${scriptName}: ${packageManager} ${ packageManager === "npm" ? "run " : "" }${scriptName}` ); } } stepNumber++; } } catch (error) { // Ignore errors when reading package.json } } } // Final tips console.log(t("common.checkReadme")); console.log(t("init.goodLuck")); } catch (error) { if (error instanceof Error && error.message === "canceled") { cancelOnce(1); return; // cancelled; stop execution } console.error(t("common.error") + error.message.split("\n")[0]); return; } }