TS语言自定义脚手架

初始化

  • 新建文件夹
  • 初始化命令
  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 文件
	registry=https://mirrors.huaweicloud.com/repository/npm

TS配置

建【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 build

build后bin文件夹下自动新增index.js文件
验证修改是否生效都需要build

在这里插入图片描述

cnpm link
gaogao

在这里插入图片描述

安装相关工具

安装固定版本,有些版本会有bug

commander

https://www.npmjs.com/package/commander

  • 处理控制台命令工具
  • 解析用户输入时一些参数
    • 例如 create 就是利用此工具做解析辅助
cnpm i commander@9.0.0
import {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 commands
import { 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 figlet@1.5.2 @types/figlet
import 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 inquirer@8.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): Promise<object> => {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:Array<any>): Promise<any> => {const answer = await inquirer.prompt({type: 'list',name,message,choices,});return answer;
}/*** @param {Array} messages  询问提示语句数组* @returns {Object} 结果对象*/
export const inquirerInputs = async (messages: Array<any>): Promise<object> => {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 options==='object'&&!options.frames&&(options.frames=['<','<','^','>','>','_','_'])this.load = loading(options).start()}else{this.load.start(options as string)}};stop () {this.load && this.load.stop();};succeed(text='success') {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-extra.0.1  /fs-extra

封装文件处理方法

import fs from "fs";import { Cred } from "./chalk";export const readDir = (path: string): Promise<any> =>new Promise((res, rej) => {fs.readdir(path, (err) => {if (!err) res(true);res(false)});});export const mkdir = (path: string): Promise<any> =>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): Promise<any> =>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 ora@5.4.1
# 安装download-git-repo模块,该模块用于下载并提取Github/Git(template本地)仓库中的文件。
cnpm i download-git-repo@3.0.2
# 安装handlebars模块,该模块用于处理模板文件。
cnpm i handlebars@4.7.6
# 安装log-symbols模块,该模块用于在控制台输出不同类型的日志符号(√或×)。
cnpm i log-symbols@4.1.0
# 安装axios模块,该模块用于发起HTTP请求。
cnpm i axios@0.26.1
# 安装gitee-repo模块,该模块用于从Gitee仓库中下载模板文件。
cnpm i gitee-repo@0.0.2
# 命令行界面表格内容显示
cnpm i table
# 基于nodejs的shell命令工具
cnpm i shelljs @types/shelljs 
# 在控制台输出不同类型的日志符号(√或×)
cnpm i log-symbols@4.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 ls

在这里插入图片描述

create命令

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();}
}

在这里插入图片描述

  • 创建项目
    在这里插入图片描述
  • 选择模版
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21519.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ETL工具: Kettle入门(示例从oracle到oracle的数据导入)

kettle介绍 ETL工具,用于对数据的抽取&#xff08;Extract), 转换(Transform),加载 (Load&#xff09; Kettle 是一种ETL工具, 现称为 Pentaho Data Integration (PDI) 特点:纯JAVA语言编写 官方学习文档 网站: https://docs.hitachivantara.com/r/en-us/pentaho-data-int…

一周学会Flask3 Python Web开发-response响应格式

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在HTTP响应中&#xff0c;数据可以通过多种格式传输。大多数情况下&#xff0c;我们会使用HTML格式&#xff0c;这也是Flask中…

内外网隔离文件传输解决方案|系统与钉钉集成+等保合规,安全提升70%

一、背景与痛点 在内外网隔离的企业网络环境中&#xff0c;员工与外部协作伙伴&#xff08;如钉钉用户&#xff09;的文件传输面临以下挑战&#xff1a; 1. **安全性风险**&#xff1a;内外网直连可能导致病毒传播、数据泄露。 2. **操作繁琐**&#xff1a;传统方式需频繁切…

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…

Jetpack Architecture系列教程之(三)——ViewModel控制器

目录 介绍 如何使用 添加依赖 构建ViewModel 分析ViewModel ViewModel生命周期 ViewModel加载原理 介绍 ViewModel 的出现是为了解决数据因Android UI控制器在生命周期活动中造成数据丢失的问题。 在一般情况下&#xff0c;页面数据丢失&#xff08;转屏、闪退等生命周期…

Vue3.5 企业级管理系统实战(七):Sidebar组件开发 1

现在开始&#xff0c;我们要进行 Sidebar 组件的开发&#xff0c;篇幅和时间原因&#xff0c;本篇先探讨 el-menu 的配置。 1 菜单样式设置 在 src/style/variables.module.scss 中&#xff0c;我们设置菜单样式相关的变量&#xff0c;这些变量将用于后续组件的样式配置。 /…

LeetCode:2595.奇偶位数

给你一个 正 整数 n 。用 even 表示在 n 的二进制形式&#xff08;下标从 0 开始&#xff09;中值为 1 的偶数下标的个数。用 odd 表示在 n 的二进制形式&#xff08;下标从 0 开始&#xff09;中值为 1 的奇数下标的个数。请注意&#xff0c;在数字的二进制表示中&#xff0c;…

