当前位置: 首页 > news >正文

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

在这里插入图片描述

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

相关文章:

TS语言自定义脚手架

初始化 新建文件夹初始化命令 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…...

深度学习-122-大语言模型LLM之基于langchian自定义国内联网查询工具并创建智能代理

文章目录 1 访问百度1.1 百度检索1.2 库baidusearch2 自定义工具@tool装饰器3 使用工具创建智能代理3.1 语言模型与工具结合3.2 方式一create_react_agent3.3 方式二create_tool_calling_agent3.4 给代理添加记忆4 参考附录1 访问百度 1.1 百度检索 from bs4 import Beautifu…...

Docker Desktop 入门教学

引言 Docker Desktop 是 Docker 官方为开发者提供的桌面应用程序&#xff0c;支持在 Windows 和 macOS 上轻松构建、运行和共享容器化应用程序。它集成了 Docker 引擎、Docker CLI 客户端以及 Docker Compose 等工具&#xff0c;方便您在本地开发和测试。 一、快速安装 1. 系…...

PyCharm 中的 %reset -f 功能:一键重置控制台变量

在 PyCharm 的日常使用中&#xff0c;我们经常需要在控制台中测试和运行各种代码片段。随着时间的推移&#xff0c;控制台中会积累大量的变量和输出&#xff0c;这可能会使得环境变得混乱&#xff0c;影响我们的开发效率。为了解决这个问题&#xff0c;IPython 提供了一个非常有…...

ollama-chat-ui-vue,一个可以用vue对接ollama的开源项目,可接入deepSeek

ollama-chat-ui-vue 使用vue3 vite elementUi 搭建的前端chat,通过ollama可与模型对话,目前支持独立思考,切换模型(联网查询后续支持) github地址&#xff1a;ollama-chat-ui-vue 制作不易github点点star&#xff0c;谢谢 前置工作 安装ollama,ollama官网地址 安装完olla…...

在Logback中拦截和修改日志

事实上,Logback并没有提供修改日志的直接方法,但有一种解决方法可以通过使用过滤器来实现我们的目标,即使它看起来有点黑客。 假设你记录了某个用户的某个id号数百次,它分散在整个应用程序中,现在你有了一个新的要求,要求你必须加密这个id号。当然,你足够聪明,可以为此…...

Compose 定制UI视图

Compose 定制UI视图 概述MaterialThemeMaterialTheme与CompositionLocalMaterialThemeCompositionLocal 定制主题方案 概述 新建一个新项目时&#xff0c;Compose会在项目中生成 ui/theme 目录&#xff0c;目录中有四个文件&#xff0c;分别如下 Color.kt&#xff1a;颜色配置…...

《STL 六大组件之容器探秘:深入剖析 string》

目录 一、string 类简介二、string 类的常用接口1. 构造函数&#xff08;constructor function&#xff09;2. 与容量相关的接口&#xff08;capacity&#xff09;3. 与迭代器有关的接口&#xff08;iterator&#xff09;4. 与元素访问有关的接口&#xff08;element access&am…...

DeepSeek 助力 Vue 开发:打造丝滑的点击动画(Click Animations)

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

SeaTunnel社区「Demo方舟计划」首期活动上线—— MySQL CDC实时同步至PostgreSQL实战

引言 凌晨2点&#xff0c;某电商公司的数据工程师小李正对着屏幕抓狂——业务部门临时要求将MySQL的订单表实时同步到PostgreSQL进行分析&#xff0c;众所周知&#xff0c;在数据驱动的业务场景中&#xff0c;异构数据源同步是高频刚需。 以MySQL到PostgreSQL的CDC同步为例&a…...

Python中常见库 PyTorch和Pydantic 讲解

PyTorch 简介 PyTorch 是一个开源的深度学习框架&#xff0c;由 Facebook 的 AI 研究团队开发。它提供了丰富的工具和库&#xff0c;用于构建和训练各种深度学习模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;及其变体&…...

基于springboot校园健康系统的设计与实现(源码+文档)

大家好我是风歌&#xff0c;今天要和大家聊的是一款基于springboot的园健康系统的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于springboot校园健康系统的设计与实现的主要使用者管理员具有最高的权限&#xff0c;通…...

一文2000字从0到1用Jmeter全流程性能测试实战

项目背景&#xff1a; 我们的平台为全国某行业监控平台&#xff0c;经过3轮功能测试、接口测试后&#xff0c;98%的问题已经关闭&#xff0c;决定对省平台向全国平台上传数据的接口进行性能测试。 01、测试步骤 1、编写性能测试方案 由于我是刚进入此项目组不久&#xff0c…...

【SFRA】笔记

GK_SFRA_INJECT(x) SFRA小信号注入函数,向控制环路注入一个小信号。如下图所示,当前程序,小信号注入是在固定占空比的基础叠加小信号,得到新的占空比,使用该占空比控制环路。 1.2 GK_SFRA_COLLECT(x, y) SFRA数据收集函数,将小信号注入环路后,该函数收集环路的数据,以…...

马拉车算法

Manacher算法 ,用于处理最长回文字符串的问题&#xff0c;可以在O&#xff08;n&#xff09;的情况下&#xff0c;求出一个字符串的最长回文字符串 回文串的基础解法&#xff1a; 以每个点为中心对称点&#xff0c;看左右两边的点是否相同。这种算法的时间复杂度为O&#xff0…...

Debezium同步之如何同步GIS数据

Debezium 可以用于同步数据库中的变更数据(CDC),包括GIS(地理信息系统)数据。GIS 数据通常存储在具有地理空间数据类型的表中,例如 PostGIS(PostgreSQL 的扩展)中的 geometry 或 geography 类型。通过 Debezium,可以实时捕获和同步这类数据的变更。本文章简单介绍Post…...

自动化之ansible(二)

一、ansible中playbook&#xff08;剧本&#xff09; 官方文档&#xff1a; Ansible playbooks — Ansible Community Documentation 1、playbook的基本结构 一个基本的playbook由以下几个主要部分组成 hosts: 定义要执行任务的主机组或主机。 become: 是否需要使用超级用户…...

Docker+Dify部署DeepSeek-r1本地知识库

安装配置Docker Desktop 软件下载 Docker Desktop版本:4.38.0.181591 Docker Desktop下载地址:Docker: Accelerated Container Application Development 或者从这里下载:DockerDesktop-4.38.0.181591资源-CSDN文库 点击图下所示位置,下载windows-AMD64版本软件 启用Hy…...

C#基础:使用Linq进行简单去重处理(DinstinctBy/反射)

目录 一、示例代码 二、示例输出 三、注意雷点 四、全字段去重封装方法 1.封装 2.示例 一、示例代码 using System; using System.Collections.Generic; using System.Linq;public class Program {public static void Main(){// 创建一些示例实体对象var people new Li…...

HTML5 面试题

1. HTML5 新增了哪些重要特性&#xff1f; 语义化标签&#xff1a;这些标签有助于提高页面的可读性和可维护性。多媒体支持&#xff1a;HTML5 引入了 和 标签&#xff0c;可以直接嵌入音频和视频文件&#xff0c;无需依赖插件。本地存储&#xff1a;引入了 localStorage 和 se…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...