@zwa73/dev-utils 1.0.89 → 1.0.90

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.
Files changed (37) hide show
  1. package/bin/cli +1 -1
  2. package/data/template/base/package.json +1 -0
  3. package/data/template/base/scripts/compile.ps1 +25 -25
  4. package/data/template/base/scripts/release.ps1 +5 -2
  5. package/data/template/base/tsup.config.js +35 -0
  6. package/data/template/cjs/scripts/compile.ps1 +9 -2
  7. package/data/template/cjs/scripts/release.ps1 +5 -1
  8. package/dist/Command/Bump.d.ts +6 -0
  9. package/dist/Command/Bump.js +70 -0
  10. package/dist/Command/CheckToken.d.ts +10 -0
  11. package/dist/Command/CheckToken.js +52 -0
  12. package/dist/Command/ExpandMacro.d.ts +1 -1
  13. package/dist/Command/GenI18n.d.ts +1 -1
  14. package/dist/Command/GenI18n.js +6 -2
  15. package/dist/Command/GenSchema.d.ts +1 -1
  16. package/dist/Command/GenTemplate.d.ts +1 -1
  17. package/dist/Command/GenTemplate.js +2 -2
  18. package/dist/Command/MapPath.d.ts +1 -1
  19. package/dist/Command/MapPath.js +66 -31
  20. package/dist/Command/Node.d.ts +1 -1
  21. package/dist/Command/Node.js +1 -1
  22. package/dist/Command/Release.d.ts +1 -1
  23. package/dist/Command/Release.js +9 -45
  24. package/dist/Command/Route.js +7 -5
  25. package/dist/Command/RouteInterface.js +1 -1
  26. package/dist/Command/ScanDups.d.ts +1 -1
  27. package/dist/Command/ScanDups.js +11 -10
  28. package/dist/DynImport.d.ts +6 -6
  29. package/dist/UtilAst.d.ts +1 -1
  30. package/dist/UtilDevTool.d.ts +1 -1
  31. package/dist/UtilDevTool.js +8 -4
  32. package/dist/UtilMacro.d.ts +1 -1
  33. package/dist/UtilMacro.js +3 -3
  34. package/package.json +1 -3
  35. package/data/template/base/tsconfig.cjs.json +0 -9
  36. package/data/template/base/tsconfig.mjs.json +0 -9
  37. package/data/template/base/tsconfig.types.json +0 -8
package/bin/cli CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const {cliRoute} = require('../dist/index.js');
4
4
 
@@ -2,6 +2,7 @@
2
2
  "name": "<%= projectName %>",
3
3
  "version": "1.0.0",
4
4
  "description": "<%= projectDescription %>",