【算法精练】背包问题(01背包问题)

目录 1. 背包问题 2. 01背包问题 3. 优化 总结 1. 背包问题 经典的背包问题&#xff1a; 有一个背包&#xff0c;限制背包的体积&#xff1b;有一堆物品&#xff0c;从这堆物品中选择&#xff0c;在不超过背包容量的前提下&#xff0c;选出最大价值的物品&#xff1b; 从这个…

ubuntu 执行 sudo apt-get update 报错

记录一下&#xff0c;遇到这个问题了&#xff0c;网络上看到的解决办法&#xff0c;亲测有效 执行sudo apt-get update ,却报以下错误&#xff0c;“SECURITY: URL redirect target contains control characters rejecting ” 经检查发现&#xff0c;/etc/apt/source.list 下的…

如何调用 DeepSeek API:详细教程与示例

目录 一、准备工作 二、DeepSeek API 调用步骤 1. 选择 API 端点 2. 构建 API 请求 3. 发送请求并处理响应 三、Python 示例&#xff1a;调用 DeepSeek API 1. 安装依赖 2. 编写代码 3. 运行代码 四、常见问题及解决方法 1. API 调用返回 401 错误 2. API 调用返回…

MySQL初学之旅(5)详解查询

目录 1.前言 2.正文 2.1聚合查询 2.1.1count() 2.1.2sum() 2.1.3avg() 2.1.4max() 2.1.5min() 2.1.6总结 2.2分组查询 2.2.1group by字句 2.2.2having字句 2.2.3group by与having的关系 2.3联合查询 2.3.1笛卡尔积 2.3.2内连接 2.3.3外连接 2.3.4自连接 2.3…

深入解析 vLLM:高性能 LLM 服务框架的架构之美(二)调度管理

深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;一&#xff09;原理与解析 深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;二&#xff09;调度管理 1. vLLM 调度器结构与主要组件 在 vLLM 中&#xff0c;调度器的结构设计围绕任务…

2.20学习

crypto buu-这是什么 下载附件后打开看到是apk文件&#xff0c;试试直接用记事本打开&#xff0c;看到乱码以外&#xff0c;还有一堆有规律的符号&#xff0c;了解后发现是jsfuck编码&#xff0c;搜索在线工具解码就行 misc buu-[BJDCTF2020]藏藏藏 下载附件&#xff0c;得…

【Java八股文】08-计算机网络面试篇

【Java八股文】08-计算机网络面试篇 计算机网络面试篇网络模型网络OSI模型和TCP/IP模型分别介绍一下键入网址到网页显示&#xff0c;期间发生了什么&#xff1f; 应用层- HTTP应用层有哪些协议&#xff1f;HTTP是什么及HTTP报文有哪些部分&#xff1f;HTTP是怎么传输数据的HTTP…

DeepSeek 助力 Vue 开发:打造丝滑的瀑布流布局(Masonry Layout)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

基于知识图谱的问答系统:后端Python+Flask,数据库Neo4j,前端Vue3(提供源码)

基于知识图谱的问答系统&#xff1a;后端PythonFlask&#xff0c;数据库Neo4j&#xff0c;前端Vue3 引言 随着人工智能技术的不断发展&#xff0c;知识图谱作为一种结构化的知识表示方式&#xff0c;逐渐成为问答系统的重要组成部分。本文将介绍如何构建一个基于知识图谱的问答…

AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践

清华大学出品《DeepSeek&#xff1a;从入门到精通》分享 在忙碌的职场中&#xff0c;制作一份高质量的PPT往往需要投入大量时间和精力&#xff0c;尤其是在临近截止日期时。今天&#xff0c;我们将探索如何借助 AI 工具 —— DeepSeek 和 Kimi —— 让 PPT 制作变得既快捷又高…

基于Flask的京东商品信息可视化分析系统的设计与实现

【Flask】基于Flask的京东商品信息可视化分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 系统能够灵活地执行SQL查询&#xff0c;提取出用于分析的关键数据指标。为了将这…

Spring Cloud — 深入了解Eureka、Ribbon及Feign

Eureka 负责服务注册与发现&#xff1b;Ribbon负责负载均衡&#xff1b;Feign简化了Web服务客户端调用方式。这三个组件可以协同工作&#xff0c;共同构建稳定、高效的微服务架构。 1 Eureka 分布式系统的CAP定理&#xff1a; 一致性&#xff08;Consistency&#xff09;&am…

Ubuntu 22.04 一键部署MinerU1.1.0

MinerU MinerU是一款将PDF转化为机器可读格式的工具&#xff08;如markdown、json&#xff09;&#xff0c;可以很方便地抽取为任意格式。 MinerU诞生于书生-浦语的预训练过程中&#xff0c;我们将会集中精力解决科技文献中的符号转化问题&#xff0c;希望在大模型时代为科技发…