make light-chat as a first option

This commit is contained in:
weboko 2022-12-22 23:39:50 +01:00
parent 53da2e44e0
commit 5e50b66bf5
No known key found for this signature in database
1 changed files with 126 additions and 97 deletions

View File

@ -6,144 +6,173 @@ const execSync = require("child_process").execSync;
const { Command } = require("commander"); const { Command } = require("commander");
const validateProjectName = require("validate-npm-package-name"); const validateProjectName = require("validate-npm-package-name");
const DEFAULT_EXAMPLE = "light-chat";
const supportedExamplesDir = path.resolve(__dirname, "./examples"); const supportedExamplesDir = path.resolve(__dirname, "./examples");
const supportedExamples = readDirNames(supportedExamplesDir); const supportedExamples = readDirNames(supportedExamplesDir);
const init = async (name, description, version) => { const init = async (name, description, version) => {
let appName; let appName;
let template; let template;
const options = new Command() const options = new Command()
.name(name) .name(name)
.description(description) .description(description)
.version(version, "-v, --version", "output the version number") .version(version, "-v, --version", "output the version number")
.arguments("<project-directory>", "Project directory to initialize Waku app") .arguments(
.action(_appName => { "<project-directory>",
appName = _appName; "Project directory to initialize Waku app"
}) )
.option( .action((_appName) => {
"-t, --template <path-to-template>", appName = _appName;
"specify a template for the created project or you can use the wizard." })
) .option(
.allowUnknownOption() "-t, --template <path-to-template>",
.parse() "specify a template for the created project or you can use the wizard."
.opts(); )
.allowUnknownOption()
.parse()
.opts();
template = options.template; template = options.template;
if (!template) { if (!template) {
const templatePrompt = new enquirer.Select({ const templatePrompt = new enquirer.Select({
name: "template", name: "template",
message: "Select template", message: "Select template",
choices: Object.keys(supportedExamples), choices: buildChoices(supportedExamples),
}); });
try { try {
template = await templatePrompt.run(); template = await templatePrompt.run();
} catch (e) { } catch (e) {
console.error(`Failed at selecting a template: ${e.message}`); console.error(`Failed at selecting a template: ${e.message}`);
process.exit(1); process.exit(1);
}
} }
}
if (!supportedExamples[template]) { if (!supportedExamples[template]) {
const supportedExamplesMessage = Object.keys(supportedExamples).reduce((acc, v) => { const supportedExamplesMessage = Object.keys(supportedExamples).reduce(
acc += `\t${v}\n`; (acc, v) => {
return acc; acc += `\t${v}\n`;
}, ""); return acc;
},
""
);
console.error(`Unknown template: ${template}`); console.error(`Unknown template: ${template}`);
console.error(`We support only following templates:\n${supportedExamplesMessage}`) console.error(
process.exit(1); `We support only following templates:\n${supportedExamplesMessage}`
} );
process.exit(1);
}
createApp(appName, template); createApp(appName, template);
}; };
function createApp(name, template) { function createApp(name, template) {
const appRoot = path.resolve(name); const appRoot = path.resolve(name);
const appName = path.basename(appRoot); const appName = path.basename(appRoot);
const templateDir = path.resolve(supportedExamplesDir, template); const templateDir = path.resolve(supportedExamplesDir, template);
terminateIfAppExists(appName); terminateIfAppExists(appName);
terminateIfProjectNameInvalid(appName); terminateIfProjectNameInvalid(appName);
console.log(`Initializing ${appName} from ${template} template.`); console.log(`Initializing ${appName} from ${template} template.`);
fs.ensureDirSync(appName); fs.ensureDirSync(appName);
fs.copySync(templateDir, appRoot); fs.copySync(templateDir, appRoot);
runNpmInApp(appRoot); runNpmInApp(appRoot);
runGitInit(appRoot); runGitInit(appRoot);
} }
function runNpmInApp(root) { function runNpmInApp(root) {
const packageJsonPath = path.resolve(root, "package.json"); const packageJsonPath = path.resolve(root, "package.json");
if (!fs.existsSync(packageJsonPath)) { if (!fs.existsSync(packageJsonPath)) {
return; return;
} }
console.log("Installing npm packages."); console.log("Installing npm packages.");
try { try {
execSync(`npm install --prefix ${root}`, { stdio: "ignore" }); execSync(`npm install --prefix ${root}`, { stdio: "ignore" });
console.log("Successfully installed npm dependencies."); console.log("Successfully installed npm dependencies.");
} catch (e) { } catch (e) {
console.warn("Failed to install npm dependencies", e); console.warn("Failed to install npm dependencies", e);
} }
} }
function runGitInit(root) { function runGitInit(root) {
if (isInGitRepository()) { if (isInGitRepository()) {
return; return;
} }
console.log("Initiating git repository."); console.log("Initiating git repository.");
try { try {
execSync(`git init ${root}`, { stdio: "ignore" }); execSync(`git init ${root}`, { stdio: "ignore" });
console.log("Successfully initialized git repo."); console.log("Successfully initialized git repo.");
} catch (e) { } catch (e) {
console.warn("Git repo not initialized", e); console.warn("Git repo not initialized", e);
} }
} }
function isInGitRepository() { function isInGitRepository() {
try { try {
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" }); execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
return true; return true;
} catch (e) { } catch (e) {
return false; return false;
} }
} }
function terminateIfProjectNameInvalid(name) { function terminateIfProjectNameInvalid(name) {
const validationResult = validateProjectName(name); const validationResult = validateProjectName(name);
if (!validationResult.validForNewPackages) { if (!validationResult.validForNewPackages) {
console.error(`Cannot create a project named ${name} because of npm naming restrictions:\n`); console.error(
[...(validationResult.errors || []), ...(validationResult.warnings || [])] `Cannot create a project named ${name} because of npm naming restrictions:\n`
.forEach(error => console.error(` * ${error}`)); );
console.error("\nPlease choose a different project name."); [
process.exit(1); ...(validationResult.errors || []),
} ...(validationResult.warnings || []),
].forEach((error) => console.error(` * ${error}`));
console.error("\nPlease choose a different project name.");
process.exit(1);
}
} }
function terminateIfAppExists(appRoot) { function terminateIfAppExists(appRoot) {
if (fs.existsSync(appRoot)) { if (fs.existsSync(appRoot)) {
console.error(`Cannot create a project because it already exists by the name: ${appRoot}`); console.error(
process.exit(1); `Cannot create a project because it already exists by the name: ${appRoot}`
} );
process.exit(1);
}
} }
function readDirNames(target) { function readDirNames(target) {
return fs.readdirSync(target, { withFileTypes: true }) return fs
.filter(dir => dir.isDirectory()) .readdirSync(target, { withFileTypes: true })
.map(dir => dir.name) .filter((dir) => dir.isDirectory())
.reduce((acc, name) => { .map((dir) => dir.name)
acc[name] = path.resolve(target, name); .reduce((acc, name) => {
return acc; acc[name] = path.resolve(target, name);
}, {}); return acc;
}, {});
}
function buildChoices(examples) {
// handle a case if default example will be deleted without updating this place
if (!examples[DEFAULT_EXAMPLE]) {
return Object.keys(examples);
}
return [
DEFAULT_EXAMPLE,
...Object.keys(examples).filter((v) => v !== DEFAULT_EXAMPLE),
];
} }
module.exports = { init }; module.exports = { init };