文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
packages/utils
调整 package.json
{
"name": "@oweqian/utils",
"version": "0.0.0",
"description": "cli-oweqian utils",
// ...
"main": "lib/index.js",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
// ...
"dependencies": {
"axios": "^1.1.3",
"execa": "^6.1.0",
"fs-extra": "^10.1.0",
"inquirer": "^9.1.3",
"npmlog": "^6.0.2",
"path-exists": "^5.0.0",
"url-join": "^5.0.0"
},
"type": "module"
}
package.json 中 type = "module"
时,.js 后缀文件会被识别为 ESM,如果不指定默认为 commonjs。
入口文件
import isDebug from "./isDebug.js";
import log from "./log.js";
import printErrorLog from "./printErrorLog.js";
import { makeList, makeInput, makePassword } from "./inquirer.js";
import { getLatestVersion } from "./npm.js";
import request from "./request.js";
import Github from "./git/Github.js";
import Gitee from "./git/Gitee.js";
import { getGitPlatform, clearCache } from "./git/GitServer.js";
import {
initGitServer,
initGitType,
createRemotoRepo,
} from "./git/GitUtils.js";
export {
log,
isDebug,
makeList,
makeInput,
makePassword,
getLatestVersion,
printErrorLog,
request,
Github,
Gitee,
getGitPlatform,
initGitServer,
initGitType,
clearCache,
createRemotoRepo,
};
封装 isDebug
/**
* 检测当前 Node.js 进程是否以调试模式启动
* 通过指定命令行参数 --debug 或 -d
*/
export default function isDebug() {
return process.argv.includes("--debug") || process.argv.includes("-d");
}
process.argv 是 Node.js 提供的一个数组,其中包含了命令行输入的参数。第一个元素是 Node.js 可执行文件的路径,第二个元素是被执行的 JavaScript 文件的路径,后面的元素是传递给脚本的命令行参数。
封装 npmlog
import log from "npmlog";
import isDebug from "./isDebug.js";
/**
* 打印日志
*/
if (isDebug()) {
log.level = "verbose";
} else {
log.level = "info";
}
log.heading = "oweqian";
log.addLevel("success", 2000, { fg: "green", bold: true });
export default log;
封装 printErrorLog
import log from "./log.js";
import isDebug from "./isDebug.js";
function printErrorLog(e, type) {
if (isDebug()) {
log.error(type, e);
} else {
log.error(type, e.message);
}
}
export default printErrorLog;
封装 inquirer
import inquirer from "inquirer";
function make({
type = "list",
message = "请选择",
defaultValue,
validate,
require = true,
pageSize,
mask = "*",
choices,
loop,
}) {
const options = {
name: "name",
type,
message,
default: defaultValue,
validate,
require,
pageSize,
mask,
loop,
};
if (type === "list") {
options.choices = choices;
}
return inquirer.prompt(options).then((answer) => answer.name);
}
// list
export function makeList(params) {
return make({ ...params });
}
// input
export function makeInput(params) {
return make({
...params,
type: "input",
});
}
// password
export function makePassword(params) {
return make({
...params,
type: "password",
});
}
封装 npm api
import urlJoin from "url-join";
import axios from "axios";
import log from "./log.js";
/**
* 获取 package 信息
*/
function getNpmInfo(npmName) {
const registry = "https://registry.npmjs.org/";
const url = urlJoin(registry, npmName);
return axios.get(url).then((response) => {
try {
return response.data;
} catch (err) {
return Promise.reject(err);
}
});
}
/**
* 获取 package 最新版本
*/
export function getLatestVersion(npmName) {
return getNpmInfo(npmName).then((data) => {
if (!data["dist-tags"] || !data["dist-tags"].latest) {
log.error("没有 latest 版本号");
return Promise.reject(new Error("没有 latest 版本号"));
}
return data["dist-tags"].latest;
});
}
封装 axios
import axios from "axios";
const BASE_URL = "http://127.0.0.1:7001";
const service = axios.create({
baseURL: BASE_URL,
timeout: 5000,
});
// 成功
function onSuccess(response) {
return response.data;
}
// 失败
function onFailed(error) {
return Promise.reject(error);
}
// 响应拦截器
service.interceptors.response.use(onSuccess, onFailed);
export default service;
封装 Git
GitServer 类
import path from "node:path";
import { execa } from "execa";
import { pathExistsSync } from "path-exists";
import fse from "fs-extra";
import { homedir } from "node:os";
import { makePassword } from "../inquirer.js";
import log from "../log.js";
const TEMP_HOME = ".cli-oweqian";
// 缓存 git token
const TEMP_TOKEN = ".git_token";
// 缓存 git 托管平台信息
const TEMP_PLATFORM = ".git_platform";
// 缓存 git 平台用户信息
const TEMP_OWN = ".git_own";
// 缓存 git 平台组织信息
const TEMP_LOGIN = ".git_login";
function createTokenPath() {
return path.resolve(homedir(), TEMP_HOME, TEMP_TOKEN);
}
function createPlatformPath() {
return path.resolve(homedir(), TEMP_HOME, TEMP_PLATFORM);
}
function createOwnPath() {
return path.resolve(homedir(), TEMP_HOME, TEMP_OWN);
}
function createLoginPath() {
return path.resolve(homedir(), TEMP_HOME, TEMP_LOGIN);
}
function getGitPlatform() {
const platformPath = createPlatformPath();
if (pathExistsSync(platformPath)) {
return fse.readFileSync(platformPath).toString();
}
return null;
}
function getGitOwn() {
const ownPath = createOwnPath();
if (pathExistsSync(ownPath)) {
return fse.readFileSync(ownPath).toString();
}
}
function getGitLogin() {
const loginPath = createLoginPath();
if (pathExistsSync(loginPath)) {
return fse.readFileSync(loginPath).toString();
}
}
function getProjectPath(cwd, fullName) {
const projectName = fullName.split("/")[1];
const projectPath = path.resolve(cwd, projectName);
return projectPath;
}
function getPackageJson(cwd, fullName) {
const projectPath = getProjectPath(cwd, fullName);
const pkgPath = path.resolve(projectPath, "package.json");
if (pathExistsSync(pkgPath)) {
return fse.readJSONSync(pkgPath);
}
return null;
}
/**
* 清除缓存
*/
function clearCache() {
const platform = createPlatformPath();
const token = createTokenPath();
const own = createOwnPath();
const login = createLoginPath();
fse.removeSync(platform);
fse.removeSync(token);
fse.removeSync(own);
fse.removeSync(login);
}
/**
* 封装 GitServer 类
*/
class GitServer {
constructor() {}
// 初始化
async init() {
// 判断 git token 是否存在
const tokenPath = createTokenPath();
if (pathExistsSync(tokenPath)) {
this.token = fse.readFileSync(tokenPath).toString();
} else {
this.token = await this.getToken();
fse.writeFileSync(tokenPath, this.token);
}
log.verbose("token", this.token);
log.verbose("token path", pathExistsSync(tokenPath));
}
getToken() {
return makePassword({
message: "请输入 token 的信息",
});
}
savePlatform(platform) {
this.platform = platform;
fse.writeFileSync(createPlatformPath(), platform);
}
saveOwn(own) {
this.own = own;
fse.writeFileSync(createOwnPath(), own);
}
saveLogin(login) {
this.login = login;
fse.writeFileSync(createLoginPath(), login);
}
getPlatform() {
return this.platform;
}
getOwn() {
return this.own;
}
getLogin() {
return this.login;
}
// 克隆仓库
cloneRepo(fullName, tag) {
if (tag) {
return execa("git", ["clone", this.getRepoUrl(fullName), "-b", tag]);
}
return execa("git", ["clone", this.getRepoUrl(fullName)]);
}
// 安装依赖
installDependencies(cwd, fullName) {
const projectPath = getProjectPath(cwd, fullName);
if (pathExistsSync(projectPath)) {
return execa(
"npm",
["install", "--registry=https://registry.npmmirror.com"],
{ cwd: projectPath }
);
}
}
// 启动项目
async runRepo(cwd, fullName) {
const projectPath = getProjectPath(cwd, fullName);
const pkg = getPackageJson(cwd, fullName);
if (pkg) {
const { scripts, bin, name } = pkg;
// 可执行文件(:脚手架
if (bin) {
await execa(
"npm",
["install", "-g", name, "--registry=https://registry.npmmirror.com"],
{
cwd: projectPath,
stdout: "inherit",
}
);
}
// 项目
if (scripts && scripts.dev) {
return execa("npm", ["run", "dev"], {
cwd: projectPath,
stdout: "inherit",
});
} else if (scripts && scripts.start) {
return execa("npm", ["run", "start"], {
cwd: projectPath,
stdout: "inherit",
});
} else {
log.warn("未找到启动命令");
}
}
}
getUser() {
throw new Error("gitUser must be implemented!");
}
getOrganization() {
throw new Error("getOrganization must be implemented!");
}
createRepo() {
throw new Error("createRepo must be implemented!");
}
}
export { getGitPlatform, GitServer, clearCache, getGitOwn, getGitLogin };
Github
import axios from "axios";
import { GitServer } from "./GitServer.js";
import log from "../log.js";
const BASE_URL = "https://api.github.com";
class Github extends GitServer {
constructor() {
super();
this.service = axios.create({
baseURL: BASE_URL,
timeout: 50000,
});
// 请求拦截器
this.service.interceptors.request.use(
(config) => {
config.headers["Authorization"] = `Bearer ${this.token}`;
config.headers["Accept"] = "application/vnd.github+json";
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
this.service.interceptors.response.use(
(response) => {
return response.data;
},
(error) => {
return Promise.reject(error);
}
);
}
// 封装 get 方法
get(url, params, headers) {
return this.service({
url,
params,
method: "get",
headers,
});
}
// 封装 post 方法
post(url, data, headers) {
return this.service({
url,
data,
method: "post",
headers,
});
}
// 搜索仓库
searchRepositories(params) {
return this.get("/search/repositories", params);
}
// 搜索源码
searchCode(params) {
return this.get("/search/code", params);
}
// 获取 tags
getTags(fullName, params) {
console.log(`/repos/${fullName}/tags`);
return this.get(`/repos/${fullName}/tags`, params);
}
getRepoUrl(fullName) {
return `https://github.com/${fullName}.git`;
}
getUser() {
return this.get("/user");
}
getOrganization() {
return this.get("/user/orgs");
}
getRepo(login, repo) {
return this.get(
`/repos/${login}/${repo}`,
{},
{
accept: "application/vnd.github+json",
}
).catch((err) => {
return null;
});
}
async createRepo(name) {
// 检查远程仓库是否存在,如果存在,则跳过创建
const repo = await this.getRepo(this.login, name);
if (!repo) {
log.info("仓库不存在,开始创建");
if (this.own === "user") {
return this.post(
"/user/repos",
{ name },
{
accept: "application/vnd.github+json",
}
);
} else if (this.own === "organization") {
return this.post(
`/orgs/${this.login}/repos`,
{ name },
{
accept: "application/vnd.github+json",
}
);
}
} else {
log.info("仓库存在,直接返回");
return repo;
}
}
}
export default Github;
Gitee
import axios from "axios";
import { GitServer } from "./GitServer.js";
import log from "../log.js";
const BASE_URL = "https://gitee.com/api/v5";
class Gitee extends GitServer {
constructor() {
super();
this.service = axios.create({
baseURL: BASE_URL,
timeout: 50000,
});
// 响应拦截器
this.service.interceptors.response.use(
(response) => {
return response.data;
},
(error) => {
return Promise.reject(error);
}
);
}
// 封装 get 方法
get(url, params, headers) {
return this.service({
url,
params: {
...params,
access_token: this.token,
},
method: "get",
headers,
});
}
// 封装 post 方法
post(url, data, headers) {
return this.service({
url,
data: {
...data,
access_token: this.token,
},
method: "post",
headers,
});
}
// 搜索仓库
searchRepositories(params) {
return this.get("/search/repositories", params);
}
// 获取 tags
getTags(fullName) {
return this.get(`/repos/${fullName}/tags`);
}
getRepoUrl(fullName) {
return `https://gitee.com/${fullName}.git`;
}
getUser() {
return this.get("/user");
}
getOrganization() {
return this.get("/user/orgs");
}
getRepo(owner, repo) {
return this.get(`/repos/${owner}/${repo}`).catch((err) => {
return null;
});
}
async createRepo(name) {
// 检查远程仓库是否存在,如果存在,则跳过创建
const repo = await this.getRepo(this.login, name);
if (!repo) {
log.info("仓库不存在,开始创建");
if (this.own === "user") {
return this.post("/user/repos", { name });
} else if (this.own === "organization") {
return this.post(`/orgs/${this.login}/repos`, { name });
}
} else {
log.info("仓库存在,直接返回");
return repo;
}
}
}
export default Gitee;
Git Utils
import { getGitPlatform, getGitLogin, getGitOwn } from "./GitServer.js";
import { makeList } from "../inquirer.js";
import log from "../log.js";
import Gitee from "./Gitee.js";
import Github from "./Github.js";
/**
* 实例化 GitServer 对象、git 托管平台、git token
*/
export async function initGitServer() {
let platform = getGitPlatform();
if (!platform) {
platform = await makeList({
message: "请选择 Git 平台",
choices: [
{
name: "Github",
value: "github",
},
{
name: "Gitee",
value: "gitee",
},
],
});
}
log.verbose("platform", platform);
let gitAPI;
if (platform === "github") {
gitAPI = new Github();
} else {
gitAPI = new Gitee();
}
gitAPI.savePlatform(platform);
await gitAPI.init();
return gitAPI;
}
/**
* git 平台用户信息、git 平台组织信息
*/
export async function initGitType(gitAPI) {
// 用户信息
let gitOwn = getGitOwn();
// 组织信息
let gitLogin = getGitLogin();
if (!gitLogin && !gitOwn) {
const user = await gitAPI.getUser();
const organization = await gitAPI.getOrganization();
log.verbose("user", user);
log.verbose("organization", organization);
// 选择仓库类型
if (!gitOwn) {
gitOwn = await makeList({
message: "请选择仓库类型",
choices: [
{
name: "User",
value: "user",
},
{
name: "Organization",
value: "organization",
},
],
});
log.verbose("gitOwn", gitOwn);
}
if (gitOwn === "user") {
gitLogin = user?.login;
} else {
const organizationList = organization.map((item) => ({
name: item.name || item.login,
value: item.login,
}));
gitLogin = await makeList({
message: "请选择组织",
choices: organizationList,
});
}
log.verbose("gitLogin", gitLogin);
}
if (!gitLogin || !gitOwn) {
throw new Error(
'未获取到用户的 Git 登录信息!请使用 "cli-oweqian commit --clear" 清除缓存后重试'
);
}
gitAPI.saveOwn(gitOwn);
gitAPI.saveLogin(gitLogin);
return gitLogin;
}
export async function createRemotoRepo(gitAPI, name) {
const ret = await gitAPI.createRepo(name);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论