石家庄专业网站制,深圳工业设计薪资,引流获客app下载,金华网站建设策划初始化
新建文件夹初始化命令 npm init -ytsc --initnpm i types/nodenpm i typescript# 处理别名npm i -D tsc-alias -y 表示选项都为yes 安装ts相关依赖 新建相关文件 bin 文件夹 src文件夹 commands 文件夹 #xff08;命令 utils 文件夹 (封装方法#xff09; index.t…初始化
新建文件夹初始化命令 npm init -ytsc --initnpm i types/nodenpm i typescript# 处理别名npm i -D tsc-alias -y 表示选项都为yes 安装ts相关依赖 新建相关文件 bin 文件夹 src文件夹 commands 文件夹 命令 utils 文件夹 (封装方法 index.ts文件export * from ./chalk index.ts 文件 #! /usr/bin/env node
console.log(hello gaogao)#! /usr/bin/env node 前后不可有空格 #!用于指定脚本的解释程序开发npm包这个指令一定要加 .gitignore 文件 #basicnode_modulepackage-lock.json#buildbin.npmrc 文件 registryhttps://mirrors.huaweicloud.com/repository/npmTS配置
建【tsconfig.json】
{compilerOptions: {target: ES6,module: commonjs,outDir: ./bin, // 输出地址 相对路径baseUrl: ./,strict: true,moduleResolution: node,esModuleInterop: true,skipLibCheck: true,forceConsistentCasingInFileNames: true,resolveJsonModule: true,paths:{:[src],utils:[utils],}},include: [./src,src/**/*.ts,src/**/*.d.ts]
}修改【package.json】 bin:执行的文件或命令 scripts-build 处理ts文件 {name: gaogao-cli,version: 1.0.0,description: ,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1,build: tsc tsc-alias},bin: {gaogao: /bin/src/index.js},keywords: [],author: ,license: ISC,dependencies: {types/figlet: ^1.7.0,types/fs-extra: ^11.0.4,types/inquirer: ^9.0.7,types/log-symbols: ^3.0.0,types/node: ^22.13.2,types/shelljs: ^0.8.15,chalk: ^4.0.0,commander: ^9.0.0,download-git-repo: ^3.0.2,figlet: ^1.8.0,fs-extra: ^10.0.1,inquirer: ^8.2.1,loading-cli: ^1.1.2,log-symbols: ^4.1.0,ora: ^5.4.1,shelljs: ^0.8.5,table: ^6.9.0,typescript: ^5.7.3},devDependencies: {tsc-alias: ^1.8.10}
}
测试
ts语言需要先build
npm run buildbuild后bin文件夹下自动新增index.js文件 验证修改是否生效都需要build cnpm link
gaogao安装相关工具
安装固定版本有些版本会有bug
commander
https://www.npmjs.com/package/commander
处理控制台命令工具解析用户输入时一些参数 例如 create 就是利用此工具做解析辅助
cnpm i commander9.0.0import {program} from commander
import Pack from ../package.json
program.version(Pack.version, -v, --version);
program.parse(process.argv)//nodejs提供的属性封装常用命令
commands文件夹下新建create文件夹 文件
import commandCreate from./create
// create见 create命令目录
const commands:any {create project-name:{description:create a project,option:[{cmd:-f,--force,msg:overwrite target directory if it exists}],action:commandCreate}
}export default commandsimport { Command } from commander;
import Commands from commands;
//index.ts
Object.keys(Commands).forEach((command:any) {const current:any program.command(command);if (Commands[command].option Commands[command].option.length) {let options current.optionCommands[command].option.forEach((item: { cmd: string; msg: any }) {current.option(item.cmd, item.msg || );});}current.action(Commands[command].action);
});chalk 美化工具
该模块用于添加颜色和样式到控制台输出 效果见【figlet】 import chalk from chalk
console.log(\r\n chalk.greenBright.bold(hello gaogao-cli))封装字体处理
import chalk from chalk;
export const Cblue (text:string) chalk.blue(text)
export const Cred (text:string) chalk.red(text)
export const Cgreen (text:string) chalk.green(text)
figlet
https://www.npmjs.com/package/figlet
该模块用于生成ASCII艺术字 具体字体可以去figlet官网查看 cnpm i figlet1.5.2 types/figletimport chalk from chalk
import figlet from figlet
program.name(gaogao).description(gaogao-cli).usage(command [options])// 用在内置的帮助信息之后输出自定义的额外信息.on(--help, () {console.log(\r\n chalk.greenBright.bold(figlet.textSync(gaogao-cli, {font: Standard,horizontalLayout: default,verticalLayout: default,width: 100,whitespaceBreak: true,})))console.log(\r\n Run ${chalk.cyanBright(gaogao-cli command --help)} for detailed usage of given command.)});inquirer -命令行交互工具
https://www.npmjs.com/package/inquirer
该模块用于实现交互式命令行界面 例如vue询问是否单元测试
cnpm i inquirer8.2.1 types/inquirer封装inquirer
- lib文件夹下新建interactive.ts 文件import inquirer from inquirer;/*** param {string} message 询问提示语句* returns {Object} 根据name属性获取用户输入的值{confirm: y/n}*/
export const inquirerConfirm async (message:string): Promiseobject {const answer await inquirer.prompt({type: confirm,name: confirm,message,});return answer;
}/*** * param {string} name 询问事项* param {string} message 询问提示语句* param {Array} choices 选择模板列表默认读取对象的name属性* returns {Object} 根据name属性获取用户输入的值{请选择项目模板: xxxxxx}*/
export const inquirerChoose async (name:string,message:string, choices:Arrayany): Promiseany {const answer await inquirer.prompt({type: list,name,message,choices,});return answer;
}/*** param {Array} messages 询问提示语句数组* returns {Object} 结果对象*/
export const inquirerInputs async (messages: Arrayany): Promiseobject {const questions messages.map(msg {return {name: msg.name,type: input,message: msg.message,}})const answers await inquirer.prompt(questions);return answers
}loading-cli
https://www.npmjs.com/package/loading-cli
utils 下新建loading文件在这里插入代码片
//loading.ts
import loading, { Options, Loading } from loading-cli;class Load {load: null | Loading;constructor() {this.load null;}/*** Descripttion: 开始loading状态* msg: * param {Options} options* return {*}*/ start (options: Options | string) {if(!this.load){typeof optionsobject!options.frames(options.frames[,,^,,,_,_])this.load loading(options).start()}else{this.load.start(options as string)}};stop () {this.load this.load.stop();};succeed(textsuccess) {this.load this.load.succeed(text);};warn(text: string) {this.load this.load.warn(text);};info (text: string){this.load this.load.info(text);};
}export default new Load();
// index.tsprogram.command(loading).description(View all available templates).action(() {loading.start({color: red,text: begin,});setTimeout(() {loading.warn(警告);setTimeout(() {loading.info(提示);setTimeout(() {loading.stop();}, 2000);}, 2000);}, 2000);})fs
https://url.nodejs.cn/api/fs.html
该模块用于对文件系统进行更强大的操作。
cnpm i fs-extra10.0.1 types/fs-extra封装文件处理方法
import fs from fs;import { Cred } from ./chalk;export const readDir (path: string): Promiseany new Promise((res, rej) {fs.readdir(path, (err) {if (!err) res(true);res(false)});});export const mkdir (path: string): Promiseany new Promise((res, rej) {fs.mkdir(path, (err) {if (!err) res();rej(${Cred(Can not mak dir)} ${typeof err string ? err : JSON.stringify(err)});});});export const rm (path: string): Promiseany new Promise((res, rej) {fs.rm(path,{ recursive: true}, (err) {if (!err) res();rej(${Cred(Can not remove dir path)} ${typeof err string ? err : JSON.stringify(err)});});});其他常用工具
# 安装ora模块该模块用于显示动画加载效果。
cnpm i ora5.4.1
# 安装download-git-repo模块该模块用于下载并提取Github/Git(template本地)仓库中的文件。
cnpm i download-git-repo3.0.2
# 安装handlebars模块该模块用于处理模板文件。
cnpm i handlebars4.7.6
# 安装log-symbols模块该模块用于在控制台输出不同类型的日志符号√或×。
cnpm i log-symbols4.1.0
# 安装axios模块该模块用于发起HTTP请求。
cnpm i axios0.26.1
# 安装gitee-repo模块该模块用于从Gitee仓库中下载模板文件。
cnpm i gitee-repo0.0.2
# 命令行界面表格内容显示
cnpm i table
# 基于nodejs的shell命令工具
cnpm i shelljs types/shelljs
# 在控制台输出不同类型的日志符号√或×
cnpm i log-symbols4.1.0 types/log-symbols配置模版文件
lib文件夹下新建constants.ts 文件
//constants.ts
/*** 项目模板列表*/
export const templates [{name: vue-template,value: direct:https://gitee.com/账号/vue-template.git,desc: 基于vite的自定义vue项目模板,},
];/*** 项目信息*/
export const messages [{name: name,message: 请输入项目名称,},{name: description,message: 请输入项目描述,},
];
//index.ts
import { table } from table;import { templates } from ../lib/constants// 查看模板列表
program
.command(ls)
.description(View all available templates)
.action(() {const data templates.map(item [chalk.greenBright(item.name), chalk.white(item.value), chalk.white(item.desc)]);data.unshift([chalk.white(Template name), chalk.white(Template address), chalk.white(Template description)]);console.log(table(data));
})gaogao lscreate命令
create
commands文件夹下新建create文件夹 文件
import fs from fs-extra;
import ora from ora;
import inquirer from inquirer;
import path from path;
import { exec } from child_process;
import {readDir,mkdir,rm,Cred,readFile,copyFolder,loading,inquirerChoose
} from utils;
import { TempLatesRepo, TempLatesName, templates } from ../../constant/repo;
export default async function (projectName: any, options: any) {const cwd process.cwd();const targetDirectory path.join(cwd, projectName);if (fs.existsSync(targetDirectory)) {if (options.force) {// 存在force配置项直接覆盖await fs.remove(targetDirectory);} else {// 不存在force配置 项询问是否覆盖let { isOverwrite } await inquirerChoose(isOverwrite,Target directory exists,Please choose an action.,[{name: Overwrite,value: true,},{name: Cancel,value: false,},]);if (!isOverwrite) {console.log(Cancel);return;} else {loading.start(Removing ${projectName},please wait a minute);await fs.remove(targetDirectory);loading.stop();}}}const spinner ora(Creating a project......).start();try {await mkdir(targetDirectory);const TemplatePath ${process.cwd()}/${TempLatesName};if (await readDir(TemplatePath)) {spinner.fail(Cred(${TempLatesName} is existed!Please remove it));process.abort();}spinner.stop()//下载模版git//TempLatesRepo 模版git地址exec(git clone ${TempLatesRepo}, async (err) {if(err){spinner.fail(Cred(can not clone this repo,please try again later!));spinner.fail(Cred(typeof err string ? err : JSON.stringify(err)));process.abort();}const project await readFile( ${TemplatePath}/project.json)//读取模版工程中project.json文件。存放模版listconst question [{type: list,message: Please select a project template,name: template,choices: JSON.parse(project),// string[]},];const { template } await inquirer.prompt(question);const newPath targetDirectory;const oldPath TemplatePath / template;loading.start(Template generation...);await copyFolder(oldPath, newPath);// 删除克隆模板await rm(TemplatePath);loading.stop()});} catch (err) {console.log(Cred(Project creation failure));spinner.fail(Cred(typeof err string ? err : JSON.stringify(err)));process.abort();}
} 创建项目 选择模版