CLI
็ฐๅจๅ้ข
ๆฌๆๆฏไฝ่ ๅจๆญๅปบ CLI ๆถ็ไธไบ็ฌ่ฎฐ ้ๅๆณ่ฆๅญฆไน CLI ๆญๅปบ็่ๆฐไปฌไบ่งฃๆดไธชๆต็จ
CLI ็ๆญๅปบๅ ถๅฎๅนถไธๅคๆ ๅ ไธบๆ ธๅฟๅ่ฝๅจ npm ไธๅทฒ็ปๆไบๅพๅคๆ็็ๆจกๅไบ
ไฝ่ ๅฎ็ฐ็ CLI ๆฏไธไธชๅธฆๆจก็็ผ่ฏ็็ฑปไผผ CRA ็ๅทฅๅ ท(ๅฝ็ถๆฏๆๅบ็ก็ๅ่ฝ ๐ฌ)
ๅ ไธบๆฏๅจ node ็ฏๅขไธ่ฟ่ก็้กน็ฎ ๆไปฅไธๆ็ demo ไฝฟ็จ็้ฝๆฏ cjs ๆจกๅ
ๅฅฝๅฆ CLI ๅ ถๅฎๆฒกๆไปไน้ป้ญๆณ ๆไปฌๅผๅงๅง๏ฝ๏ฝ๏ฝ ๐๐๐
้ข่งๅพๅไปฃ็ ๅฆไธ ๐๐๐
Preview

