@quiteer/scripts 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +327 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Soybean
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import cac from "cac";
|
|
2
|
+
import { bgRed, blue, gray, green, lightGreen, red, yellow } from "kolorist";
|
|
3
|
+
import { rimraf } from "rimraf";
|
|
4
|
+
import { access, writeFile } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { prompt } from "enquirer";
|
|
8
|
+
import { loadConfig } from "c12";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { versionBump } from "bumpp";
|
|
11
|
+
|
|
12
|
+
//#region package.json
|
|
13
|
+
var version = "0.0.1";
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/commands/cleanup.ts
|
|
17
|
+
async function cleanup(paths) {
|
|
18
|
+
await rimraf(paths, { glob: true });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/config/index.ts
|
|
23
|
+
const defaultOptions = {
|
|
24
|
+
cwd: process.cwd(),
|
|
25
|
+
cleanupDirs: [
|
|
26
|
+
"**/dist",
|
|
27
|
+
"**/node_modules",
|
|
28
|
+
"!node_modules/**"
|
|
29
|
+
],
|
|
30
|
+
lang: "zh-cn",
|
|
31
|
+
ncuCommandArgs: ["--deep", "-u"],
|
|
32
|
+
gitCommitVerifyIgnores: [
|
|
33
|
+
/^((Merge pull request)|(Merge (.*?) into (.*)|(Merge branch (.*)))(?:\r?\n)*$)/m,
|
|
34
|
+
/^(Merge tag (.*))(?:\r?\n)*$/m,
|
|
35
|
+
/^(R|r)evert (.*)/,
|
|
36
|
+
/^(amend|fixup|squash)!/,
|
|
37
|
+
/^(Merged (.*?)(in|into) (.*)|Merged PR (.*): (.*))/,
|
|
38
|
+
/^Merge remote-tracking branch(\s*)(.*)/,
|
|
39
|
+
/^Automatic merge(.*)/,
|
|
40
|
+
/^Auto-merged (.*?) into (.*)/
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
async function loadCliOptions(overrides, cwd = process.cwd()) {
|
|
44
|
+
const { config } = await loadConfig({
|
|
45
|
+
name: "quiteer",
|
|
46
|
+
defaults: defaultOptions,
|
|
47
|
+
overrides,
|
|
48
|
+
cwd,
|
|
49
|
+
packageJson: true
|
|
50
|
+
});
|
|
51
|
+
return config;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/commands/generate-cfg.ts
|
|
56
|
+
/**
|
|
57
|
+
* 函数:在项目根目录生成 quiteer 配置文件
|
|
58
|
+
* 作用:若已有配置则询问是否覆盖;按默认配置生成 `quiteer.config.ts`
|
|
59
|
+
*/
|
|
60
|
+
async function generateConfig() {
|
|
61
|
+
const cwd = process.cwd();
|
|
62
|
+
const configPath = path.join(cwd, "quiteer.config.ts");
|
|
63
|
+
let exists = true;
|
|
64
|
+
try {
|
|
65
|
+
await access(configPath);
|
|
66
|
+
} catch {
|
|
67
|
+
exists = false;
|
|
68
|
+
}
|
|
69
|
+
if (exists) {
|
|
70
|
+
const { overwrite } = await prompt([{
|
|
71
|
+
name: "overwrite",
|
|
72
|
+
type: "confirm",
|
|
73
|
+
message: `检测到已存在配置文件 ${path.basename(configPath)},是否覆盖?`
|
|
74
|
+
}]);
|
|
75
|
+
if (!overwrite) return;
|
|
76
|
+
}
|
|
77
|
+
const regexList = defaultOptions.gitCommitVerifyIgnores.map((r) => r.toString());
|
|
78
|
+
const indentJson = (val) => {
|
|
79
|
+
return JSON.stringify(val, null, 2).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
80
|
+
};
|
|
81
|
+
await writeFile(configPath, [
|
|
82
|
+
"// 自动生成的 quiteer 配置文件",
|
|
83
|
+
"",
|
|
84
|
+
"export default {",
|
|
85
|
+
` cleanupDirs: ${indentJson(defaultOptions.cleanupDirs)},`,
|
|
86
|
+
` lang: ${JSON.stringify(defaultOptions.lang)},`,
|
|
87
|
+
` ncuCommandArgs: ${indentJson(defaultOptions.ncuCommandArgs)},`,
|
|
88
|
+
" gitCommitVerifyIgnores: [",
|
|
89
|
+
...regexList.map((r, idx, arr) => ` ${r}${idx < arr.length - 1 ? "," : ""}`),
|
|
90
|
+
" ]",
|
|
91
|
+
"}",
|
|
92
|
+
""
|
|
93
|
+
].join("\n"), "utf8");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/locales/index.ts
|
|
98
|
+
const locales = {
|
|
99
|
+
"zh-cn": {
|
|
100
|
+
gitCommitMessages: {
|
|
101
|
+
types: "请选择提交类型",
|
|
102
|
+
scopes: "请选择提交范围",
|
|
103
|
+
description: `请输入描述信息(${yellow("!")}开头表示破坏性改动`
|
|
104
|
+
},
|
|
105
|
+
gitCommitTypes: [
|
|
106
|
+
["feat", "新功能"],
|
|
107
|
+
["feat-wip", "开发中的功能,比如某功能的部分代码"],
|
|
108
|
+
["fix", "修复Bug"],
|
|
109
|
+
["docs", "只涉及文档更新"],
|
|
110
|
+
["typo", "代码或文档勘误,比如错误拼写"],
|
|
111
|
+
["style", "修改代码风格,不影响代码含义的变更"],
|
|
112
|
+
["refactor", "代码重构,既不修复 bug 也不添加功能的代码变更"],
|
|
113
|
+
["perf", "可提高性能的代码更改"],
|
|
114
|
+
["optimize", "优化代码质量的代码更改"],
|
|
115
|
+
["test", "添加缺失的测试或更正现有测试"],
|
|
116
|
+
["build", "影响构建系统或外部依赖项的更改"],
|
|
117
|
+
["ci", "对 CI 配置文件和脚本的更改"],
|
|
118
|
+
["chore", "没有修改src或测试文件的其他变更"],
|
|
119
|
+
["revert", "还原先前的提交"]
|
|
120
|
+
],
|
|
121
|
+
gitCommitScopes: [
|
|
122
|
+
["projects", "项目"],
|
|
123
|
+
["packages", "包"],
|
|
124
|
+
["components", "组件"],
|
|
125
|
+
["hooks", "钩子函数"],
|
|
126
|
+
["utils", "工具函数"],
|
|
127
|
+
["types", "TS类型声明"],
|
|
128
|
+
["styles", "代码风格"],
|
|
129
|
+
["deps", "项目依赖"],
|
|
130
|
+
["release", "发布项目新版本"],
|
|
131
|
+
["other", "其他的变更"]
|
|
132
|
+
],
|
|
133
|
+
gitCommitVerify: `${bgRed(" 错误 ")} ${red("git 提交信息必须符合 Conventional Commits 标准!")}\n\n${green("推荐使用命令 `pnpm commit` 生成符合 Conventional Commits 标准的提交信息。\n获取有关 Conventional Commits 的更多信息,请访问此链接: https://conventionalcommits.org")}`
|
|
134
|
+
},
|
|
135
|
+
"en-us": {
|
|
136
|
+
gitCommitMessages: {
|
|
137
|
+
types: "Please select a type",
|
|
138
|
+
scopes: "Please select a scope",
|
|
139
|
+
description: `Please enter a description (add prefix ${yellow("!")} to indicate breaking change)`
|
|
140
|
+
},
|
|
141
|
+
gitCommitTypes: [
|
|
142
|
+
["feat", "A new feature"],
|
|
143
|
+
["feat-wip", "Features in development, such as partial code for a certain feature"],
|
|
144
|
+
["fix", "A bug fix"],
|
|
145
|
+
["docs", "Documentation only changes"],
|
|
146
|
+
["typo", "Code or document corrections, such as spelling errors"],
|
|
147
|
+
["style", "Changes that do not affect the meaning of the code"],
|
|
148
|
+
["refactor", "A code change that neither fixes a bug nor adds a feature"],
|
|
149
|
+
["perf", "A code change that improves performance"],
|
|
150
|
+
["optimize", "A code change that optimizes code quality"],
|
|
151
|
+
["test", "Adding missing tests or correcting existing tests"],
|
|
152
|
+
["build", "Changes that affect the build system or external dependencies"],
|
|
153
|
+
["ci", "Changes to our CI configuration files and scripts"],
|
|
154
|
+
["chore", "Other changes that don't modify src or test files"],
|
|
155
|
+
["revert", "Reverts a previous commit"]
|
|
156
|
+
],
|
|
157
|
+
gitCommitScopes: [
|
|
158
|
+
["projects", "project"],
|
|
159
|
+
["packages", "packages"],
|
|
160
|
+
["components", "components"],
|
|
161
|
+
["hooks", "hook functions"],
|
|
162
|
+
["utils", "utils functions"],
|
|
163
|
+
["types", "TS declaration"],
|
|
164
|
+
["styles", "style"],
|
|
165
|
+
["deps", "project dependencies"],
|
|
166
|
+
["release", "release project"],
|
|
167
|
+
["other", "other changes"]
|
|
168
|
+
],
|
|
169
|
+
gitCommitVerify: `${bgRed(" ERROR ")} ${red("git commit message must match the Conventional Commits standard!")}\n\n${green("Recommended to use the command `pnpm commit` to generate Conventional Commits compliant commit information.\nGet more info about Conventional Commits, follow this link: https://conventionalcommits.org")}`
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/shared/index.ts
|
|
175
|
+
async function execCommand(cmd, args, options) {
|
|
176
|
+
const { execa } = await import("execa");
|
|
177
|
+
return ((await execa(cmd, args, options))?.stdout)?.trim() || "";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/commands/git-commit.ts
|
|
182
|
+
/**
|
|
183
|
+
* 函数:交互式添加变更文件到暂存区
|
|
184
|
+
* 作用:先询问是否添加全部;若否,列出变更文件供多选后执行 git add
|
|
185
|
+
*/
|
|
186
|
+
async function gitCommitAdd() {
|
|
187
|
+
const { confirm } = await prompt([{
|
|
188
|
+
name: "confirm",
|
|
189
|
+
type: "confirm",
|
|
190
|
+
message: "是否添加所有变更文件到暂存区?"
|
|
191
|
+
}]);
|
|
192
|
+
if (!confirm) {
|
|
193
|
+
const files = (await execCommand("git", ["diff", "--name-only"])).split("\n").filter(Boolean);
|
|
194
|
+
if (files.length === 0) return;
|
|
195
|
+
const { selected } = await prompt([{
|
|
196
|
+
name: "selected",
|
|
197
|
+
type: "multiselect",
|
|
198
|
+
message: "选择需要添加到暂存区的文件(空格选择,回车确认)",
|
|
199
|
+
choices: files.map((f) => ({
|
|
200
|
+
name: f,
|
|
201
|
+
value: f
|
|
202
|
+
}))
|
|
203
|
+
}]);
|
|
204
|
+
if (!selected?.length) return;
|
|
205
|
+
await execCommand("git", ["add", ...selected], { stdio: "inherit" });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
await execCommand("git", ["add", "."], { stdio: "inherit" });
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Git commit with Conventional Commits standard
|
|
212
|
+
*
|
|
213
|
+
* @param lang
|
|
214
|
+
*/
|
|
215
|
+
async function gitCommit(lang = "en-us") {
|
|
216
|
+
const { gitCommitMessages, gitCommitTypes, gitCommitScopes } = locales[lang];
|
|
217
|
+
const typesChoices = gitCommitTypes.map(([value, msg]) => {
|
|
218
|
+
return {
|
|
219
|
+
name: value,
|
|
220
|
+
message: `${`${value}:`.padEnd(12)}${msg}`
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
const scopesChoices = gitCommitScopes.map(([value, msg]) => ({
|
|
224
|
+
name: value,
|
|
225
|
+
message: `${value.padEnd(30)} (${msg})`
|
|
226
|
+
}));
|
|
227
|
+
const result = await prompt([
|
|
228
|
+
{
|
|
229
|
+
name: "types",
|
|
230
|
+
type: "select",
|
|
231
|
+
message: gitCommitMessages.types,
|
|
232
|
+
choices: typesChoices
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "scopes",
|
|
236
|
+
type: "select",
|
|
237
|
+
message: gitCommitMessages.scopes,
|
|
238
|
+
choices: scopesChoices
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "description",
|
|
242
|
+
type: "text",
|
|
243
|
+
message: gitCommitMessages.description
|
|
244
|
+
}
|
|
245
|
+
]);
|
|
246
|
+
const breaking = result.description.startsWith("!") ? "!" : "";
|
|
247
|
+
const description = result.description.replace(/^!/, "").trim();
|
|
248
|
+
await execCommand("git", [
|
|
249
|
+
"commit",
|
|
250
|
+
"-m",
|
|
251
|
+
`${result.types}(${result.scopes})${breaking}: ${description}`
|
|
252
|
+
], { stdio: "inherit" });
|
|
253
|
+
}
|
|
254
|
+
/** Git commit message verify */
|
|
255
|
+
async function gitCommitVerify(lang = "zh-cn", ignores = []) {
|
|
256
|
+
const gitPath = await execCommand("git", ["rev-parse", "--show-toplevel"]);
|
|
257
|
+
const commitMsg = readFileSync(path.join(gitPath, ".git", "COMMIT_EDITMSG"), "utf8").trim();
|
|
258
|
+
if (ignores.some((regExp) => regExp.test(commitMsg))) return;
|
|
259
|
+
if (!/(?<type>[a-z]+)(?:\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i.test(commitMsg)) {
|
|
260
|
+
const errorMsg = locales[lang].gitCommitVerify;
|
|
261
|
+
throw new Error(errorMsg);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region src/commands/release.ts
|
|
267
|
+
async function release(execute = "", push = true) {
|
|
268
|
+
await versionBump({
|
|
269
|
+
files: ["**/package.json", "!**/node_modules"],
|
|
270
|
+
execute,
|
|
271
|
+
all: true,
|
|
272
|
+
tag: true,
|
|
273
|
+
commit: "chore(projects): release v%s",
|
|
274
|
+
push
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/commands/update-pkg.ts
|
|
280
|
+
async function updatePkg(args = ["--deep", "-u"]) {
|
|
281
|
+
execCommand("npx", ["npm-check-updates", ...args], { stdio: "inherit" });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/index.ts
|
|
286
|
+
async function setupCli() {
|
|
287
|
+
/**
|
|
288
|
+
* 初始化并注册 CLI
|
|
289
|
+
* - 加载配置,注册命令与选项
|
|
290
|
+
* - 设置中文提示与帮助文案
|
|
291
|
+
* @returns Promise<void>
|
|
292
|
+
*/
|
|
293
|
+
const cliOptions = await loadCliOptions();
|
|
294
|
+
const cli = cac(blue("quiteer-scripts"));
|
|
295
|
+
cli.version(lightGreen(version)).help();
|
|
296
|
+
cli.command("generate-config", "在项目根目录下生成配置文件").alias("g").action(async () => {
|
|
297
|
+
await generateConfig();
|
|
298
|
+
});
|
|
299
|
+
cli.command("remove [path]", "删除单个或者多个文件,多个值用逗号分隔,递归删除").alias("rm").action(async (paths) => {
|
|
300
|
+
if (paths && paths.includes(",")) await cleanup(paths.split(","));
|
|
301
|
+
else if (paths) await cleanup([paths]);
|
|
302
|
+
else console.info("quiteer-script :>> ", gray("无事发生"));
|
|
303
|
+
});
|
|
304
|
+
cli.command("cleanup [path]", "清除目录 node_modules、dist 等").alias("c").action(async (paths) => {
|
|
305
|
+
if (paths && paths.includes(",")) await cleanup(paths.split(","));
|
|
306
|
+
else if (paths) await cleanup([paths]);
|
|
307
|
+
else await cleanup(cliOptions.cleanupDirs);
|
|
308
|
+
});
|
|
309
|
+
cli.command("update-pkg", "更新 package.json 依赖版本").alias("u").action(async () => {
|
|
310
|
+
await updatePkg(cliOptions.ncuCommandArgs);
|
|
311
|
+
});
|
|
312
|
+
cli.command("git-commit", "git 提交前后的操作和规范等").alias("git-c").option("--add", "添加所有变更文件到暂存区", { default: true }).option("-l ,--lang", "校验提交信息的语言", { default: cliOptions.lang }).action(async (args) => {
|
|
313
|
+
if (args?.add) await gitCommitAdd();
|
|
314
|
+
await gitCommit(args?.lang);
|
|
315
|
+
});
|
|
316
|
+
cli.command("git-commit-verify", "校验提交信息是否符合 Conventional Commits 标准").alias("git-v").option("-l --lang", "校验提交信息的语言", { default: cliOptions.lang }).action(async (args) => {
|
|
317
|
+
await gitCommitVerify(args?.lang, cliOptions.gitCommitVerifyIgnores);
|
|
318
|
+
});
|
|
319
|
+
cli.command("release", "发布:更新版本、生成变更日志、提交代码").alias("r").option("--execute", "执行发布的命令").option("--push", "是否推送代码", { default: true }).action(async (args) => {
|
|
320
|
+
await release(args?.execute, args?.push);
|
|
321
|
+
});
|
|
322
|
+
cli.parse();
|
|
323
|
+
}
|
|
324
|
+
setupCli();
|
|
325
|
+
|
|
326
|
+
//#endregion
|
|
327
|
+
export { setupCli };
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quiteer/scripts",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"homepage": "https://github.com/TaiAiAc/web",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.mjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.mjs",
|
|
18
|
+
"module": "./dist/index.mjs",
|
|
19
|
+
"types": "./dist/index.d.mts",
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
"*": {
|
|
22
|
+
"*": [
|
|
23
|
+
"./src/*"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"quiteer": "./dist/index.mjs",
|
|
29
|
+
"qui": "./dist/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"bumpp": "10.3.1",
|
|
36
|
+
"c12": "3.3.2",
|
|
37
|
+
"cac": "6.7.14",
|
|
38
|
+
"consola": "3.4.2",
|
|
39
|
+
"enquirer": "2.4.1",
|
|
40
|
+
"execa": "9.6.0",
|
|
41
|
+
"kolorist": "1.8.0",
|
|
42
|
+
"npm-check-updates": "19.1.2",
|
|
43
|
+
"rimraf": "6.1.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"tsdown": "^0.16.1",
|
|
47
|
+
"tsx": "^4.20.6"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"dev": "tsdown -w",
|
|
51
|
+
"build": "tsdown",
|
|
52
|
+
"release": "pnpm publish"
|
|
53
|
+
}
|
|
54
|
+
}
|