5
+ "types": "./dist/types/index.d.ts",
5
6
  "exports": {
6
7
  ".": {
7
8
  "require": "./dist/cjs/index.js",
@@ -1,25 +1,25 @@
1
- npm run expand-macro
2
- Write-Output 开始删除原dist
3
- Remove-Item -Recurse -Force dist
4
- Write-Output 开始编译
5
-
6
- $CurrentDir = Get-Location
7
-
8
- Start-Job -Name "JobCjs" -ScriptBlock {
9
- Set-Location $using:CurrentDir
10
- tsc -p tsconfig.cjs.json
11
- tsc-alias -p tsconfig.cjs.json
12
- }
13
- Start-Job -Name "JobMjs" -ScriptBlock {
14
- Set-Location $using:CurrentDir
15
- tsc -p tsconfig.mjs.json
16
- tsc-alias -p tsconfig.mjs.json
17
- tsc-esm-fix --tsconfig "./tsconfig.mjs.json" --ext ".mjs"
18
- }
19
- Start-Job -Name "JobTypes" -ScriptBlock {
20
- Set-Location $using:CurrentDir
21
- tsc -p tsconfig.types.json
22
- tsc-alias -p tsconfig.types.json
23
- }
24
- Wait-Job -State Running
25
- Get-Job | Receive-Job
1
+ # compiletsupv1.0.0
2
+ if (Test-Path dist) {
3
+ Write-Output "开始删除原dist"
4
+ Remove-Item -Recurse -Force dist
5
+ }
6
+ Write-Output "开始类型检查..."
7
+ # 用 tsc 做类型检查
8
+ # tsc -p tsconfig.compile.json
9
+ tsc -p tsconfig.compile.json --noEmit
10
+ if ($LASTEXITCODE -ne 0) {
11
+ Write-Error "类型检查失败, 停止编译"
12
+ exit $LASTEXITCODE
13
+ }
14
+
15
+ Write-Output "类型检查通过, 开始 tsup 编译..."
16
+
17
+ # 执行 tsup
18
+ $tsupOutput = tsup --silent 2>&1
19
+ if ($LASTEXITCODE -ne 0) {
20
+ Write-Error "tsup 编译失败"
21
+ Write-Output $tsupOutput # 只在失败时打印 tsup 的输出
22
+ exit $LASTEXITCODE
23
+ }
24
+
25
+ Write-Output "编译完成"
@@ -1,4 +1,7 @@
1
- Write-Output 开始编译
2
- npm run compile
1
+ npm run compile
2
+ if ($LASTEXITCODE -ne 0) {
3
+ Write-Error "编译失败, 停止发布"
4
+ exit $LASTEXITCODE
5
+ }
3
6
  Write-Output 开始发布
4
7
  npx zcli release
@@ -0,0 +1,35 @@
1
+ const { defineConfig } = require("tsup");
2
+
3
+ const common = {
4
+ entry: [
5
+ "src/**/*.ts",
6
+ "!**/test/**",
7
+ "!src/**/*.macro.ts",
8
+ ],
9
+ tsconfig: 'tsconfig.compile.json',
10
+ clean: false,
11
+ dts: false,
12
+ external: []
13
+ }
14
+ export default defineConfig([
15
+ // CommonJS 输出
16
+ {
17
+ ...common,
18
+ format: ["cjs"],
19
+ outDir: "dist/cjs",
20
+ target: "es2022",
21
+ },
22
+ // ESM 输出
23
+ {
24
+ ...common,
25
+ format: ["esm"],
26
+ outDir: "dist/mjs",
27
+ target: "esnext",
28
+ },
29
+ {
30
+ ...common,
31
+ name: "types",
32
+ dts: { only: true },
33
+ outDir: "dist/types",
34
+ }
35
+ ]);
@@ -1,6 +1,13 @@
1
1
  npm run expand-macro
2
- Write-Output 开始删除原dist
3
- Remove-Item -Recurse -Force dist
2
+ # compile v1.0.0
3
+ if (Test-Path dist) {
4
+ Write-Output "开始删除原dist"
5
+ Remove-Item -Recurse -Force dist
6
+ }
4
7
  Write-Output 开始编译
5
8
  tsc -p tsconfig.compile.json
9
+ if ($LASTEXITCODE -ne 0) {
10
+ Write-Error "tsc 编译失败"
11
+ exit $LASTEXITCODE
12
+ }
6
13
  tsc-alias -p tsconfig.compile.json
@@ -1,4 +1,8 @@
1
- Write-Output 开始编译
1
+ # releasev1.0.0
2
2
  npm run compile
3
+ if ($LASTEXITCODE -ne 0) {
4
+ Write-Error "编译失败, 停止发布"
5
+ exit $LASTEXITCODE
6
+ }
3
7
  Write-Output 开始发布
4
8
  npx zcli release
@@ -0,0 +1,6 @@
1
+ import type { Command } from 'commander';
2
+ export declare const bump: (opt: {
3
+ version?: string;
4
+ }) => Promise<void>;
5
+ /**更新版本号 */
6
+ export declare const CmdBump: (program: Command) => Command;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CmdBump = exports.bump = void 0;
7
+ const utils_1 = require("@zwa73/utils");
8
+ const pathe_1 = __importDefault(require("pathe"));
9
+ const RouteInterface_1 = require("./RouteInterface");
10
+ /**解析版本号为number数组 */
11
+ function parseVersion(version) {
12
+ const arr = version.split(".").map(Number);
13
+ if (arr.length !== 3)
14
+ (0, utils_1.throwError)(`${version} 不是有效的版本号`, 'error');
15
+ for (let i = 0; i < 3; i++) {
16
+ if (!isFinite(arr[i]))
17
+ (0, utils_1.throwError)(`${version} 不是有效的版本号`, 'error');
18
+ }
19
+ return arr;
20
+ }
21
+ /**判断版本号是否有效 */
22
+ function checkVersion(oldVersion, newVersion) {
23
+ const oldParts = parseVersion(oldVersion);
24
+ const newParts = parseVersion(newVersion);
25
+ for (let i = 0; i < 3; i++) {
26
+ if (newParts[i] < oldParts[i])
27
+ (0, utils_1.throwError)(`${newVersion} 低于当前版本号 ${oldVersion}`, 'error');
28
+ if (newParts[i] > oldParts[i])
29
+ break;
30
+ }
31
+ }
32
+ /**更新版本号 */
33
+ async function updateVersion(newVersion) {
34
+ const packagePath = pathe_1.default.join(RouteInterface_1.PROCESS_PATH, "package.json");
35
+ const packageData = await (0, utils_1.memoize)(utils_1.UtilFT.loadJSONFile)(packagePath);
36
+ if (newVersion == 'current')
37
+ return packageData.version;
38
+ if (newVersion) {
39
+ checkVersion(packageData.version, newVersion);
40
+ packageData.version = newVersion;
41
+ }
42
+ else {
43
+ const version = packageData.version.split(".");
44
+ version[2] = (parseInt(version[2]) + 1).toString();
45
+ packageData.version = version.join(".");
46
+ }
47
+ await utils_1.UtilFT.writeJSONFile(packagePath, packageData);
48
+ return packageData.version;
49
+ }
50
+ const bump = async (opt) => {
51
+ await (0, RouteInterface_1.checkProject)();
52
+ utils_1.SLogger.info(`开始更新版本号`);
53
+ try {
54
+ const newVersion = await updateVersion(opt.version);
55
+ utils_1.SLogger.info(`新版本号: ${newVersion}`);
56
+ }
57
+ catch (error) {
58
+ utils_1.SLogger.error(error);
59
+ throw error;
60
+ }
61
+ };
62
+ exports.bump = bump;
63
+ /**更新版本号 */
64
+ const CmdBump = (program) => program
65
+ .command("bump")
66
+ .alias("version")
67
+ .description("更新项目版本号")
68
+ .option("-v, --version <version>", "指定版本号, 为 `current` 时不更新版本号, 格式应为 `${number}.${number}.${number}`")
69
+ .action(exports.bump);
70
+ exports.CmdBump = CmdBump;
@@ -0,0 +1,10 @@
1
+ import type { LogLevel } from "@zwa73/utils";
2
+ import type { Command } from "commander";
3
+ /**检查npm token过期 */
4
+ export declare function checkNpmToken(opt?: {
5
+ logstd?: boolean;
6
+ threshold?: number;
7
+ loglvl?: LogLevel | 'none' | ((v: string) => void);
8
+ }): Promise<string | undefined>;
9
+ /**更新版本号并发布npm包 */
10
+ export declare const CmdCheckToken: (program: Command) => Command;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CmdCheckToken = void 0;
4
+ exports.checkNpmToken = checkNpmToken;
5
+ const utils_1 = require("@zwa73/utils");
6
+ /**检查npm token过期 */
7
+ async function checkNpmToken(opt) {
8
+ const { logstd = false, threshold = 15, loglvl = 'warn', } = opt ?? {};
9
+ try {
10
+ const { stderr, stdout } = await utils_1.UtilFunc.exec('npm token list', {
11
+ outlvl: logstd ? console.log : undefined
12
+ });
13
+ // 正则:
14
+ //Publish token npm_a0… with id 616dfb created 2025-12-05
15
+ //with IP whitelist:
16
+ // [1] 前缀 npm_xxx [2] id [3] 创建日期 yyyy-mm-dd
17
+ const re = /token\s+(npm_[^\s]+).*?id\s+([a-z0-9]+).*?created\s+(\d{4}-\d{2}-\d{2})/gi;
18
+ const now = new Date();
19
+ const msg = [];
20
+ for (const m of stdout.matchAll(re)) {
21
+ const [, prefix, id, created] = m;
22
+ const createdDate = new Date(created);
23
+ // 默认 Granular Token 有效期 90 天;Classic 看起来“Never”,可按需特殊处理
24
+ const expiresDate = new Date(createdDate.getTime() + 90 * 24 * 60 * 60 * 1000);
25
+ const daysLeft = Math.floor((expiresDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
26
+ if (daysLeft <= threshold)
27
+ msg.push(`⚠️ Token ${prefix} with id ${id} 即将过期, 剩余 ${daysLeft} 天, 过期 ${expiresDate.toISOString().slice(0, 10)}`);
28
+ }
29
+ const msgText = msg.join('\n');
30
+ if (msgText.length > 0) {
31
+ if (typeof loglvl == 'string' && loglvl !== 'none')
32
+ utils_1.SLogger.log(loglvl, msgText);
33
+ else if (typeof loglvl == 'function')
34
+ loglvl(msgText);
35
+ return msgText;
36
+ }
37
+ return undefined;
38
+ }
39
+ catch (e) {
40
+ utils_1.SLogger.error('checkNpmToken 错误', e);
41
+ return undefined;
42
+ }
43
+ }
44
+ /**更新版本号并发布npm包 */
45
+ const CmdCheckToken = (program) => program
46
+ .command("Check-Token")
47
+ .alias("checktoken")
48
+ .description("检查npm token是否即将过期")
49
+ .action(async () => {
50
+ await checkNpmToken({ logstd: true });
51
+ });
52
+ exports.CmdCheckToken = CmdCheckToken;
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**构造macro */
3
3
  export declare const CmdExpandMacro: (program: Command) => Command;
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**生成i18n */
3
3
  export declare const CmdGenI18n: (program: Command) => Command;
@@ -5,14 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CmdGenI18n = void 0;
7
7
  const utils_1 = require("@zwa73/utils");
8
- const UtilAst_1 = require("../UtilAst");
9
8
  const pathe_1 = __importDefault(require("pathe"));
10
9
  const DynImport_1 = require("../DynImport");
10
+ const UtilAst_1 = require("../UtilAst");
11
11
  function format(str) {
12
12
  return str.replace(/\\(.)/g, '$1').replace(/%/g, '\\%');
13
13
  }
14
14
  async function procFile(p, filePath, funckey) {
15
15
  const TsMorph = await (0, DynImport_1.importTsMorph)();
16
+ if (!TsMorph)
17
+ (0, utils_1.throwError)(`ts-morph 未安装`);
16
18
  const { SyntaxKind } = TsMorph;
17
19
  const date = new Date().toISOString();
18
20
  //const content = await fs.promises.readFile(filePath,'utf-8');
@@ -60,6 +62,8 @@ async function procFile(p, filePath, funckey) {
60
62
  }
61
63
  async function scanI18n(i18nDataDir, include, exclude, funckey) {
62
64
  const TsMorph = await (0, DynImport_1.importTsMorph)();
65
+ if (!TsMorph)
66
+ (0, utils_1.throwError)(`ts-morph 未安装`);
63
67
  const { Project } = TsMorph;
64
68
  const fixedKey = typeof funckey == 'string' ? [funckey] : funckey;
65
69
  const filePaths = (await utils_1.UtilFT.fileSearchGlob(process.cwd(), include, { ingore: exclude }))
@@ -67,7 +71,7 @@ async function scanI18n(i18nDataDir, include, exclude, funckey) {
67
71
  const project = new Project();
68
72
  await utils_1.SI18n.init(i18nDataDir, '*');
69
73
  //console.log(filePaths);
70
- (await Promise.all(filePaths.map(p => procFile(project, p, fixedKey))))
74
+ (await Promise.all(filePaths.map(async (p) => procFile(project, p, fixedKey))))
71
75
  .flat().forEach(dat => utils_1.SI18n.addOriginalText(dat));
72
76
  await utils_1.SI18n.saveTable();
73
77
  }
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**生成schema */
3
3
  export declare const CmdGenSchema: (program: Command) => Command;
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**生成schema */
3
3
  export declare const CmdGenTemplate: (program: Command) => Command;
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CmdGenTemplate = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const utils_1 = require("@zwa73/utils");
7
9
  const pathe_1 = __importDefault(require("pathe"));
8
10
  const RouteInterface_1 = require("./RouteInterface");
9
- const utils_1 = require("@zwa73/utils");
10
- const fs_1 = __importDefault(require("fs"));
11
11
  /**复制基础文件 */
12
12
  async function copyData(templatePath, projectPath) {
13
13
  const filelist = await fs_1.default.promises.readdir(templatePath);
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**重命名文件或路径 */
3
3
  export declare const CmdMapPath: (program: Command) => Command;
@@ -4,39 +4,58 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CmdMapPath = void 0;
7
- const utils_1 = require("@zwa73/utils");
8
7
  const fs_1 = __importDefault(require("fs"));
8
+ const utils_1 = require("@zwa73/utils");
9
9
  const pathe_1 = __importDefault(require("pathe"));
10
- const DupMethodList = ["skip", "overwrite"];
10
+ const DupMethodList = ["skip", "overwrite", "rename"];
11
11
  /**重命名文件或路径 */
12
12
  const CmdMapPath = (program) => program
13
13
  .command("Map-Path")
14
14
  .alias("mappath")
15
- .description("根据正则表达式对文件名进行映射")
15
+ .description(`根据正则表达式对文件名进行映射`)
16
16
  .argument("<regex>", "要匹配的正则表达式, posix风格路径")
17
17
  .argument("<replacement>", "替换字符串")
18
18
  .option("-e, --exclude <regex>", "排除文件的正则表达式")
19
- .option(`-d, --duplicate-handling <${DupMethodList.join('|')}|[path:string]>`, `处理重名文件的方式:
19
+ .option(`-d, --duplicate-handling <${DupMethodList.join('|')}>`, `处理重名文件的方式:
20
20
  skip 不进行处理
21
21
  overwrite 覆盖重名
22
- 其他字符串 将重名部分映射到指定目录下的对应位置, 再次重复将会覆盖`, "skip")
23
- .option("-r, --recursive", "是否处理子目录", false)
22
+ rename [name]_idx[.ext?] 的形式重命名`, "skip")
23
+ .option("-r, --recursive", "递归的处理子目录", false)
24
24
  .option("-m, --move", "重命名而不是复制文件", false)
25
25
  .option("-o, --output <path>", "输出到某个绝对路径而非当前目录", '')
26
26
  .option("-i, --input <path>", "扫描某个绝对路径而非当前目录", '')
27
27
  .option("-t, --test", "不对文件进行实际操作, 在控制台输出映射结果", false)
28
+ .option("-@, --extend", `使用@占位符扩展语法, 可用占位符:
29
+ @i 表示处理顺序下标 (从0开始)
30
+ @c 表示处理计数 (从1开始)
31
+ @name 表示文件名 (不含扩展名)
32
+ @ext 表示文件扩展名 (带.)
33
+ @base 表示文件名 (含扩展名)
34
+ @dir 表示文件所在目录的路径
35
+ @path[n] 获取路径中的第 n 段 (从 0 开始, 负数表示倒数)
36
+ @@ 表示对@的转义
37
+ exmaple:
38
+ match: "/data/archive/project/file.txt"
39
+ @name -> "file"
40
+ @ext -> ".txt"
41
+ @base -> "file.txt"
42
+ @dir -> "/data/archive/project"
43
+ @path[0] -> "data"
44
+ @path[-1] -> "file.txt"
45
+ @path[-2] -> "project"
46
+ `, false)
28
47
  .action(async (regexStr, replacement, options) => {
29
48
  const regex = new RegExp(regexStr);
30
49
  const excludeRegex = options.exclude ? new RegExp(options.exclude) : null;
31
50
  if (!DupMethodList.includes(options.duplicateHandling))
32
51
  (0, utils_1.throwError)(`${options.duplicateHandling} 不是有效的 duplicate-handling`);
33
52
  const duplicateHandling = options.duplicateHandling;
34
- const absout = options.output.length > 0;
35
- const absin = options.input.length > 0;
36
- const searchPath = absin ? options.input : process.cwd();
37
- const outPath = absout ? options.output : process.cwd();
53
+ const searchPath = options.input.length > 0
54
+ ? options.input : process.cwd();
55
+ const outPath = options.output.length > 0
56
+ ? options.output : process.cwd();
38
57
  // 遍历当前目录下的所有文件
39
- const filePaths = (await utils_1.UtilFT.fileSearchRegex(searchPath, regex, { relative: options.recursive }))
58
+ const filePaths = (await utils_1.UtilFT.fileSearchRegex(searchPath, regex, { recursive: options.recursive }))
40
59
  .map(fp => pathe_1.default.relative(searchPath, fp))
41
60
  .filter(fp => excludeRegex ? (!excludeRegex.test(fp)) : true);
42
61
  //对单个路径映射
@@ -49,31 +68,47 @@ overwrite 覆盖重名
49
68
  return fs_1.default.promises.rename(source, target);
50
69
  return fs_1.default.promises.copyFile(source, target);
51
70
  };
52
- await Promise.all(filePaths.map(async (rawfilePath) => {
71
+ // 先生成带编号的文件映射
72
+ const indexedFiles = filePaths.map((rawfilePath, idx) => {
53
73
  const filePath = pathe_1.default.normalize(rawfilePath);
54
- const replacedFilePath = filePath.replace(regex, replacement);
55
- // 重命名文件
56
- const oldFilePath = absin
57
- ? pathe_1.default.join(searchPath, filePath)
58
- : filePath;
59
- const newFilePath = absout
60
- ? pathe_1.default.join(outPath, replacedFilePath) //如果是绝对路径输出则拼接绝对路径
74
+ const segments = filePath.split(pathe_1.default.sep).filter(Boolean); // 提取路径片段
75
+ const replacedFilePath = filePath
76
+ .replace(regex, replacement); //替换
77
+ const processedFilePath = options.extend
78
+ ? replacedFilePath
79
+ .replace(/(?<!@)@name/g, pathe_1.default.parse(filePath).name)
80
+ .replace(/(?<!@)@ext/g, pathe_1.default.parse(filePath).ext)
81
+ .replace(/(?<!@)@base/g, pathe_1.default.parse(filePath).base)
82
+ .replace(/(?<!@)@dir/g, pathe_1.default.dirname(filePath))
83
+ .replace(/(?<!@)@i/g, `${idx}`) //数字下标
84
+ .replace(/(?<!@)@c/g, `${idx + 1}`)
85
+ .replace(/(?<!@)@path\[(\-?\d+)\]/g, (_, rawIndex) => {
86
+ const index = Number(rawIndex);
87
+ const resolved = index < 0
88
+ ? segments[segments.length + index]
89
+ : segments[index];
90
+ return resolved ?? '';
91
+ })
92
+ .replace(/@@/g, `@`) //转义
61
93
  : replacedFilePath;
62
- // 如果文件名发生了变化
94
+ return {
95
+ idx,
96
+ oldFilePath: pathe_1.default.join(searchPath, filePath),
97
+ newFilePath: pathe_1.default.join(outPath, processedFilePath),
98
+ };
99
+ });
100
+ await Promise.all(indexedFiles.map(async ({ idx, oldFilePath, newFilePath, }) => {
101
+ // 如果文件名无变化则不操作
63
102
  if (newFilePath === oldFilePath)
64
103
  return;
65
104
  //如果文件已存在
66
- if (await utils_1.UtilFT.pathExists(newFilePath)) {
67
- //如果是跳过或覆盖
68
- if (DupMethodList.includes(options.duplicateHandling)) {
69
- return (0, utils_1.match)(duplicateHandling, {
70
- 'skip': () => utils_1.SLogger.info(`重名文件存在,跳过:${newFilePath}`),
71
- 'overwrite': () => mapPath(oldFilePath, newFilePath),
72
- });
73
- }
74
- //如果是转移位置
75
- return mapPath(oldFilePath, pathe_1.default.join(outPath, duplicateHandling, replacedFilePath));
76
- }
105
+ if (await utils_1.UtilFT.pathExists(newFilePath))
106
+ return (0, utils_1.match)(duplicateHandling, {
107
+ 'skip': () => utils_1.SLogger.info(`重名文件存在,跳过:${newFilePath}`),
108
+ 'overwrite': async () => mapPath(oldFilePath, newFilePath),
109
+ 'rename': async () => mapPath(oldFilePath, newFilePath.replace(/((\.[^/.]+)?$)/, `_${idx}$1`)),
110
+ });
111
+ //如果文件不存在, 直接映射
77
112
  return mapPath(oldFilePath, newFilePath);
78
113
  }));
79
114
  });
@@ -1,3 +1,3 @@
1
- import { Command } from 'commander';
1
+ import type { Command } from 'commander';
2
2
  /**编译并运行某个文件 */
3
3
  export declare const CmdNode: (program: Command) => Command;
@@ -13,6 +13,6 @@ const CmdNode = (program) => program
13
13
  let cmd = `ts-node -r tsconfig-paths/register ${arg}`;
14
14
  if (opt.project)
15
15
  cmd += ` -P ${opt.project}`;
16
- await utils_1.UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'error' });
16
+ await utils_1.UtilFunc.exec(cmd, { outlvl: console.info, errlvl: console.error });
17
17
  });
18
18
  exports.CmdNode = CmdNode;
@@ -1,3 +1,3 @@
1
- import { Command } from 'commander';
1
+ import type { Command } from 'commander';
2
2
  /**更新版本号并发布npm包 */
3
3
  export declare const CmdRelease: (program: Command) => Command;
@@ -4,50 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CmdRelease = void 0;
7
- const pathe_1 = __importDefault(require("pathe"));
7
+ const fs_1 = __importDefault(require("fs"));
8
8
  const utils_1 = require("@zwa73/utils");
9
+ const pathe_1 = __importDefault(require("pathe"));
10
+ const Bump_1 = require("./Bump");
11
+ const CheckToken_1 = require("./CheckToken");
9
12
  const RouteInterface_1 = require("./RouteInterface");
10
- const fs_1 = __importDefault(require("fs"));
11
- /**解析版本号为number数组 */
12
- function parseVersion(version) {
13
- const arr = version.split(".").map(Number);
14
- if (arr.length !== 3)
15
- (0, utils_1.throwError)(`${version} 不是有效的版本号`, 'error');
16
- for (let i = 0; i < 3; i++) {
17
- if (!isFinite(arr[i]))
18
- (0, utils_1.throwError)(`${version} 不是有效的版本号`, 'error');
19
- }
20
- return arr;
21
- }
22
- /**判断版本号是否有效 */
23
- function checkVersion(oldVersion, newVersion) {
24
- const oldParts = parseVersion(oldVersion);
25
- const newParts = parseVersion(newVersion);
26
- for (let i = 0; i < 3; i++) {
27
- if (newParts[i] < oldParts[i])
28
- (0, utils_1.throwError)(`${newVersion} 低于当前版本号 ${oldVersion}`, 'error');
29
- if (newParts[i] > oldParts[i])
30
- break;
31
- }
32
- }
33
- /**更新版本号 */
34
- async function updateVersion(newVersion) {
35
- const packagePath = pathe_1.default.join(RouteInterface_1.PROCESS_PATH, "package.json");
36
- const packageData = await (0, utils_1.memoize)(utils_1.UtilFT.loadJSONFile)(packagePath);
37
- if (newVersion == 'current')
38
- return packageData.version;
39
- if (newVersion) {
40
- checkVersion(packageData.version, newVersion);
41
- packageData.version = newVersion;
42
- }
43
- else {
44
- const version = packageData.version.split(".");
45
- version[2] = (parseInt(version[2]) + 1).toString();
46
- packageData.version = version.join(".");
47
- }
48
- await utils_1.UtilFT.writeJSONFile(packagePath, packageData);
49
- return packageData.version;
50
- }
51
13
  /**获取包名 */
52
14
  async function getPackName() {
53
15
  const packagePath = pathe_1.default.join(RouteInterface_1.PROCESS_PATH, "package.json");
@@ -65,11 +27,10 @@ const CmdRelease = (program) => program
65
27
  .option("-a, --access <access>", "npm publish 的 access 参数 默认 public", "public")
66
28
  .option("-l, --local <path>", "仅打包到本地对印目录下 如./build/", undefined)
67
29
  .action(async (opt) => {
68
- (0, RouteInterface_1.checkProject)();
30
+ await (0, Bump_1.bump)(opt);
69
31
  utils_1.SLogger.info(`开始发布项目`);
70
32
  try {
71
- const newVersion = await updateVersion(opt.version);
72
- utils_1.SLogger.info(`新版本号: ${newVersion}`);
33
+ const chkPromise = (0, CheckToken_1.checkNpmToken)({ loglvl: 'none' });
73
34
  if (opt.local) {
74
35
  utils_1.SLogger.info("正在打包...");
75
36
  const fullpath = pathe_1.default.join(process.cwd(), opt.local);
@@ -89,6 +50,9 @@ const CmdRelease = (program) => program
89
50
  const cmd = `npm publish --registry ${RouteInterface_1.OFFICIAL_SOURCE} --access ${opt.access}`;
90
51
  await utils_1.UtilFunc.exec(cmd, { errlvl: 'info' });
91
52
  utils_1.SLogger.info("发布完成");
53
+ const chkResult = await chkPromise;
54
+ if (chkResult)
55
+ utils_1.SLogger.warn(chkResult);
92
56
  }
93
57
  catch (error) {
94
58
  utils_1.SLogger.error(error);
@@ -2,14 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.cliRoute = cliRoute;
4
4
  const commander_1 = require("commander");
5
- const Node_1 = require("./Node");
6
- const Release_1 = require("./Release");
7
- const MapPath_1 = require("./MapPath");
8
- const ScanDups_1 = require("./ScanDups");
9
- const GenSchema_1 = require("./GenSchema");
5
+ const CheckToken_1 = require("./CheckToken");
10
6
  const ExpandMacro_1 = require("./ExpandMacro");
11
7
  const GenI18n_1 = require("./GenI18n");
8
+ const GenSchema_1 = require("./GenSchema");
12
9
  const GenTemplate_1 = require("./GenTemplate");
10
+ const MapPath_1 = require("./MapPath");
11
+ const Node_1 = require("./Node");
12
+ const Release_1 = require("./Release");
13
+ const ScanDups_1 = require("./ScanDups");
13
14
  async function cliRoute() {
14
15
  (0, Node_1.CmdNode)(commander_1.program);
15
16
  (0, Release_1.CmdRelease)(commander_1.program);
@@ -19,5 +20,6 @@ async function cliRoute() {
19
20
  (0, ExpandMacro_1.CmdExpandMacro)(commander_1.program);
20
21
  (0, GenI18n_1.CmdGenI18n)(commander_1.program);
21
22
  (0, GenTemplate_1.CmdGenTemplate)(commander_1.program);
23
+ (0, CheckToken_1.CmdCheckToken)(commander_1.program);
22
24
  commander_1.program.parse(process.argv);
23
25
  }
@@ -10,8 +10,8 @@ exports.parseBoolean = parseBoolean;
10
10
  exports.withMirrorSource = withMirrorSource;
11
11
  exports.withOfficialSource = withOfficialSource;
12
12
  exports.checkProject = checkProject;
13
- const pathe_1 = __importDefault(require("pathe"));
14
13
  const utils_1 = require("@zwa73/utils");
14
+ const pathe_1 = __importDefault(require("pathe"));
15
15
  /**npm镜像源 */
16
16
  exports.MIRROR_SOURCE = "https://registry.npmmirror.com/";
17
17
  /**npm官方源 */
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import type { Command } from "commander";
2
2
  /**重命名文件或路径 scan_duplicates */
3
3
  export declare const CmdScanDups: (program: Command) => Command;
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CmdScanDups = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
7
8
  const utils_1 = require("@zwa73/utils");
8
9
  const pathe_1 = __importDefault(require("pathe"));
9
- const fs_1 = __importDefault(require("fs"));
10
10
  const DynImport_1 = require("../DynImport");
11
11
  const { tap } = utils_1.UtilFP;
12
12
  /**hashlist转为dupmap */
@@ -62,6 +62,8 @@ const CmdScanDups = (program) => program
62
62
  : dir.map(d => pathe_1.default.isAbsolute(d) ? d : pathe_1.default.join(process.cwd(), d));
63
63
  // 添加一个多步进度条
64
64
  const cliProgress = await (0, DynImport_1.importCliProgress)();
65
+ if (!cliProgress)
66
+ (0, utils_1.throwError)('cli-progress 未安装');
65
67
  const progressBar = new cliProgress.MultiBar({
66
68
  clearOnComplete: true, hideCursor: true,
67
69
  format: " {task} [{bar}] {percentage}% | ETA: {eta}s | {value}/{total} | {status}",
@@ -82,9 +84,8 @@ const CmdScanDups = (program) => program
82
84
  return await utils_1.UtilFT.fileSearchRegex(p, regex.source, { recursive });
83
85
  })), stacklist => stacklist.flat(), // 扁平化文件路径列表
84
86
  // 如果是结构模式则先筛选相同结构
85
- // 扁平化文件路径列表
86
- list => struct ? (0, utils_1.pipe)(list, tap(dupFpList => (structProgress.setTotal(dupFpList.length),
87
- structProgress.update(0, { status: `结构扫描检出 ${dupFpList.length} 个可能的相等项` }))), list => utils_1.Stream.from(list, 8)
87
+ async (list) => struct ? (0, utils_1.pipe)(list, tap(dupFpList => (structProgress.setTotal(dupFpList.length),
88
+ structProgress.update(0, { status: `结构扫描检出 ${dupFpList.length} 个可能的相等项` }))), async (list) => utils_1.Stream.from(list, 8)
88
89
  .map(async (filePath) => ({
89
90
  filePath,
90
91
  hash: await struct2hash(await scanDirStruct(filePath), cpath => pathe_1.default.relative(filePath, cpath)).then(tap(() => structProgress.increment()))
@@ -92,11 +93,11 @@ const CmdScanDups = (program) => program
92
93
  .toArray(), reduce2Dupmap, reduce2DupFpList) : list,
93
94
  // 第二步:快速扫描,计算采样哈希
94
95
  tap(list => (sampledProgress.setTotal(list.length),
95
- sampledProgress.update(0, { status: `总计 ${list.length} 个文件` }))), list => utils_1.Stream.from(list, 8)
96
+ sampledProgress.update(0, { status: `总计 ${list.length} 个文件` }))), async (list) => utils_1.Stream.from(list, 8)
96
97
  .map(async (filePath) => ({
97
98
  filePath,
98
99
  hash: struct
99
- ? await struct2hash(await scanDirStruct(filePath), (str) => utils_1.UtilFT.calculateHash(str, { sampled: true })).then(tap(() => sampledProgress.increment()))
100
+ ? await struct2hash(await scanDirStruct(filePath), async (str) => utils_1.UtilFT.calculateHash(str, { sampled: true })).then(tap(() => sampledProgress.increment()))
100
101
  : await utils_1.UtilFT.calculateHash(filePath, { sampled: true }).then(tap(() => sampledProgress.increment())),
101
102
  }))
102
103
  .toArray(),
@@ -104,19 +105,19 @@ const CmdScanDups = (program) => program
104
105
  reduce2Dupmap, reduce2DupFpList,
105
106
  // 第四步:对筛选出的重复文件路径并发计算完整哈希
106
107
  tap(dupFpList => (fullHashProgress.setTotal(dupFpList.length),
107
- fullHashProgress.update(0, { status: `快速扫描检出 ${dupFpList.length} 个可能的相等项` }))), dupFpList => utils_1.Stream.from(dupFpList, 8)
108
+ fullHashProgress.update(0, { status: `快速扫描检出 ${dupFpList.length} 个可能的相等项` }))), async (dupFpList) => utils_1.Stream.from(dupFpList, 8)
108
109
  .map(async (filePath) => ({
109
110
  filePath,
110
111
  hash: struct
111
- ? await struct2hash(await scanDirStruct(filePath), (str) => utils_1.UtilFT.calculateHash(str)).then(tap(() => sampledProgress.increment()))
112
+ ? await struct2hash(await scanDirStruct(filePath), async (str) => utils_1.UtilFT.calculateHash(str)).then(tap(() => sampledProgress.increment()))
112
113
  : await utils_1.UtilFT.calculateHash(filePath).then(tap(() => fullHashProgress.increment())), // 计算完整哈希
113
114
  }))
114
115
  .toArray(),
115
116
  // 第五步:重新整理完整哈希结果, 过滤唯一哈希
116
117
  reduce2Dupmap, map => Object.entries(map).reduce((acc, [hash, files]) => files.length <= 1 ? acc : { ...acc, [hash]: files }, {}),
117
118
  // 第六步:输出结果
118
- tap(() => progressBar.stop()), out => (0, utils_1.match)(outtype, {
119
+ tap(() => progressBar.stop()), async (out) => (0, utils_1.match)(outtype, {
119
120
  "console": () => utils_1.SLogger.info(out),
120
- }, () => utils_1.UtilFT.writeJSONFile(pathe_1.default.join(basePath, outtype), out)));
121
+ }, async () => utils_1.UtilFT.writeJSONFile(pathe_1.default.join(basePath, outtype), out)));
121
122
  });
122
123
  exports.CmdScanDups = CmdScanDups;
@@ -1,15 +1,15 @@
1
- import type { getProgramFromFiles, buildGenerator } from 'typescript-json-schema';
2
- import type { Project, SyntaxKind } from 'ts-morph';
3
1
  import type cliProgress from "cli-progress";
2
+ import type { Project, SyntaxKind } from 'ts-morph';
3
+ import type { getProgramFromFiles, buildGenerator } from 'typescript-json-schema';
4
4
  type TJSInstance = {
5
5
  getProgramFromFiles: typeof getProgramFromFiles;
6
6
  buildGenerator: typeof buildGenerator;
7
7
  };
8
- type TsMorphInstance = {
8
+ export type TsMorphInstance = {
9
9
  Project: typeof Project;
10
10
  SyntaxKind: typeof SyntaxKind;
11
11
  };
12
- export declare function importTsMorph(): Promise<TsMorphInstance>;
13
- export declare function importTJS(): Promise<TJSInstance>;
14
- export declare function importCliProgress(): Promise<typeof cliProgress>;
12
+ export declare function importTsMorph(): Promise<TsMorphInstance | undefined>;
13
+ export declare function importTJS(): Promise<TJSInstance | undefined>;
14
+ export declare function importCliProgress(): Promise<typeof cliProgress | undefined>;
15
15
  export {};
package/dist/UtilAst.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyFunc } from "@zwa73/utils";
1
+ import type { AnyFunc } from "@zwa73/utils";
2
2
  import type { SyntaxKind, KindToNodeMappings, Node } from "ts-morph";
3
3
  export declare namespace UtilAst {
4
4
  /**匹配Node的类型进行处理 无法匹配时返回undefined
@@ -1,4 +1,4 @@
1
- import { JObject } from '@zwa73/utils';
1
+ import type { JObject } from '@zwa73/utils';
2
2
  export declare namespace UtilDT {
3
3
  /**执行js/ts的可选项 */
4
4
  type BatchNodeOpt = Partial<{
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.UtilDT = void 0;
7
- const pathe_1 = __importDefault(require("pathe"));
8
7
  const fs_1 = __importDefault(require("fs"));
9
8
  const utils_1 = require("@zwa73/utils");
9
+ const pathe_1 = __importDefault(require("pathe"));
10
10
  const DynImport_1 = require("./DynImport");
11
11
  var UtilDT;
12
12
  (function (UtilDT) {
@@ -25,7 +25,11 @@ var UtilDT;
25
25
  async function generateSchema(dir, opt) {
26
26
  //导入
27
27
  const TJS = await (0, DynImport_1.importTJS)();
28
+ if (!TJS)
29
+ (0, utils_1.throwError)('typescript-json-schema 未安装');
28
30
  const TsMorph = await (0, DynImport_1.importTsMorph)();
31
+ if (!TsMorph)
32
+ (0, utils_1.throwError)('ts-morph 未安装');
29
33
  //生成
30
34
  const settings = {
31
35
  required: true,
@@ -134,12 +138,12 @@ var UtilDT;
134
138
  // 创建一个字符串,其中包含所有文件的 require 语句
135
139
  const requires = absolutePaths.map(fp => `require('${fp}')`).join(';');
136
140
  // 创建并执行 ts-node 命令
137
- const cmd = `ts-node -r tsconfig-paths/register -e "${requires}" ${opt?.project ? `-P "${opt.project}"` : ""}`;
138
- await utils_1.UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'warn' });
141
+ const cmd = `ts-node --transpile-only -r tsconfig-paths/register -e "${requires}" ${opt?.project ? `-P "${opt.project}"` : ""}`;
142
+ await utils_1.UtilFunc.exec(cmd, { outlvl: console.log, errlvl: console.warn });
139
143
  }
140
144
  UtilDT.batchNode = batchNode;
141
145
  //#region macro工具
142
- const parseMacroPaths = (opt) => {
146
+ const parseMacroPaths = async (opt) => {
143
147
  // JsFunc -> ComposeFunc -> xxxmacro -> parseMacroPaths -> sourceTS
144
148
  const loc = utils_1.UtilFunc.getFuncLoc(4);
145
149
  if (!loc && !opt?.filePath)
@@ -3,5 +3,5 @@ export declare namespace UtilMacro {
3
3
  * @param glob - 应用的golb 默认 src\/**\/index.ts
4
4
  * @example
5
5
  */
6
- function exportComment(glob?: string): void;
6
+ function exportComment(glob?: string): Promise<void>;
7
7
  }
package/dist/UtilMacro.js CHANGED
@@ -5,16 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.UtilMacro = void 0;
7
7
  const utils_1 = require("@zwa73/utils");
8
- const QuickFunc_1 = require("./QuickFunc");
9
8
  const pathe_1 = __importDefault(require("pathe"));
9
+ const UtilDevTool_1 = require("./UtilDevTool");
10
10
  var UtilMacro;
11
11
  (function (UtilMacro) {
12
12
  /**根据注释批量生成导出
13
13
  * @param glob - 应用的golb 默认 src\/**\/index.ts
14
14
  * @example
15
15
  */
16
- function exportComment(glob = 'src/**/index.ts') {
17
- (0, QuickFunc_1.commentMacro)(/export (\S*)/, async ({ filePath, matchId, execArr }) => {
16
+ async function exportComment(glob = 'src/**/index.ts') {
17
+ await UtilDevTool_1.UtilDT.commentMacro(/export (\S*)/, async ({ filePath, matchId, execArr }) => {
18
18
  const basedir = pathe_1.default.dirname(filePath);
19
19
  const result = (await utils_1.UtilFT.fileSearchGlob(basedir, execArr[1]))
20
20
  .map((file) => pathe_1.default.relative(basedir, file))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/dev-utils",
3
- "version": "1.0.89",
3
+ "version": "1.0.90",
4
4
  "description": "编译与调试工具",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -30,8 +30,6 @@
30
30
  "@types/cli-progress": "^3.11.6",
31
31
  "@types/jest": "^29.5.12",
32
32
  "@types/node": "^20.14.11",
33
- "jest": "^29.7.0",
34
- "ts-jest": "^29.1.2",
35
33
  "tsc-alias": "^1.8.8",
36
34
  "typescript": "^5.3.3"
37
35
  },
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.compile.json",
3
- "compilerOptions": {
4
- "module": "node16",
5
- "moduleResolution": "node16",
6
- "outDir": "./dist/cjs",
7
- "target": "ES2022"
8
- }
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.compile.json",
3
- "compilerOptions": {
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "outDir": "./dist/mjs",
7
- "target": "ESNext"
8
- }
9
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "./tsconfig.compile.json",
3
- "compilerOptions": {
4
- "outDir": "./dist/types",
5
- "declaration": true,
6
- "emitDeclarationOnly": true
7
- }
8
- }