UNPKG

@seasketch/geoprocessing

Version:

Geoprocessing and reporting framework for SeaSketch 2.0

157 lines • 6.64 kB
import ora from "ora"; import fs from "fs-extra"; import chalk from "chalk"; import { projectSchema } from "../../src/types/index.js"; import { promisify } from "node:util"; import { getGeoprocessingPath, getBaseProjectPath } from "../util/getPaths.js"; import { $ } from "zx"; import * as child from "node:child_process"; $.verbose = false; const exec = promisify(child.exec); /** Create project at basePath. If should be created non-interactively then set interactive = false and provide all project creation metadata, otherwise will prompt for answers */ export async function createProject(metadata, interactive = true, basePath = "") { const { organization, region, languages, email, gpVersion, name, description, author, license, repositoryUrl, } = metadata; // Installation path for new project const projectPath = `${basePath ? basePath + "/" : ""}${metadata.name}`; const spinner = interactive ? ora("Creating new project").start() : { start: () => false, stop: () => false, succeed: () => false, fail: () => false, }; spinner.start(`creating ${projectPath}`); await fs.ensureDir(projectPath); spinner.succeed(`created ${projectPath}/`); spinner.start("copying base project"); const baseProjectPath = getBaseProjectPath(); // Get version of geoprocessing currently running const curGpPackage = JSON.parse(fs.readFileSync(`${getGeoprocessingPath()}/package.json`).toString()); const curGpVersion = curGpPackage.version; // Copy all files from base project template try { await fs.ensureDir(projectPath); await $ `cp -r ${baseProjectPath}/* ${projectPath}`; await $ `cp -r ${baseProjectPath}/. ${projectPath}`; await $ `rm -f ${projectPath}/package-lock.json`; await $ `rm -f ${projectPath}/project/geoprocessing.json`; await $ `rm -rf ${projectPath}/examples/outputs/*.*`; await $ `rm -rf ${projectPath}/examples/features/*.json`; await $ `rm -rf ${projectPath}/examples/sketches/*.json`; } catch (error) { if (error instanceof Error) { console.log("Base project copy failed"); throw error; } } spinner.succeed("copied base files"); spinner.start("updating package.json with provided details"); const packageJSON = { ...JSON.parse(fs.readFileSync(`${baseProjectPath}/package.json`).toString()), name, version: "0.1.0", description, author, license, repositoryUrl, // TODO: other repo types ...(/github/.test(metadata.repositoryUrl) ? { repository: { type: "git", url: "git+" + metadata.repositoryUrl + ".git", }, homepage: metadata.repositoryUrl + "#readme", bugs: { url: metadata.repositoryUrl + "/issues", }, } : {}), private: false, }; if (gpVersion) { spinner.start(`Installing user-defined GP version ${gpVersion}`); packageJSON.dependencies["@seasketch/geoprocessing"] = gpVersion; spinner.succeed(`Installing user-defined GP version ${gpVersion}`); } else { packageJSON.dependencies["@seasketch/geoprocessing"] = curGpVersion; } await fs.writeFile(`${projectPath}/package.json`, JSON.stringify(packageJSON, null, 2)); spinner.succeed("updated package.json"); spinner.start("creating geoprocessing.json"); const geoAuthor = email ? `${metadata.author} <${email}>` : metadata.author; await fs.writeFile(`${projectPath}/project/geoprocessing.json`, JSON.stringify({ author: geoAuthor, organization: organization || "", region, clients: [], preprocessingFunctions: [], geoprocessingFunctions: [], }, null, " ")); spinner.succeed("created geoprocessing.json"); spinner.start("updating basic.json"); const basic = fs.readJSONSync(`${projectPath}/project/basic.json`); const validBasic = projectSchema.parse({ ...basic, languages: ["EN", ...languages], // insert EN as required language }); await fs.writeJSONSync(`${projectPath}/project/basic.json`, validBasic, { spaces: 2, }); spinner.succeed("updated basic.json"); spinner.start("add .gitignore"); try { if (fs.existsSync(`${projectPath}/_gitignore`)) { fs.move(`${projectPath}/_gitignore`, `${projectPath}/.gitignore`); } spinner.succeed("added .gitignore"); } catch (error) { spinner.fail(".gitignore add failed"); console.error(error); } // recursively copy entire i18n directory to project space spinner.start("add i18n"); await fs.copy(`${getGeoprocessingPath()}/src/i18n`, projectPath + "/src/i18n"); // Create i18n.json with project-specific config const configPath = `${projectPath}/project/i18n.json`; const i18nConfig = { localNamespace: "translation", remoteContext: packageJSON.name, }; await fs.writeJSON(configPath, i18nConfig, { spaces: 2 }); spinner.succeed("added i18n"); // Install dependencies including adding GP. if (interactive) { spinner.start("installing dependencies with npm"); try { await exec(`npm install`, { cwd: metadata.name, }); spinner.succeed("installed dependencies"); spinner.start("extracting translations"); await exec(`npm run extract:translation`, { cwd: metadata.name, }); } catch (error) { if (error instanceof Error) { console.log(error.message); console.log(error.stack); process.exit(); } } spinner.succeed("extracted initial translations"); } if (interactive) { console.log(chalk.blue(`\nYour geoprocessing project has been initialized!`)); console.log(`\nNext Steps: * ${chalk.yellow(`Tutorials`)} are available to create your first geoprocessing function and report client at https://github.com/seasketch/geoprocessing/wiki/Tutorials * ${chalk.yellow(`Translations`)} need to be synced if you are using POEditor. Make sure POEDITOR_PROJECT and POEDITOR_API_TOKEN environemnt variables are set in your shell environment and then run 'npm run sync:translation'. See tutorials for more information `); } } //# sourceMappingURL=createProject.js.map