ไปๅบๅฐๅ https://github.com/LuckyChou710/code-traveling/tree/main/09-node-training-camp/cli
ไธๆ่ฏดๅฐ็YepGym xxx
ๅฐฑๆฏๅจๆง่ก CLI
ๅทฅๆฌฒๅๅ
ถไบ๏ผๅฟ
ๅ
ๅฉๅ
ถๅจ
ๅทฅๆฌฒๅๅ ถไบ๏ผๅฟ ๅ ๅฉๅ ถๅจ ้ฆๅ ๅธฆๅคงๅฎถไบ่งฃไธไบ CLI ๅถไฝๅฟ ๅค็ npm ๅ
ไปฅไธ็ไธบๆๅบ็ก็ไฝฟ็จๆนๆณ ๅ ทไฝ็็จๆณๅฏๅปๅฏนๅบ็ๅฎ็ฝๆฅ็
PS๏ผๆๅพๅคๅ ๅทฒๆดๆฐๆไบ ESM ๆจกๅ ๅฆๆ่ฆไฝฟ็จ CJS ๆจกๅ็่ฏ ่ฏทๅฎ่ฃ ๅฏนๅบ็็ๆฌ
commander
https://www.npmjs.com/package/commander
ๅ้็น ๐ commander ๆฏ CLI ๆญๅปบไธญ็ไธไธชๆๆ ธๅฟ็ๅ
ๅฎๅฏไปฅไธบไฝ ็ CLI ๅฝไปคๆณจๅ ฅๅพๅคๅๆฐ ไพๅฆ
YepGym create xxx
ๅฏไปฅๅๅปบไธไธชๆจก็YepGym help
ๅฏไปฅ่ทๅ CLI ็ๆๆๅฝไปค่ฏดๆ......
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
create|c create a project
help [command] display help for command
้่ฟๅผๅ
ฅcommander
่ฟไธชๅบ ๅฐฑๅฏไปฅๅฟซ้ๅธฎๅฉๆไปฌๅฎ็ฐ่ฟไธชๆๆ
const { program } = require('commander');
program
.command('create')
.alias('c')
.description('create a project')
.action(() => {
// do something
});
program.parse();
inquirer or prompts
https://www.npmjs.com/package/inquirer
https://www.npmjs.com/package/prompts
่ฟไธคไธชๅบ้ฝๅฏไปฅๅจๅฝไปค่ก็ๆไธไบๅฏไพ็จๆท้ๆฉ็ไบคไบ
ไพๅฆ
? Select Compiler (Press <space> to select, <a> to toggle all, <i> to invert sel
ection, and <enter> to proceed)
โฏโฏ Babel
โฏ TypeScript
const inquirer = require('inquirer');
inquirer
.prompt([
{
type: 'checkbox',
message: 'Select Compiler',
name: 'compiler',
choices: [
{
name: 'Babel',
},
{
name: 'TypeScript',
},
],
validate(answer) {
if (answer.length < 1) {
return 'You must choose at least one topping.';
}
return true;
},
},
])
.then((answers) => {
console.log(JSON.stringify(answers));
});
้่ฟๆนๅ็ฌฌไธไธช type ๅฑๆง ๆไปฌๅฏไปฅ่ฎพ็ฝฎๆ input / list / ......
download-git-repo
https://www.npmjs.com/package/download-git-repo
็ดๆฅไธไปฃ็ ๅง ๐
const download = require('download-git-repo');
download('YepGym/react-v17-template', 'test/tmp', { clone: false }, (err) => {
console.log(err ? 'Error' : 'Success');
});
ไธ่ฟฐไปฃ็ ๅฐฑไผๅจๅฝๅ็ฎๅไธ็ test/temp ไธๆๅป่ฟ็จไปๅบ YepGym/react-v17-template ไธ็ไปฃ็
ๆดๅค็็จๆณๅฏไปฅๅ่ไธ่ฟฐๆๆกฃ
ejs
https://ejs.bootcss.com/
https://www.npmjs.com/package/ejs
ejs ๆฏไธ็ง็ฎๆด็ๆจก็่ฏญๆณ ไพๅฆ ๆไปฌๆไธไปฝ package.json
{
"name": "<%= projectName %>",
"description": "<%= projectDescription %>",
"author": "<%= projectAuthor %>",
"version": "1.0.0",
"main": "index.js"
}
้้ขๆไธไบ็ฑปไผผๅ้็ๅฐๆน ็จ ejs ่ฏญๆณ่ฟ่กๅ ไฝ
้่ฟ ejs ็็ผ่ฏ ๅฐฑๅฏไปฅๅฐ่ฟไธชๅ้ๅกซๅ ่ฟๅป ็ๆๆ็ป็ๆไปถ
็จๆณๅฆไธ
let template = ejs.compile(str, options);
template(data);
// => ่พๅบๆธฒๆๅ็ HTML ๅญ็ฌฆไธฒ
ejs.render(str, data, options);
// => ่พๅบๆธฒๆๅ็ HTML ๅญ็ฌฆไธฒ
ejs.renderFile(filename, data, options, function (err, str) {
// str => ่พๅบๆธฒๆๅ็ HTML ๅญ็ฌฆไธฒ
});
็ปๅไธๆ็ demo ๆไปฌ้่ฆ็ผ่ฏ package.json ็จๆณๅฆไธ
const ejs = require('ejs');
const fs = require('fs');
const projectName = 'chou-cli';
const projectDescription = 'description ......';
const projectAuthor = 'chou';
ejs
.renderFile('./package.json', {
projectName,
projectDescription,
projectAuthor,
})
.then((res) => {
fs.writeFile('./package.json', res, (err) => throw err);
});
ejs.renderFile
ๅฏไปฅ่ฏปๅ
ฅไธไธชๆไปถ ็ถๅ็ฌฌไบไธชๅๆฐๅฏไปฅไผ ้ๆจก็้้่ฆ็ๅ้
github api
https://docs.github.com/en/rest/guides/getting-started-with-the-rest-api
github ไธบๆไปฌๆไพไบ restful api ไพๅฆไปๅบ็่ทๅ ็จๆทไฟกๆฏ็่ทๅ็ญ็ญ
ๅ ทไฝ็ๆๆกฃๅฏไปฅๅ่ๅฎๆนๆๆกฃ
้ฆไธๆทป่ฑ
chalk
https://www.npmjs.com/package/chalk
chalk ๆฏ็ฒ็ฌ็ๆๆ ้กพๅๆไน ๅฎๅฏไปฅ่ฎฉๆไปฌ็่พๅบ(console)ๅธฆไธ้ข่ฒ
็ดๆฅ้่ฟ chalk.็ๆนๆณๅฐฑๅฏไปฅไธบไฝ ็ console ๆณจๅ ฅ้ข่ฒๅฆ๏ฝ๏ฝ
const chalk = require('chalk');
console.log(chalk.blue.bold('Hello Chou!'));
console.log(chalk.blue.bold.bgWhiteBright('Hello Chou!'));
boxen
https://www.npmjs.com/package/boxen
ไพๅฆๅฝๆไธช npm ๅ ๆไบๆฐ็็ๆฌ้่ฆๅ็บงๆถ ๆ่ ๆไปฌๅฏๅจไธไธช้กน็ฎๆถ ็ปๅธธไผๅ็ฐไธ้ข็ๆๆ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ New version available 4.5.13 โ 5.0.1 โ
โ Run yarn global add @vue/cli to update! โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
const boxen = require('boxen');
const chalk = require('chalk');
const upgradeMessage = `New version available ${chalk.magenta(
'4.5.13'
)} โ ${chalk.green('5.0.1')} \nRun ${chalk.yellow(
'yarn global add @vue/cli'
)} to update!`;
console.log(
boxen(upgradeMessage, {
align: 'center',
borderColor: 'green',
dimBorder: true,
padding: 1,
})
);
ora
https://www.npmjs.com/package/ora
่ฟไธชๅบๅฏไปฅ็ๆไธไธช loading ็ spinner
โ Fetching...
ๅฝๆไปฌๆง่กไธไบ่ๆถ็ๆไฝๆถ ไพๅฆ api ่ฏทๆฑๆถ ๅฐฑๅฏไปฅๅธฆไธ่ฟไธชๅบ่ฎฉ็จๆทๆๆดๅฅฝ็ไฝ้ช
const ora = require('ora');
const spinner = ora('Fetching...');
spinner.start();
setTimeout(() => {
spinner.succeed('success');
}, 2000);
figlet
https://www.npmjs.com/package/figlet
ไพๅฆ่ฟไธชๅบ ๆไปฌๅฏไปฅๅจ็ป็ซฏๆๅฐๅบๅพๅฅฝ็็ๆๅญๆๆ ไพๅฆๆ็ซ ๅผๅคด้ข่งๅพ็ๆๆ
__ __ ____ __
/\ \ /\ \ /\ _`\ /\ \
\ `\`\\/'/ __ _____\ \ \L\_\ __ __ ___ ___\ \ \
`\ `\ /' /'__`\/\ '__`\ \ \L_L /\ \/\ \ /' __` __`\ \ \
`\ \ \/\ __/\ \ \L\ \ \ \/, \ \ \_\ \/\ \/\ \/\ \ \_\
\ \_\ \____\\ \ ,__/\ \____/\/`____ \ \_\ \_\ \_\/\_\
\/_/\/____/ \ \ \/ \/___/ `/___/> \/_/\/_/\/_/\/_/
\ \_\ /\___/
\/_/ \/__/
const figlet = require('figlet');
figlet.text(
'YepGym!',
{
font: 'Larry 3D',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 80,
whitespaceBreak: true,
},
(err, data) => {
if (!err) console.log(data);
}
);
figlet ๅ ็ฝฎไบๅพๅค็ง font ๅฏไพ้ๆฉ
http://www.figlet.org/examples.html
ๅฏไปฅ้่ฟ่ฟไธช็ฝๅ ๆฅ็ examples
็ปๅ chalk ๅ่ฏฅๅบ ๅฐฑๅฏไปฅๅฎ็ฐไบ้ขๅ ญ่ฒ็ logo sign ๅฆ
clear
clear ๅฏไปฅ็จๆธ ้คไฝ ็ๅฝไปค่ก ๅ่ฝๅไฝ ็ดๆฅๅจ cmd / bash ่พๅ ฅ clear ็ๆๆไธๆ ท
ๅฝๆไปฌๅจๅฑๅนไธๆๆฏ่พๅค็ไฟกๆฏ ๆณ่ฆๆธ ไธไธๅฑ็ๆถๅ ๅฐฑๅฏไปฅไฝฟ็จ่ฟไธชๅบ
> https://www.npmjs.com/package/clear
const clear = require('clear');
clear();
validate-npm-package-name
https://www.npmjs.com/package/validate-npm-package-name
ๅจ vue-cli
ไธญ ๅฐฑๆฏๅผๅ
ฅไบ่ฟไธชๅบๅปๅคๆญ่ฆๅๅปบ็้กน็ฎๅๆฏๅฆๅๆณ
const validateProjectName = require('validate-npm-package-name');
const result = validateProjectName(' leading-space:and:weirdchars');
console.log(result);
// {
// validForNewPackages: false,
// validForOldPackages: false,
// errors: [
// 'name cannot contain leading or trailing spaces',
// 'name can only contain URL-friendly characters'
// ]
// }
YepGym
npm link
้ฆๅ ๆไปฌ่ฆๅ็ๅฐฑๆฏๅฐๆไปฌ็ CLI ๅฝไปค ๅจ็ป็ซฏๆง่ก่ตทๆฅ
ๅจ้กน็ฎ็ package.json ไธญๆทปๅ bin ๅญๆฎต ้ ็ฝฎไธไฝ ็ CLI ๅฝไปคๅๅฏนๅบ็ๆไปถ่ทฏๅพ
"bin": {
"YepGym": "./bin/YepGym.js"
},
ๆณจๆ โ ๏ธ๏ผ ่ฏฅๆไปถ็ๆไปถๅคดๅฟ ้กปๅ ไธ
#! /usr/bin/env node
่กจๆ่ฏฅๆไปถ่ฆไปฅ node ็็ฏๅขๅป่ฟ่ก
็ถๅๅจ้กน็ฎ็ฎๅฝไธๆง่ก npm link
่ฟไธชๅฝไปคๅฐฑไผ่ฝฏ้พๆฅๅจๅ
จๅฑ็ bin ็ฎๅฝไธ
ๆง่ก npm list -g
ๅฏไปฅ็ๅฐ
/opt/homebrew/lib
โโโ nodemon@2.0.15
โโโ npm@8.3.1
โโโ nrm@1.2.5
โโโ yep-gym@1.0.0 -> package.jsonไธ้
็ฝฎ็ๆไปถไฝ็ฝฎ
ๆญคๆถ ๆไปฌๅจๅฝไปค่กไธๆง่ก YepGym ๆถ ๅฐฑไผๅปๆพๅฐๅฏนๅบ็ๆไปถไฝ็ฝฎ ๅนถไปฅ node ็ฏๅข่ฟ่ก่ฏฅๆไปถ
cli ๆต็จ
ๆดไธช้กน็ฎ็ปๆๅฆไธ ไปๅบ้พๆฅ ๐ ๅจๆ็ซ ๅผๅคด
ไปฃ็ ๆฏ่พ็ฎๅ ๆๅ ด่ถฃ็ๅฏไปฅ่ชๅทฑๆฅ็ ๐ถ
YepGym-CLI
โโ .eslintrc.js
โโ README.md
โโ bin
โ โโ YepGym.js
โโ lib
โ โโ commander.js
โ โโ create.js
โ โโ main.js
โ โโ utils
โ โโ constants.js
โ โโ generator.js // ็ผ่ฏๆจก็ๆไปถ
โ โโ loadCustomPreset.js // ๅ ่ฝฝ็จๆท่ชๅฎไน้
็ฝฎ
โ โโ loadRemotePreset.js // ๅ ่ฝฝ่ฟ็จไปๅบๆจก็
โ โโ prompt.js // ็จๆท่ชๅฎไนไฟกๆฏ่พๅ
ฅ
โ โโ request.js // github api request
โ โโ sign.js
โโ package.json
โโ yarn.lock
ๅจ่ฟ้ ๅชๅไธไบๆต็จไธ็่ฏดๆ
้่ฟ loadCustomPreset ๅปๅ ่ฝฝ็จๆท็ไธไบ้ ็ฝฎ
ๆ นๆฎ้ๆฉ็ไปๅบ ็จ
download-git-repo
ๅปๆๅๅฏนๅบ็ๆจก็ๅฐๆฌๅฐๅฆๆๆฏๅธฆๆจก็่ฏญๆณ็ ้่ฆ่ฟ่กๆจก็่ฏญๆณ็ผ่ฏ็ ๅๅ่ฟๅ ฅ generator ๆนๆณ ๅจ่ฟ้ ๆไฝฟ็จ็ๆฏ ejs ๆจก็่ฏญๆณ
Last updated
Was this helpful?