@zwa73/dev-utils 1.0.88 → 1.0.89
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/bin/cli +2 -2
- package/data/template/base/package.json +6 -6
- package/data/template/base/scripts/compile.ps1 +23 -6
- package/data/template/base/tsconfig.cjs.json +2 -1
- package/data/template/base/tsconfig.json +3 -5
- package/data/template/base/tsconfig.mjs.json +2 -2
- package/data/template/base/tsconfig.types.json +8 -0
- package/data/template/cjs/gitignore +3 -0
- package/data/template/cjs/package.json +19 -0
- package/data/template/cjs/scripts/compile.ps1 +6 -0
- package/data/template/cjs/scripts/expand-macro.ps1 +2 -0
- package/data/template/cjs/scripts/release.ps1 +4 -0
- package/data/template/cjs/scripts/watch.ps1 +10 -0
- package/data/template/cjs/src/index.ts +0 -0
- package/data/template/cjs/src/macro.macro.ts +6 -0
- package/data/template/cjs/tsconfig.compile.json +12 -0
- package/data/template/cjs/tsconfig.json +21 -0
- package/data/template/electron/package.json +25 -25
- package/dist/{cjs/Command → Command}/GenI18n.js +14 -10
- package/dist/{cjs/Command → Command}/GenTemplate.js +7 -4
- package/dist/{cjs/Command → Command}/ScanDups.js +4 -3
- package/dist/DynImport.d.ts +15 -0
- package/dist/DynImport.js +15 -0
- package/dist/{mjs/UtilAst.d.ts → UtilAst.d.ts} +1 -1
- package/dist/{cjs/UtilDevTool.js → UtilDevTool.js} +13 -34
- package/dist/UtilInterface.d.ts +8 -0
- package/dist/UtilMacro.d.ts +7 -0
- package/dist/{cjs/UtilMacro.js → UtilMacro.js} +2 -2
- package/package.json +2 -8
- package/dist/cjs/UtilAst.d.ts +0 -13
- package/dist/cjs/UtilInterface.d.ts +0 -4
- package/dist/cjs/UtilMacro.d.ts +0 -7
- package/dist/cjs/test/testFileMacro.d.ts +0 -1
- package/dist/cjs/test/testFileMacro.js +0 -1
- package/dist/cjs/test/testGlobMacro.d.ts +0 -1
- package/dist/cjs/test/testGlobMacro.js +0 -2
- package/dist/cjs/test/testRegex.d.ts +0 -1
- package/dist/cjs/test/testRegex.js +0 -3
- package/dist/cjs/test/testRegexa.d.ts +0 -1
- package/dist/cjs/test/testRegexa.js +0 -1
- package/dist/mjs/Command/ExpandMacro.d.ts +0 -3
- package/dist/mjs/Command/ExpandMacro.js +0 -16
- package/dist/mjs/Command/GenI18n.d.ts +0 -3
- package/dist/mjs/Command/GenI18n.js +0 -75
- package/dist/mjs/Command/GenSchema.d.ts +0 -3
- package/dist/mjs/Command/GenSchema.js +0 -22
- package/dist/mjs/Command/GenTemplate.d.ts +0 -3
- package/dist/mjs/Command/GenTemplate.js +0 -61
- package/dist/mjs/Command/MapPath.d.ts +0 -3
- package/dist/mjs/Command/MapPath.js +0 -73
- package/dist/mjs/Command/Node.d.ts +0 -3
- package/dist/mjs/Command/Node.js +0 -14
- package/dist/mjs/Command/Release.d.ts +0 -3
- package/dist/mjs/Command/Release.js +0 -90
- package/dist/mjs/Command/Route.d.ts +0 -1
- package/dist/mjs/Command/Route.js +0 -20
- package/dist/mjs/Command/RouteInterface.d.ts +0 -24
- package/dist/mjs/Command/RouteInterface.js +0 -58
- package/dist/mjs/Command/ScanDups.d.ts +0 -3
- package/dist/mjs/Command/ScanDups.js +0 -114
- package/dist/mjs/Command/index.d.ts +0 -1
- package/dist/mjs/Command/index.js +0 -1
- package/dist/mjs/QuickFunc.d.ts +0 -2
- package/dist/mjs/QuickFunc.js +0 -2
- package/dist/mjs/UtilAst.js +0 -15
- package/dist/mjs/UtilDevTool.d.ts +0 -99
- package/dist/mjs/UtilDevTool.js +0 -297
- package/dist/mjs/UtilInterface.d.ts +0 -4
- package/dist/mjs/UtilInterface.js +0 -1
- package/dist/mjs/UtilMacro.d.ts +0 -7
- package/dist/mjs/UtilMacro.js +0 -23
- package/dist/mjs/index.d.ts +0 -5
- package/dist/mjs/index.js +0 -5
- package/dist/mjs/test/testFileMacro.d.ts +0 -1
- package/dist/mjs/test/testFileMacro.js +0 -1
- package/dist/mjs/test/testGlobMacro.d.ts +0 -1
- package/dist/mjs/test/testGlobMacro.js +0 -2
- package/dist/mjs/test/testRegex.d.ts +0 -1
- package/dist/mjs/test/testRegex.js +0 -2
- package/dist/mjs/test/testRegexa.d.ts +0 -1
- package/dist/mjs/test/testRegexa.js +0 -1
- /package/dist/{cjs/Command → Command}/ExpandMacro.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/ExpandMacro.js +0 -0
- /package/dist/{cjs/Command → Command}/GenI18n.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/GenSchema.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/GenSchema.js +0 -0
- /package/dist/{cjs/Command → Command}/GenTemplate.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/MapPath.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/MapPath.js +0 -0
- /package/dist/{cjs/Command → Command}/Node.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/Node.js +0 -0
- /package/dist/{cjs/Command → Command}/Release.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/Release.js +0 -0
- /package/dist/{cjs/Command → Command}/Route.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/Route.js +0 -0
- /package/dist/{cjs/Command → Command}/RouteInterface.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/RouteInterface.js +0 -0
- /package/dist/{cjs/Command → Command}/ScanDups.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/index.d.ts +0 -0
- /package/dist/{cjs/Command → Command}/index.js +0 -0
- /package/dist/{cjs/QuickFunc.d.ts → QuickFunc.d.ts} +0 -0
- /package/dist/{cjs/QuickFunc.js → QuickFunc.js} +0 -0
- /package/dist/{cjs/UtilAst.js → UtilAst.js} +0 -0
- /package/dist/{cjs/UtilDevTool.d.ts → UtilDevTool.d.ts} +0 -0
- /package/dist/{cjs/UtilInterface.js → UtilInterface.js} +0 -0
- /package/dist/{cjs/index.d.ts → index.d.ts} +0 -0
- /package/dist/{cjs/index.js → index.js} +0 -0
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -1 +0,0 @@
|
|
1
|
-
type CM1 = 3;
|
@@ -1 +0,0 @@
|
|
1
|
-
"use strict";
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import { UtilDT } from "../UtilDevTool.js";
|
2
|
-
/**构造macro */
|
3
|
-
export const CmdExpandMacro = (program) => program
|
4
|
-
.command("Expand-Macro")
|
5
|
-
.alias("expandmacro")
|
6
|
-
.description("根据macro生成代码")
|
7
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts", "src/**/*.macro.ts")
|
8
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
9
|
-
.option("-p, --project <path>", "tsconfig路径 默认tsconfig.json", "tsconfig.json")
|
10
|
-
.action(async (opt) => {
|
11
|
-
await UtilDT.matchNode(process.cwd(), {
|
12
|
-
include: opt.include,
|
13
|
-
exclude: opt.ignore,
|
14
|
-
project: opt.project,
|
15
|
-
});
|
16
|
-
});
|
@@ -1,75 +0,0 @@
|
|
1
|
-
import { SI18n, UtilFT } from "@zwa73/utils";
|
2
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
3
|
-
import { UtilAst } from "../UtilAst.js";
|
4
|
-
import path from 'pathe';
|
5
|
-
function format(str) {
|
6
|
-
return str.replace(/\\(.)/g, '$1').replace(/%/g, '\\%');
|
7
|
-
}
|
8
|
-
async function procFile(p, filePath, funckey) {
|
9
|
-
const date = new Date().toISOString();
|
10
|
-
//const content = await fs.promises.readFile(filePath,'utf-8');
|
11
|
-
const b = p.addSourceFileAtPath(filePath);
|
12
|
-
//const b = p.createSourceFile(path.relative(process.cwd(),filePath),content,{overwrite:true});
|
13
|
-
const ds = b.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);
|
14
|
-
const dats = [];
|
15
|
-
for (const d of ds) {
|
16
|
-
if (!funckey.includes(d.getTag().getText()))
|
17
|
-
continue;
|
18
|
-
const template = d.getTemplate();
|
19
|
-
let result = '';
|
20
|
-
let i = 0;
|
21
|
-
UtilAst.withKind(template, {
|
22
|
-
[SyntaxKind.NoSubstitutionTemplateLiteral]: (t) => result += format(t.getLiteralText()),
|
23
|
-
[SyntaxKind.TemplateExpression]: (t) => {
|
24
|
-
t.getChildren().forEach((c) => {
|
25
|
-
UtilAst.withKind(c, {
|
26
|
-
[SyntaxKind.TemplateHead]: (sc) => result += format(sc.getLiteralText()),
|
27
|
-
[SyntaxKind.SyntaxList]: (sc) => {
|
28
|
-
sc.getChildrenOfKind(SyntaxKind.TemplateSpan).forEach((span) => {
|
29
|
-
span.getChildren().forEach((ssc) => {
|
30
|
-
result += UtilAst.withKind(ssc, {
|
31
|
-
[SyntaxKind.TemplateMiddle]: (sssc) => format(sssc.getLiteralText()),
|
32
|
-
[SyntaxKind.TemplateTail]: (sssc) => format(sssc.getLiteralText()),
|
33
|
-
}) ?? String(`%${i++}`);
|
34
|
-
});
|
35
|
-
});
|
36
|
-
},
|
37
|
-
});
|
38
|
-
});
|
39
|
-
}
|
40
|
-
});
|
41
|
-
const pos = b.getLineAndColumnAtPos(d.getStart());
|
42
|
-
const dat = {
|
43
|
-
original: result,
|
44
|
-
scan_time: date,
|
45
|
-
position: `${filePath}:${pos.line}:${pos.column}`,
|
46
|
-
lang_table: {},
|
47
|
-
source: "Ast"
|
48
|
-
};
|
49
|
-
dats.push(dat);
|
50
|
-
}
|
51
|
-
return dats;
|
52
|
-
}
|
53
|
-
async function scanI18n(i18nDataDir, include, exclude, funckey) {
|
54
|
-
const fixedKey = typeof funckey == 'string' ? [funckey] : funckey;
|
55
|
-
const filePaths = (await UtilFT.fileSearchGlob(process.cwd(), include, { ingore: exclude }))
|
56
|
-
.filter(p => ['.ts', '.tsx'].includes(path.parse(p).ext));
|
57
|
-
const project = new Project();
|
58
|
-
await SI18n.init(i18nDataDir, '*');
|
59
|
-
//console.log(filePaths);
|
60
|
-
(await Promise.all(filePaths.map(p => procFile(project, p, fixedKey))))
|
61
|
-
.flat().forEach(dat => SI18n.addOriginalText(dat));
|
62
|
-
await SI18n.saveTable();
|
63
|
-
}
|
64
|
-
/**生成i18n */
|
65
|
-
export const CmdGenI18n = (program) => program
|
66
|
-
.command("Gen-I18n")
|
67
|
-
.alias("geni18n")
|
68
|
-
.description("根据文件行为树生成i18n数据")
|
69
|
-
.option("-o, --output <path>", "输出的数据目录位置 默认 i18n", 'i18n')
|
70
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.ts", "src/**/*.ts")
|
71
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
72
|
-
.option("-f, --funckey <string|strings>", "扫描的目标函数名, 可传入逗号分隔数组, 默认 t", (i) => i.split(','), ['t'])
|
73
|
-
.action(async (opt) => {
|
74
|
-
await scanI18n(opt.output, opt.include, opt.exclude, opt.funckey);
|
75
|
-
});
|
@@ -1,22 +0,0 @@
|
|
1
|
-
import { UtilDT } from "../UtilDevTool.js";
|
2
|
-
/**生成schema */
|
3
|
-
export const CmdGenSchema = (program) => program
|
4
|
-
.command("Gen-Schema")
|
5
|
-
.alias("genschema")
|
6
|
-
.description("生成匹配的文件的所有type的schema")
|
7
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.schema.ts", "src/**/*.schema.ts")
|
8
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
9
|
-
.option("-p, --project <path>", "tsconfig路径 默认tsconfig.json", "tsconfig.json")
|
10
|
-
.option("-o, --out <dir>", "schema输出路径目录 默认 ./schema/")
|
11
|
-
.option("-it, --include-types <regexp[]>", "包含的types正则匹配数组, 传入逗号分隔数组", (i) => i.split(','))
|
12
|
-
.option("-et, --exclude-types <regexp[]>", "排除的types正则匹配数组, 传入逗号分隔数组", (i) => i.split(','))
|
13
|
-
.action(async (opt) => {
|
14
|
-
await UtilDT.generateSchema(process.cwd(), {
|
15
|
-
include: opt.include,
|
16
|
-
exclude: opt.exclude,
|
17
|
-
project: opt.project,
|
18
|
-
outDir: opt.out,
|
19
|
-
includeTypes: opt.includeTypes,
|
20
|
-
excludeTypes: opt.excludeTypes
|
21
|
-
});
|
22
|
-
});
|
@@ -1,61 +0,0 @@
|
|
1
|
-
import path from 'pathe';
|
2
|
-
import { MIRROR_SOURCE, TEMPLATE_PATH } from "./RouteInterface.js";
|
3
|
-
import { SLogger, UtilFT, UtilFunc } from "@zwa73/utils";
|
4
|
-
import fs from 'fs';
|
5
|
-
/**复制基础文件 */
|
6
|
-
async function copyData(templatePath, projectPath) {
|
7
|
-
const filelist = await fs.promises.readdir(templatePath);
|
8
|
-
const plist = filelist.map(async (fileName) => {
|
9
|
-
SLogger.info(`正在复制 ${fileName}`);
|
10
|
-
const filePath = path.join(templatePath, fileName);
|
11
|
-
const targetPath = path.join(projectPath, fileName);
|
12
|
-
if (!await UtilFT.pathExists(targetPath))
|
13
|
-
await fs.promises.cp(filePath, targetPath, { recursive: true });
|
14
|
-
else
|
15
|
-
SLogger.info(`${fileName} 已存在 跳过`);
|
16
|
-
return null;
|
17
|
-
});
|
18
|
-
await Promise.all(plist);
|
19
|
-
}
|
20
|
-
/**安装npm包 */
|
21
|
-
async function installPackage(projectPath, depList, devDepList) {
|
22
|
-
const install = async (name) => await UtilFunc.exec(`npm i --registry ${MIRROR_SOURCE} ${name}`, { cwd: projectPath });
|
23
|
-
const installdev = async (name) => await UtilFunc.exec(`npm i --registry ${MIRROR_SOURCE} --save-dev ${name}`, { cwd: projectPath });
|
24
|
-
for (const name of depList) {
|
25
|
-
SLogger.info(`正在安装 ${name}`);
|
26
|
-
await install(name);
|
27
|
-
}
|
28
|
-
for (const name of devDepList) {
|
29
|
-
SLogger.info(`正在安装 ${name}`);
|
30
|
-
await installdev(name);
|
31
|
-
}
|
32
|
-
}
|
33
|
-
/**生成schema */
|
34
|
-
export const CmdGenTemplate = (program) => program
|
35
|
-
.command("Gen-Template")
|
36
|
-
.alias("gentemplate")
|
37
|
-
.description("生成项目模板")
|
38
|
-
.argument("<template>", "项目模板 可用 base|electron")
|
39
|
-
.requiredOption("-n, --projectName <name>", "项目名称")
|
40
|
-
.requiredOption("-d, --projectDescription <description>", "项目描述")
|
41
|
-
.requiredOption("-a, --authorName <name>", "作者名")
|
42
|
-
.action(async (templateName, opt) => {
|
43
|
-
const templatePath = path.join(TEMPLATE_PATH, templateName);
|
44
|
-
if (!await UtilFT.pathExists(templatePath))
|
45
|
-
SLogger.error(`模板 ${templateName} 不存在`);
|
46
|
-
const projectPath = path.join(process.cwd(), opt.projectName);
|
47
|
-
await UtilFT.ensurePathExists(projectPath, { dir: true });
|
48
|
-
await copyData(templatePath, projectPath);
|
49
|
-
await installPackage(projectPath, ['@zwa73/utils'], ['@types/node']);
|
50
|
-
if (await UtilFT.pathExists(path.join(projectPath, "gitignore")))
|
51
|
-
await fs.promises.rename(path.join(projectPath, "gitignore"), path.join(projectPath, ".gitignore"));
|
52
|
-
const packageJson = await UtilFT.loadJSONFile(path.join(projectPath, 'package.json'));
|
53
|
-
packageJson.name = opt.projectName;
|
54
|
-
packageJson.description = opt.projectDescription;
|
55
|
-
packageJson.author = opt.authorName;
|
56
|
-
await UtilFT.writeJSONFile(path.join(projectPath, 'package.json'), packageJson);
|
57
|
-
switch (templateName) {
|
58
|
-
case 'base': break;
|
59
|
-
case 'electron': break;
|
60
|
-
}
|
61
|
-
});
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import { SLogger, UtilFT, match, throwError } from "@zwa73/utils";
|
2
|
-
import fs from "fs";
|
3
|
-
import path from "pathe";
|
4
|
-
const DupMethodList = ["skip", "overwrite"];
|
5
|
-
/**重命名文件或路径 */
|
6
|
-
export const CmdMapPath = (program) => program
|
7
|
-
.command("Map-Path")
|
8
|
-
.alias("mappath")
|
9
|
-
.description("根据正则表达式对文件名进行映射")
|
10
|
-
.argument("<regex>", "要匹配的正则表达式, posix风格路径")
|
11
|
-
.argument("<replacement>", "替换字符串")
|
12
|
-
.option("-e, --exclude <regex>", "排除文件的正则表达式")
|
13
|
-
.option(`-d, --duplicate-handling <${DupMethodList.join('|')}|[path:string]>`, `处理重名文件的方式:
|
14
|
-
skip 不进行处理
|
15
|
-
overwrite 覆盖重名
|
16
|
-
其他字符串 将重名部分映射到指定目录下的对应位置, 再次重复将会覆盖`, "skip")
|
17
|
-
.option("-r, --recursive", "是否处理子目录", false)
|
18
|
-
.option("-m, --move", "重命名而不是复制文件", false)
|
19
|
-
.option("-o, --output <path>", "输出到某个绝对路径而非当前目录", '')
|
20
|
-
.option("-i, --input <path>", "扫描某个绝对路径而非当前目录", '')
|
21
|
-
.option("-t, --test", "不对文件进行实际操作, 在控制台输出映射结果", false)
|
22
|
-
.action(async (regexStr, replacement, options) => {
|
23
|
-
const regex = new RegExp(regexStr);
|
24
|
-
const excludeRegex = options.exclude ? new RegExp(options.exclude) : null;
|
25
|
-
if (!DupMethodList.includes(options.duplicateHandling))
|
26
|
-
throwError(`${options.duplicateHandling} 不是有效的 duplicate-handling`);
|
27
|
-
const duplicateHandling = options.duplicateHandling;
|
28
|
-
const absout = options.output.length > 0;
|
29
|
-
const absin = options.input.length > 0;
|
30
|
-
const searchPath = absin ? options.input : process.cwd();
|
31
|
-
const outPath = absout ? options.output : process.cwd();
|
32
|
-
// 遍历当前目录下的所有文件
|
33
|
-
const filePaths = (await UtilFT.fileSearchRegex(searchPath, regex, { relative: options.recursive }))
|
34
|
-
.map(fp => path.relative(searchPath, fp))
|
35
|
-
.filter(fp => excludeRegex ? (!excludeRegex.test(fp)) : true);
|
36
|
-
//对单个路径映射
|
37
|
-
const mapPath = async (source, target) => {
|
38
|
-
if (options.test)
|
39
|
-
return SLogger.info(`${source} -> ${target}`);
|
40
|
-
const dir = path.parse(target).dir;
|
41
|
-
await UtilFT.ensurePathExists(dir, { dir: true });
|
42
|
-
if (options.move)
|
43
|
-
return fs.promises.rename(source, target);
|
44
|
-
return fs.promises.copyFile(source, target);
|
45
|
-
};
|
46
|
-
await Promise.all(filePaths.map(async (rawfilePath) => {
|
47
|
-
const filePath = path.normalize(rawfilePath);
|
48
|
-
const replacedFilePath = filePath.replace(regex, replacement);
|
49
|
-
// 重命名文件
|
50
|
-
const oldFilePath = absin
|
51
|
-
? path.join(searchPath, filePath)
|
52
|
-
: filePath;
|
53
|
-
const newFilePath = absout
|
54
|
-
? path.join(outPath, replacedFilePath) //如果是绝对路径输出则拼接绝对路径
|
55
|
-
: replacedFilePath;
|
56
|
-
// 如果文件名发生了变化
|
57
|
-
if (newFilePath === oldFilePath)
|
58
|
-
return;
|
59
|
-
//如果文件已存在
|
60
|
-
if (await UtilFT.pathExists(newFilePath)) {
|
61
|
-
//如果是跳过或覆盖
|
62
|
-
if (DupMethodList.includes(options.duplicateHandling)) {
|
63
|
-
return match(duplicateHandling, {
|
64
|
-
'skip': () => SLogger.info(`重名文件存在,跳过:${newFilePath}`),
|
65
|
-
'overwrite': () => mapPath(oldFilePath, newFilePath),
|
66
|
-
});
|
67
|
-
}
|
68
|
-
//如果是转移位置
|
69
|
-
return mapPath(oldFilePath, path.join(outPath, duplicateHandling, replacedFilePath));
|
70
|
-
}
|
71
|
-
return mapPath(oldFilePath, newFilePath);
|
72
|
-
}));
|
73
|
-
});
|
package/dist/mjs/Command/Node.js
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
import { SLogger, UtilFunc } from '@zwa73/utils';
|
2
|
-
/**编译并运行某个文件 */
|
3
|
-
export const CmdNode = (program) => program
|
4
|
-
.command('Node <path|path[]>')
|
5
|
-
.alias('node')
|
6
|
-
.option('-p, --project <path>', 'tsconfig的目录')
|
7
|
-
.description('编译并运行某个文件')
|
8
|
-
.action(async (arg, opt) => {
|
9
|
-
SLogger.info(`编译并运行: ${arg}`);
|
10
|
-
let cmd = `ts-node -r tsconfig-paths/register ${arg}`;
|
11
|
-
if (opt.project)
|
12
|
-
cmd += ` -P ${opt.project}`;
|
13
|
-
await UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'error' });
|
14
|
-
});
|
@@ -1,90 +0,0 @@
|
|
1
|
-
import path from 'pathe';
|
2
|
-
import { memoize, SLogger, throwError, UtilFT, UtilFunc } from '@zwa73/utils';
|
3
|
-
import { checkProject, OFFICIAL_SOURCE, PROCESS_PATH } from './RouteInterface.js';
|
4
|
-
import fs from 'fs';
|
5
|
-
/**解析版本号为number数组 */
|
6
|
-
function parseVersion(version) {
|
7
|
-
const arr = version.split(".").map(Number);
|
8
|
-
if (arr.length !== 3)
|
9
|
-
throwError(`${version} 不是有效的版本号`, 'error');
|
10
|
-
for (let i = 0; i < 3; i++) {
|
11
|
-
if (!isFinite(arr[i]))
|
12
|
-
throwError(`${version} 不是有效的版本号`, 'error');
|
13
|
-
}
|
14
|
-
return arr;
|
15
|
-
}
|
16
|
-
/**判断版本号是否有效 */
|
17
|
-
function checkVersion(oldVersion, newVersion) {
|
18
|
-
const oldParts = parseVersion(oldVersion);
|
19
|
-
const newParts = parseVersion(newVersion);
|
20
|
-
for (let i = 0; i < 3; i++) {
|
21
|
-
if (newParts[i] < oldParts[i])
|
22
|
-
throwError(`${newVersion} 低于当前版本号 ${oldVersion}`, 'error');
|
23
|
-
if (newParts[i] > oldParts[i])
|
24
|
-
break;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
/**更新版本号 */
|
28
|
-
async function updateVersion(newVersion) {
|
29
|
-
const packagePath = path.join(PROCESS_PATH, "package.json");
|
30
|
-
const packageData = await memoize(UtilFT.loadJSONFile)(packagePath);
|
31
|
-
if (newVersion == 'current')
|
32
|
-
return packageData.version;
|
33
|
-
if (newVersion) {
|
34
|
-
checkVersion(packageData.version, newVersion);
|
35
|
-
packageData.version = newVersion;
|
36
|
-
}
|
37
|
-
else {
|
38
|
-
const version = packageData.version.split(".");
|
39
|
-
version[2] = (parseInt(version[2]) + 1).toString();
|
40
|
-
packageData.version = version.join(".");
|
41
|
-
}
|
42
|
-
await UtilFT.writeJSONFile(packagePath, packageData);
|
43
|
-
return packageData.version;
|
44
|
-
}
|
45
|
-
/**获取包名 */
|
46
|
-
async function getPackName() {
|
47
|
-
const packagePath = path.join(PROCESS_PATH, "package.json");
|
48
|
-
const packageData = await memoize(UtilFT.loadJSONFile)(packagePath);
|
49
|
-
return packageData.name
|
50
|
-
.replace(/\//g, '-')
|
51
|
-
.replace(/^@/g, '');
|
52
|
-
}
|
53
|
-
/**更新版本号并发布npm包 */
|
54
|
-
export const CmdRelease = (program) => program
|
55
|
-
.command("Release")
|
56
|
-
.alias("release")
|
57
|
-
.description("更新版本号并发布包")
|
58
|
-
.option("-v, --version <version>", "指定发布的版本号, 为 `current` 时不更新版本号, 格式应为 `${number}.${number}.${number}`")
|
59
|
-
.option("-a, --access <access>", "npm publish 的 access 参数 默认 public", "public")
|
60
|
-
.option("-l, --local <path>", "仅打包到本地对印目录下 如./build/", undefined)
|
61
|
-
.action(async (opt) => {
|
62
|
-
checkProject();
|
63
|
-
SLogger.info(`开始发布项目`);
|
64
|
-
try {
|
65
|
-
const newVersion = await updateVersion(opt.version);
|
66
|
-
SLogger.info(`新版本号: ${newVersion}`);
|
67
|
-
if (opt.local) {
|
68
|
-
SLogger.info("正在打包...");
|
69
|
-
const fullpath = path.join(process.cwd(), opt.local);
|
70
|
-
await UtilFT.ensurePathExists(fullpath, { dir: true });
|
71
|
-
await UtilFunc.exec(`npm pack`, { errlvl: 'info' });
|
72
|
-
const packageName = await getPackName();
|
73
|
-
const filelist = await fs.promises.readdir(process.cwd());
|
74
|
-
await Promise.all(filelist
|
75
|
-
.filter(p => new RegExp(packageName).test(p))
|
76
|
-
.map(async (p) => {
|
77
|
-
const packagePath = path.join(fullpath, p);
|
78
|
-
await fs.promises.rename(p, packagePath);
|
79
|
-
}));
|
80
|
-
return;
|
81
|
-
}
|
82
|
-
SLogger.info("正在发布...");
|
83
|
-
const cmd = `npm publish --registry ${OFFICIAL_SOURCE} --access ${opt.access}`;
|
84
|
-
await UtilFunc.exec(cmd, { errlvl: 'info' });
|
85
|
-
SLogger.info("发布完成");
|
86
|
-
}
|
87
|
-
catch (error) {
|
88
|
-
SLogger.error(error);
|
89
|
-
}
|
90
|
-
});
|
@@ -1 +0,0 @@
|
|
1
|
-
export declare function cliRoute(): Promise<void>;
|
@@ -1,20 +0,0 @@
|
|
1
|
-
import { program } from 'commander';
|
2
|
-
import { CmdNode } from './Node.js';
|
3
|
-
import { CmdRelease } from './Release.js';
|
4
|
-
import { CmdMapPath } from './MapPath.js';
|
5
|
-
import { CmdScanDups } from './ScanDups.js';
|
6
|
-
import { CmdGenSchema } from './GenSchema.js';
|
7
|
-
import { CmdExpandMacro } from './ExpandMacro.js';
|
8
|
-
import { CmdGenI18n } from './GenI18n.js';
|
9
|
-
import { CmdGenTemplate } from './GenTemplate.js';
|
10
|
-
export async function cliRoute() {
|
11
|
-
CmdNode(program);
|
12
|
-
CmdRelease(program);
|
13
|
-
CmdMapPath(program);
|
14
|
-
CmdScanDups(program);
|
15
|
-
CmdGenSchema(program);
|
16
|
-
CmdExpandMacro(program);
|
17
|
-
CmdGenI18n(program);
|
18
|
-
CmdGenTemplate(program);
|
19
|
-
program.parse(process.argv);
|
20
|
-
}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
/**npm镜像源 */
|
2
|
-
export declare const MIRROR_SOURCE = "https://registry.npmmirror.com/";
|
3
|
-
/**npm官方源 */
|
4
|
-
export declare const OFFICIAL_SOURCE = "https://registry.npmjs.org/";
|
5
|
-
/**根目录 */
|
6
|
-
export declare const ROOT_PATH: string;
|
7
|
-
/**data文件夹路径 */
|
8
|
-
export declare const DATA_PATH: string;
|
9
|
-
/**template文件夹路径 */
|
10
|
-
export declare const TEMPLATE_PATH: string;
|
11
|
-
/**当前路径 */
|
12
|
-
export declare const PROCESS_PATH: string;
|
13
|
-
/** 检测非浮点的整数类型 */
|
14
|
-
export declare function parseInteger(value: string): number;
|
15
|
-
/** 检测任意数字类型 */
|
16
|
-
export declare function parseNumber(value: string): number;
|
17
|
-
/** 检测布尔类型 */
|
18
|
-
export declare function parseBoolean(value: string): boolean;
|
19
|
-
/**在镜像源内镜像操作 */
|
20
|
-
export declare function withMirrorSource(func: (() => any)): Promise<void>;
|
21
|
-
/**在官方源内镜像操作 */
|
22
|
-
export declare function withOfficialSource(func: (() => any)): Promise<void>;
|
23
|
-
/**检查目录是否为项目 */
|
24
|
-
export declare function checkProject(): Promise<void>;
|
@@ -1,58 +0,0 @@
|
|
1
|
-
import path from 'pathe';
|
2
|
-
import { SLogger, throwError, UtilFT, UtilFunc } from '@zwa73/utils';
|
3
|
-
/**npm镜像源 */
|
4
|
-
export const MIRROR_SOURCE = "https://registry.npmmirror.com/";
|
5
|
-
/**npm官方源 */
|
6
|
-
export const OFFICIAL_SOURCE = "https://registry.npmjs.org/";
|
7
|
-
/**根目录 */
|
8
|
-
export const ROOT_PATH = path.join(`${process.platform === 'win32' ? '' : '/'}${/file:\/{2,3}(.+)\/[^/]/.exec(import.meta.url)[1]}`, '..', '..', '..');
|
9
|
-
/**data文件夹路径 */
|
10
|
-
export const DATA_PATH = path.join(ROOT_PATH, 'data');
|
11
|
-
/**template文件夹路径 */
|
12
|
-
export const TEMPLATE_PATH = path.join(DATA_PATH, 'template');
|
13
|
-
/**当前路径 */
|
14
|
-
export const PROCESS_PATH = process.cwd();
|
15
|
-
/** 检测非浮点的整数类型 */
|
16
|
-
export function parseInteger(value) {
|
17
|
-
const num = Number(value);
|
18
|
-
if (!(typeof num === 'number' && isFinite(num) && Math.floor(num) === num))
|
19
|
-
throwError(`${value} 不是有效的整数数字`);
|
20
|
-
return num;
|
21
|
-
}
|
22
|
-
/** 检测任意数字类型 */
|
23
|
-
export function parseNumber(value) {
|
24
|
-
const num = Number(value);
|
25
|
-
if (!(typeof value === 'number' && isFinite(value)))
|
26
|
-
throwError(`${value} 不是有效的数字`);
|
27
|
-
return num;
|
28
|
-
}
|
29
|
-
/** 检测布尔类型 */
|
30
|
-
export function parseBoolean(value) {
|
31
|
-
return value ? true : false;
|
32
|
-
}
|
33
|
-
/**在镜像源内镜像操作 */
|
34
|
-
export async function withMirrorSource(func) {
|
35
|
-
const out = await UtilFunc.exec('npm config get registry');
|
36
|
-
const OriginSource = out.stdout.trim(); //?
|
37
|
-
SLogger.info(`正在修改npm源为 镜像源: ${MIRROR_SOURCE}`);
|
38
|
-
await UtilFunc.exec(`npm config set registry ${MIRROR_SOURCE}`);
|
39
|
-
await func();
|
40
|
-
SLogger.info(`正在修改npm源为 原始源: ${OriginSource}`);
|
41
|
-
await UtilFunc.exec(`npm config set registry ${OriginSource}`);
|
42
|
-
}
|
43
|
-
/**在官方源内镜像操作 */
|
44
|
-
export async function withOfficialSource(func) {
|
45
|
-
const out = await UtilFunc.exec('npm config get registry');
|
46
|
-
const OriginSource = out.stdout.trim(); //?
|
47
|
-
SLogger.info(`正在修改npm源为 官方源: ${OFFICIAL_SOURCE}`);
|
48
|
-
await UtilFunc.exec(`npm config set registry ${OFFICIAL_SOURCE}`);
|
49
|
-
await func();
|
50
|
-
SLogger.info(`正在修改npm源为 原始源: ${OriginSource}`);
|
51
|
-
await UtilFunc.exec(`npm config set registry ${OriginSource}`);
|
52
|
-
}
|
53
|
-
/**检查目录是否为项目 */
|
54
|
-
export async function checkProject() {
|
55
|
-
const filePath = path.join(PROCESS_PATH, "package.json");
|
56
|
-
if (!(await UtilFT.pathExists(filePath)))
|
57
|
-
throwError(`当前目录: ${PROCESS_PATH} 不是npm项目目录, 请先使用 npm init`);
|
58
|
-
}
|
@@ -1,114 +0,0 @@
|
|
1
|
-
import { match, memoize, pipe, PromiseQueue, SLogger, Stream, UtilFP, UtilFT, UtilFunc } from "@zwa73/utils";
|
2
|
-
import path from "pathe";
|
3
|
-
import cliProgress from "cli-progress";
|
4
|
-
import fs from 'fs';
|
5
|
-
const { tap } = UtilFP;
|
6
|
-
/**hashlist转为dupmap */
|
7
|
-
const reduce2Dupmap = (list) => list.reduce((acc, cur) => {
|
8
|
-
const files = acc[cur.hash] ?? [];
|
9
|
-
acc[cur.hash] = [...files, cur.filePath]; // 分类采样哈希到对应文件路径
|
10
|
-
return acc;
|
11
|
-
}, {});
|
12
|
-
/**从dupmap提取重复的filepath */
|
13
|
-
const reduce2DupFpList = (map) => Object.entries(map).reduce((acc, [hash, files]) => files.length > 1 ? [...acc, ...files] : acc, // 筛选出重复采样哈希的文件路径
|
14
|
-
[]);
|
15
|
-
/**扫描文件结构 */
|
16
|
-
const scanDirStruct = memoize(async (root) => {
|
17
|
-
const list = await fs.promises.readdir(root, { withFileTypes: true });
|
18
|
-
const stack = await Promise.all(list.map(async (fp) => fp.isDirectory()
|
19
|
-
? [fp.name, await scanDirStruct(path.join(root, fp.name))]
|
20
|
-
: [fp.name, path.join(root, fp.name)]));
|
21
|
-
return stack.reduce((acc, cur) => ({
|
22
|
-
...acc, [cur[0]]: cur[1],
|
23
|
-
}), {});
|
24
|
-
});
|
25
|
-
const hashQueue = new PromiseQueue({ concurrency: 8 });
|
26
|
-
/**计算文件结构的hash */
|
27
|
-
async function struct2hash(struct, fn) {
|
28
|
-
const recursion = (struct) => {
|
29
|
-
return Object.entries(struct).map(async ([k, v]) => {
|
30
|
-
if (typeof v === "string")
|
31
|
-
return [await hashQueue.enqueue(async () => fn(v))];
|
32
|
-
return (await Promise.all(recursion(v))).flat();
|
33
|
-
});
|
34
|
-
};
|
35
|
-
return UtilFunc.calcHash((await Promise.all(recursion(struct)))
|
36
|
-
.flat().join('|'), { algorithm: "blake2b512" });
|
37
|
-
}
|
38
|
-
/**重命名文件或路径 scan_duplicates */
|
39
|
-
export const CmdScanDups = (program) => program
|
40
|
-
.command("Scan-Dups")
|
41
|
-
.alias("scandups")
|
42
|
-
.description("扫描当前目录下hash重复的文件")
|
43
|
-
.option("-i, --include <regex>", "文件的正则表达式, 使用posix路径", ".*")
|
44
|
-
.option("-o, --out <dir|console>", "输出的json文件路径, 默认 scandups.json, 为 \"console\" 时无文件输出", "scandups")
|
45
|
-
.option("-r, --recursive", "是否处理子目录, 默认 true", true)
|
46
|
-
.option("-s, --struct", `结构模式
|
47
|
-
只扫描 -i 参数目录下的单层目录, 并计算目录是否出现相同的层次结构
|
48
|
-
默认 false`, true)
|
49
|
-
.option("-d, --dir <dirs...>", `扫描的根目录, 以空格分隔 -d "a/b c" "d e/f", 默认为命令行当前目录`, [])
|
50
|
-
.action(async (options) => {
|
51
|
-
const { out: outtype, recursive, include, struct, dir } = options;
|
52
|
-
const regex = new RegExp(include);
|
53
|
-
const basePath = process.cwd();
|
54
|
-
const pathList = dir.length <= 0
|
55
|
-
? [process.cwd()]
|
56
|
-
: dir.map(d => path.isAbsolute(d) ? d : path.join(process.cwd(), d));
|
57
|
-
// 添加一个多步进度条
|
58
|
-
const progressBar = new cliProgress.MultiBar({
|
59
|
-
clearOnComplete: true, hideCursor: true,
|
60
|
-
format: " {task} [{bar}] {percentage}% | ETA: {eta}s | {value}/{total} | {status}",
|
61
|
-
}, cliProgress.Presets.shades_classic);
|
62
|
-
// 文件结构进度条
|
63
|
-
const structProgress = struct ? progressBar.create(1, 0, { task: "结构扫描", status: "准备中..." }) : undefined;
|
64
|
-
// 采样哈希进度条
|
65
|
-
const sampledProgress = progressBar.create(1, 0, { task: "快速扫描", status: "准备中..." });
|
66
|
-
// 完整哈希进度条
|
67
|
-
const fullHashProgress = progressBar.create(1, 0, { task: "完整扫描", status: "准备中..." });
|
68
|
-
await pipe(
|
69
|
-
// 第一步:文件搜索,获取符合正则的文件路径
|
70
|
-
Promise.all(pathList.map(async (p) => {
|
71
|
-
if (struct)
|
72
|
-
return (await fs.promises.readdir(p, { withFileTypes: true }))
|
73
|
-
.filter(fp => fp.isDirectory())
|
74
|
-
.map(fp => path.join(p, fp.name));
|
75
|
-
return await UtilFT.fileSearchRegex(p, regex.source, { recursive });
|
76
|
-
})), stacklist => stacklist.flat(), // 扁平化文件路径列表
|
77
|
-
// 如果是结构模式则先筛选相同结构
|
78
|
-
// 扁平化文件路径列表
|
79
|
-
list => struct ? pipe(list, tap(dupFpList => (structProgress.setTotal(dupFpList.length),
|
80
|
-
structProgress.update(0, { status: `结构扫描检出 ${dupFpList.length} 个可能的相等项` }))), list => Stream.from(list, 8)
|
81
|
-
.map(async (filePath) => ({
|
82
|
-
filePath,
|
83
|
-
hash: await struct2hash(await scanDirStruct(filePath), cpath => path.relative(filePath, cpath)).then(tap(() => structProgress.increment()))
|
84
|
-
}))
|
85
|
-
.toArray(), reduce2Dupmap, reduce2DupFpList) : list,
|
86
|
-
// 第二步:快速扫描,计算采样哈希
|
87
|
-
tap(list => (sampledProgress.setTotal(list.length),
|
88
|
-
sampledProgress.update(0, { status: `总计 ${list.length} 个文件` }))), list => Stream.from(list, 8)
|
89
|
-
.map(async (filePath) => ({
|
90
|
-
filePath,
|
91
|
-
hash: struct
|
92
|
-
? await struct2hash(await scanDirStruct(filePath), (str) => UtilFT.calculateHash(str, { sampled: true })).then(tap(() => sampledProgress.increment()))
|
93
|
-
: await UtilFT.calculateHash(filePath, { sampled: true }).then(tap(() => sampledProgress.increment())),
|
94
|
-
}))
|
95
|
-
.toArray(),
|
96
|
-
// 第三步:筛选重复的采样哈希 (去掉唯一的采样哈希)
|
97
|
-
reduce2Dupmap, reduce2DupFpList,
|
98
|
-
// 第四步:对筛选出的重复文件路径并发计算完整哈希
|
99
|
-
tap(dupFpList => (fullHashProgress.setTotal(dupFpList.length),
|
100
|
-
fullHashProgress.update(0, { status: `快速扫描检出 ${dupFpList.length} 个可能的相等项` }))), dupFpList => Stream.from(dupFpList, 8)
|
101
|
-
.map(async (filePath) => ({
|
102
|
-
filePath,
|
103
|
-
hash: struct
|
104
|
-
? await struct2hash(await scanDirStruct(filePath), (str) => UtilFT.calculateHash(str)).then(tap(() => sampledProgress.increment()))
|
105
|
-
: await UtilFT.calculateHash(filePath).then(tap(() => fullHashProgress.increment())), // 计算完整哈希
|
106
|
-
}))
|
107
|
-
.toArray(),
|
108
|
-
// 第五步:重新整理完整哈希结果, 过滤唯一哈希
|
109
|
-
reduce2Dupmap, map => Object.entries(map).reduce((acc, [hash, files]) => files.length <= 1 ? acc : { ...acc, [hash]: files }, {}),
|
110
|
-
// 第六步:输出结果
|
111
|
-
tap(() => progressBar.stop()), out => match(outtype, {
|
112
|
-
"console": () => SLogger.info(out),
|
113
|
-
}, () => UtilFT.writeJSONFile(path.join(basePath, outtype), out)));
|
114
|
-
});
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Route.js';
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Route.js';
|
package/dist/mjs/QuickFunc.d.ts
DELETED