@zwa73/dev-utils 1.0.80 → 1.0.81
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/dist/test/testFileMacro.d.ts +1 -0
- package/dist/test/testFileMacro.js +1 -0
- package/dist/test/testGlobMacro.d.ts +1 -0
- package/dist/test/testGlobMacro.js +2 -0
- package/dist/test/testRegex.d.ts +1 -0
- package/dist/test/testRegex.js +10 -0
- package/dist/test/testRegex.macro.d.ts +1 -0
- package/dist/test/testRegex.macro.js +12 -0
- package/dist/test/testRegexa.d.ts +1 -0
- package/dist/test/testRegexa.js +1 -0
- package/dist/test/testRegexa.macro.d.ts +1 -0
- package/dist/test/testRegexa.macro.js +5 -0
- package/package.json +8 -2
- package/UnableTypes.txt +0 -1
- package/jest.config.js +0 -16
- package/scripts/compile.ps1 +0 -5
- package/scripts/postinstall.js +0 -54
- package/scripts/release.ps1 +0 -4
- package/scripts/watch.ps1 +0 -10
- package/src/Command/ExpandMacro.ts +0 -18
- package/src/Command/GenI18n.ts +0 -85
- package/src/Command/GenSchema.ts +0 -24
- package/src/Command/Init.ts +0 -65
- package/src/Command/InitElectron.ts +0 -42
- package/src/Command/MapPath.ts +0 -64
- package/src/Command/Node.ts +0 -16
- package/src/Command/Release.ts +0 -96
- package/src/Command/Route.ts +0 -24
- package/src/Command/RouteInterface.ts +0 -63
- package/src/Command/ScanDups.ts +0 -47
- package/src/Command/index.ts +0 -1
- package/src/Macro.macro.ts +0 -4
- package/src/QuickFunc.ts +0 -7
- package/src/UtilAst.ts +0 -25
- package/src/UtilDevTool.ts +0 -345
- package/src/UtilInterface.ts +0 -5
- package/src/UtilMacro.ts +0 -23
- package/src/index.ts +0 -5
- package/test.js +0 -29
- package/tsconfig.compile.json +0 -4
- package/tsconfig.json +0 -22
@@ -0,0 +1 @@
|
|
1
|
+
type FileMacro = 5;
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";
|
@@ -0,0 +1 @@
|
|
1
|
+
type Test3 = 4;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,10 @@
|
|
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
|
+
const utils_1 = require("@zwa73/utils");
|
7
|
+
const pathe_1 = __importDefault(require("pathe"));
|
8
|
+
utils_1.UtilFT.fileSearchRegexSync(__dirname, /.+/.source, { relative: false })
|
9
|
+
.map((filepath) => pathe_1.default.relative(__dirname, filepath)); //?
|
10
|
+
2;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const QuickFunc_1 = require("../QuickFunc");
|
4
|
+
console.log(__filename);
|
5
|
+
(0, QuickFunc_1.regionMacro)('macroTest1', "type Test1 = 1");
|
6
|
+
(0, QuickFunc_1.regionMacro)('macroTest2', "type Test2 = 2");
|
7
|
+
(0, QuickFunc_1.regionMacro)('macroTest3', "type Test3 = 3");
|
8
|
+
(0, QuickFunc_1.commentMacro)('comment1', "type CM1 = 3");
|
9
|
+
(0, QuickFunc_1.commentMacro)('comment2', "type CM2 = 3");
|
10
|
+
(0, QuickFunc_1.regionMacro)('macroTest4', "type Test3 = 4", { filePath: 'src/test/**/*.ts', glob: true });
|
11
|
+
(0, QuickFunc_1.fileMacro)("type FileMacro = 5", { filePath: 'src/test/testFileMacro.ts' });
|
12
|
+
(0, QuickFunc_1.commentMacro)(/regexTest[\S]*/, ({ matchId: id }) => `type ${id} = "${id}"`);
|
@@ -0,0 +1 @@
|
|
1
|
+
type CM1 = 3;
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zwa73/dev-utils",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.81",
|
4
4
|
"description": "编译与调试工具",
|
5
5
|
"main": "index.js",
|
6
6
|
"scripts": {
|
@@ -35,5 +35,11 @@
|
|
35
35
|
},
|
36
36
|
"bin": {
|
37
37
|
"zcli": "bin/cli"
|
38
|
-
}
|
38
|
+
},
|
39
|
+
"files": [
|
40
|
+
"data",
|
41
|
+
"dist",
|
42
|
+
"index.js",
|
43
|
+
"index.d.ts"
|
44
|
+
]
|
39
45
|
}
|
package/UnableTypes.txt
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
PartialOption,ProperSubset,ProperSubsetCheck,Literal,LiteralCheck,AssignObject,FixedLengthTuple,UnionToIntersection,ExclusiveSub,ExclusiveRecursive,ExclusiveRecord,ExclusiveJObject,Await,FuncPropNames,ComposedClass,Mixinable,IsCtor,RefMixinable,ComposedMixinable,ComposedRefMixinable,ExtendThen,MatchableFlag,ExtractOutcome,AnnotableTuple,bigint,UnionInclude
|
package/jest.config.js
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module.exports = {
|
6
|
-
roots: ['./jest'],
|
7
|
-
transform: {
|
8
|
-
'^.+\\.tsx?$': 'ts-jest',
|
9
|
-
},
|
10
|
-
moduleNameMapper: {
|
11
|
-
'^@src/(.*)$': '<rootDir>/dist/$1',
|
12
|
-
'^@/(.*)$': '<rootDir>/$1',
|
13
|
-
'^@$': '<rootDir>/index'
|
14
|
-
},
|
15
|
-
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
16
|
-
};
|
package/scripts/compile.ps1
DELETED
package/scripts/postinstall.js
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
const path = require('path');
|
2
|
-
const { UtilFT } = require("@zwa73/utils");
|
3
|
-
|
4
|
-
const PACKAGE_PATH = path.join(__dirname,'..','package.json');
|
5
|
-
const VERSION_PATH = path.join(__dirname,"..","..","version.json");
|
6
|
-
//提示表
|
7
|
-
const INFO_TABLE = {
|
8
|
-
"1.0.33":"zcli Build-Macro Build-Schema 更名为 Expand-Macro Gen-Schema",
|
9
|
-
"1.0.36":"$macro 更名为 regionMacro"
|
10
|
-
}
|
11
|
-
|
12
|
-
const PKG_NAME = "dev-utils";
|
13
|
-
|
14
|
-
// 将版本号转换为可以比较的数字
|
15
|
-
function versionToNumber(version) {
|
16
|
-
if(version==undefined) return 0;
|
17
|
-
return version.split('.').map(Number).reduce((acc, val) => acc * 1000 + val);
|
18
|
-
}
|
19
|
-
|
20
|
-
//显示提示
|
21
|
-
function showUpgradeMessages(prevVersion, currentVersion) {
|
22
|
-
const prevVersionNumber = versionToNumber(prevVersion);
|
23
|
-
const currentVersionNumber = versionToNumber(currentVersion);
|
24
|
-
let hasOut = false;
|
25
|
-
// 遍历infoTable中的所有版本
|
26
|
-
for (const version in INFO_TABLE) {
|
27
|
-
const versionNumber = versionToNumber(version);
|
28
|
-
// 如果用户的上一个版本低于这个版本,而当前版本高于或等于这个版本
|
29
|
-
if (versionNumber > prevVersionNumber && versionNumber <= currentVersionNumber) {
|
30
|
-
// 显示这个版本的提示信息
|
31
|
-
log(INFO_TABLE[version]);
|
32
|
-
hasOut=true;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
return hasOut;
|
36
|
-
}
|
37
|
-
|
38
|
-
const log = ()=>undefined;
|
39
|
-
|
40
|
-
async function main(){
|
41
|
-
const packageTable = await UtilFT.loadJSONFile(PACKAGE_PATH);
|
42
|
-
const currentVersion = packageTable.version;
|
43
|
-
await UtilFT.ensurePathExists(VERSION_PATH);
|
44
|
-
const versionTable = await UtilFT.loadJSONFile(VERSION_PATH,{default:{}});
|
45
|
-
const prevVersion = versionTable[PKG_NAME]?.version ?? "10000.0.0";
|
46
|
-
|
47
|
-
log(`${currentVersion} 版本已安装`);
|
48
|
-
// 使用这个函数来显示升级信息
|
49
|
-
const hasOut = showUpgradeMessages(prevVersion, currentVersion);
|
50
|
-
|
51
|
-
const ntable = Object.assign({},versionTable,{[PKG_NAME]:{version:currentVersion}});
|
52
|
-
await UtilFT.writeJSONFile(VERSION_PATH, ntable);
|
53
|
-
}
|
54
|
-
main()
|
package/scripts/release.ps1
DELETED
package/scripts/watch.ps1
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# 定义一个函数来运行脚本
|
2
|
-
function New-Script {
|
3
|
-
param($command)
|
4
|
-
# 在后台运行命令
|
5
|
-
Start-Process -NoNewWindow -FilePath "powershell" -ArgumentList "-Command", $command
|
6
|
-
}
|
7
|
-
|
8
|
-
# 开始运行脚本
|
9
|
-
New-Script "tsc -w -p tsconfig.compile.json"
|
10
|
-
New-Script "tsc-alias -w -p tsconfig.compile.json"
|
@@ -1,18 +0,0 @@
|
|
1
|
-
import { Command } from "commander";
|
2
|
-
import { UtilDT } from "@/src/UtilDevTool";
|
3
|
-
|
4
|
-
/**构造macro */
|
5
|
-
export const CmdExpandMacro = (program:Command) => program
|
6
|
-
.command("Expand-Macro")
|
7
|
-
.alias("expandmacro")
|
8
|
-
.description("根据macro生成代码")
|
9
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts","src/**/*.macro.ts")
|
10
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
11
|
-
.option("-p, --project <path>", "tsconfig路径 默认tsconfig.json","tsconfig.json")
|
12
|
-
.action(async (opt) => {
|
13
|
-
await UtilDT.matchNode(process.cwd(), {
|
14
|
-
include: opt.include,
|
15
|
-
exclude: opt.ignore,
|
16
|
-
project: opt.project,
|
17
|
-
});
|
18
|
-
});
|
package/src/Command/GenI18n.ts
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
import { Command } from "commander";
|
2
|
-
import { AnyFunc, I18nTextData, SI18n, UtilFT, ivk } from "@zwa73/utils";
|
3
|
-
import { Project,SyntaxKind } from 'ts-morph';
|
4
|
-
import { UtilAst } from "@/src/UtilAst";
|
5
|
-
import path from 'pathe';
|
6
|
-
|
7
|
-
function format(str:string){
|
8
|
-
return str.replace(/\\(.)/g,'$1').replace(/%/g,'\\%');
|
9
|
-
}
|
10
|
-
|
11
|
-
async function procFile(p:Project,filePath:string,funckey:string[]){
|
12
|
-
const date = new Date().toISOString();
|
13
|
-
//const content = await fs.promises.readFile(filePath,'utf-8');
|
14
|
-
const b = p.addSourceFileAtPath(filePath);
|
15
|
-
//const b = p.createSourceFile(path.relative(process.cwd(),filePath),content,{overwrite:true});
|
16
|
-
const ds = b.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);
|
17
|
-
const dats:I18nTextData[] = [];
|
18
|
-
for(const d of ds){
|
19
|
-
if(!funckey.includes(d.getTag().getText())) continue;
|
20
|
-
const template = d.getTemplate();
|
21
|
-
let result = '';
|
22
|
-
let i=0;
|
23
|
-
UtilAst.withKind(template,{
|
24
|
-
[SyntaxKind.NoSubstitutionTemplateLiteral]:(t)=>result+=format(t.getLiteralText()),
|
25
|
-
[SyntaxKind.TemplateExpression]:(t)=>{
|
26
|
-
t.getChildren().forEach((c)=>{
|
27
|
-
UtilAst.withKind(c,{
|
28
|
-
[SyntaxKind.TemplateHead]:(sc)=>result += format(sc.getLiteralText()),
|
29
|
-
[SyntaxKind.SyntaxList]:(sc)=>{
|
30
|
-
sc.getChildrenOfKind(SyntaxKind.TemplateSpan).forEach((span)=>{
|
31
|
-
span.getChildren().forEach((ssc)=>{
|
32
|
-
result += UtilAst.withKind(ssc,{
|
33
|
-
[SyntaxKind.TemplateMiddle]:(sssc)=>format(sssc.getLiteralText()),
|
34
|
-
[SyntaxKind.TemplateTail] :(sssc)=>format(sssc.getLiteralText()),
|
35
|
-
})??String(`%${i++}`);
|
36
|
-
})
|
37
|
-
})
|
38
|
-
},
|
39
|
-
});
|
40
|
-
});
|
41
|
-
}
|
42
|
-
});
|
43
|
-
const pos = b.getLineAndColumnAtPos(d.getStart());
|
44
|
-
const dat:I18nTextData={
|
45
|
-
original:result,
|
46
|
-
scan_time:date,
|
47
|
-
position: `${filePath}:${pos.line}:${pos.column}`,
|
48
|
-
lang_table:{},
|
49
|
-
source:"Ast"
|
50
|
-
}
|
51
|
-
dats.push(dat);
|
52
|
-
}
|
53
|
-
return dats;
|
54
|
-
}
|
55
|
-
|
56
|
-
async function scanI18n(i18nDataDir:string,include:string,exclude:string,funckey:string[]|string){
|
57
|
-
const fixedKey = typeof funckey == 'string' ? [funckey] : funckey;
|
58
|
-
const filePaths = (await UtilFT.fileSearchGlob(process.cwd(),include,{ingore:exclude}))
|
59
|
-
.filter(p=>['.ts','.tsx'].includes(path.parse(p).ext));
|
60
|
-
const project = new Project();
|
61
|
-
await SI18n.init(i18nDataDir,'*');
|
62
|
-
//console.log(filePaths);
|
63
|
-
(await Promise.all(filePaths.map(p=>procFile(project,p,fixedKey))))
|
64
|
-
.flat().forEach(dat=>SI18n.addOriginalText(dat));
|
65
|
-
await SI18n.saveTable();
|
66
|
-
}
|
67
|
-
|
68
|
-
/**生成i18n */
|
69
|
-
export const CmdGenI18n = (program:Command) => program
|
70
|
-
.command("Gen-I18n")
|
71
|
-
.alias("geni18n")
|
72
|
-
.description("根据文件行为树生成i18n数据")
|
73
|
-
.option("-o, --output <path>" , "输出的数据目录位置 默认 i18n",'i18n')
|
74
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.ts","src/**/*.ts")
|
75
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
76
|
-
.option("-f, --funckey <string|strings>", "扫描的目标函数名, 可传入逗号分隔数组, 默认 t",
|
77
|
-
(i:string)=>i.split(','),['t'])
|
78
|
-
.action(async (opt) => {
|
79
|
-
await scanI18n(
|
80
|
-
opt.output ,
|
81
|
-
opt.include,
|
82
|
-
opt.exclude,
|
83
|
-
opt.funckey,
|
84
|
-
);
|
85
|
-
});
|
package/src/Command/GenSchema.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import { Command } from "commander";
|
2
|
-
import { UtilDT } from "@/src/UtilDevTool";
|
3
|
-
|
4
|
-
/**生成schema */
|
5
|
-
export const CmdGenSchema = (program:Command) => program
|
6
|
-
.command("Gen-Schema")
|
7
|
-
.alias("genschema")
|
8
|
-
.description("生成匹配的文件的所有type的schema")
|
9
|
-
.option("-i, --include <glob>", "包含的glob 默认 src/**/*.schema.ts","src/**/*.schema.ts")
|
10
|
-
.option("-g, --exclude <glob>", "忽略的glob")
|
11
|
-
.option("-p, --project <path>", "tsconfig路径 默认tsconfig.json","tsconfig.json")
|
12
|
-
.option("-o, --out <dir>", "schema输出路径目录 默认 ./schema/")
|
13
|
-
.option("-it, --include-types <regexp[]>", "包含的types正则匹配数组, 传入逗号分隔数组",(i:string)=>i.split(','))
|
14
|
-
.option("-et, --exclude-types <regexp[]>", "排除的types正则匹配数组, 传入逗号分隔数组",(i:string)=>i.split(','))
|
15
|
-
.action(async (opt) => {
|
16
|
-
await UtilDT.generateSchema(process.cwd(), {
|
17
|
-
include : opt.include,
|
18
|
-
exclude : opt.exclude,
|
19
|
-
project : opt.project,
|
20
|
-
outDir : opt.out,
|
21
|
-
includeTypes: opt.includeTypes,
|
22
|
-
excludeTypes: opt.excludeTypes
|
23
|
-
});
|
24
|
-
});
|
package/src/Command/Init.ts
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
import { Command } from 'commander';
|
2
|
-
import * as fs from 'fs';
|
3
|
-
import path from 'pathe';
|
4
|
-
|
5
|
-
import { SLogger, UtilFT, UtilFunc } from '@zwa73/utils';
|
6
|
-
|
7
|
-
import { checkProject, DATA_PATH, MIRROR_SOURCE, PROJECT_PATH } from './RouteInterface';
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
const InitDataPath = path.join(DATA_PATH,'init');
|
14
|
-
|
15
|
-
/**复制基础文件 */
|
16
|
-
async function copyData() {
|
17
|
-
const filelist = await fs.promises.readdir(InitDataPath);
|
18
|
-
const plist = filelist.map(async (fileName)=>{
|
19
|
-
SLogger.info(`正在复制 ${fileName}`);
|
20
|
-
const filePath = path.join(InitDataPath,fileName);
|
21
|
-
const targetPath = path.join(PROJECT_PATH,fileName);
|
22
|
-
if(!await UtilFT.pathExists(targetPath))
|
23
|
-
await fs.promises.cp(filePath,targetPath,{recursive:true});
|
24
|
-
else
|
25
|
-
SLogger.info(`${fileName} 已存在 跳过`);
|
26
|
-
return null;
|
27
|
-
})
|
28
|
-
await Promise.all(plist);
|
29
|
-
}
|
30
|
-
|
31
|
-
/**安装npm包 */
|
32
|
-
async function installPackage() {
|
33
|
-
const install = async (name:string)=>
|
34
|
-
await UtilFunc.exec(`npm i --registry ${MIRROR_SOURCE} ${name}`);
|
35
|
-
const installdev = async (name:string)=>
|
36
|
-
await UtilFunc.exec(`npm i --registry ${MIRROR_SOURCE} --save-dev ${name}`);
|
37
|
-
const packageList = ['@zwa73/utils'];
|
38
|
-
const devPackList = [
|
39
|
-
'@zwa73/dev-utils',
|
40
|
-
'@types/fluent-ffmpeg',
|
41
|
-
'@types/node',
|
42
|
-
];
|
43
|
-
for(const name of packageList){
|
44
|
-
SLogger.info(`正在安装 ${name}`);
|
45
|
-
await install(name);
|
46
|
-
}
|
47
|
-
for(const name of devPackList){
|
48
|
-
SLogger.info(`正在安装 ${name}`);
|
49
|
-
await installdev(name);
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
/**对项目进行初始化 */
|
54
|
-
export const CmdInit = (program:Command)=>program
|
55
|
-
.command('Init')
|
56
|
-
.alias('init')
|
57
|
-
.description('对当前目录进行项目初始化')
|
58
|
-
.action(async (opt) => {
|
59
|
-
checkProject();
|
60
|
-
SLogger.info(`开始初始化设置当前目录 ${PROJECT_PATH}`);
|
61
|
-
await Promise.all([
|
62
|
-
copyData(),
|
63
|
-
installPackage(),
|
64
|
-
]);
|
65
|
-
});
|
@@ -1,42 +0,0 @@
|
|
1
|
-
import { Command } from 'commander';
|
2
|
-
import * as fs from 'fs';
|
3
|
-
import path from 'pathe';
|
4
|
-
|
5
|
-
import { SLogger, UtilFT, UtilFunc } from '@zwa73/utils';
|
6
|
-
|
7
|
-
import { checkProject, DATA_PATH, MIRROR_SOURCE, PROJECT_PATH } from './RouteInterface';
|
8
|
-
|
9
|
-
|
10
|
-
const InitDataPath = path.join(DATA_PATH,'InitElectron');
|
11
|
-
|
12
|
-
/**复制基础文件 */
|
13
|
-
async function copyData() {
|
14
|
-
const filelist = await fs.promises.readdir(InitDataPath);
|
15
|
-
const plist = filelist.map(async (fileName)=>{
|
16
|
-
SLogger.info(`正在复制 ${fileName}`);
|
17
|
-
const filePath = path.join(InitDataPath,fileName);
|
18
|
-
const targetPath = path.join(PROJECT_PATH,fileName);
|
19
|
-
if(!await UtilFT.pathExists(targetPath))
|
20
|
-
await fs.promises.cp(filePath,targetPath,{recursive:true});
|
21
|
-
else
|
22
|
-
SLogger.info(`${fileName} 已存在 跳过`);
|
23
|
-
return null;
|
24
|
-
})
|
25
|
-
await Promise.all(plist);
|
26
|
-
await fs.promises.rename('./gitignore','./.gitignore');
|
27
|
-
}
|
28
|
-
|
29
|
-
|
30
|
-
/**对项目进行初始化 */
|
31
|
-
export const CmdInitElectron = (program:Command)=>program
|
32
|
-
.command('Init-Electron')
|
33
|
-
.alias('initelectron')
|
34
|
-
.description('对当前目录进行项目初始化,创建Electron基础环境')
|
35
|
-
.action(async (opt) => {
|
36
|
-
//checkProject();
|
37
|
-
SLogger.info(`开始初始化设置当前目录 ${PROJECT_PATH}`);
|
38
|
-
await Promise.all([
|
39
|
-
copyData(),
|
40
|
-
UtilFunc.exec(`npm ci`,{outlvl:'info',errlvl:'warn'})
|
41
|
-
]);
|
42
|
-
});
|
package/src/Command/MapPath.ts
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
import { SLogger, UtilFT, matchProc, throwError } from "@zwa73/utils";
|
2
|
-
import { Command } from "commander";
|
3
|
-
import fs from "fs";
|
4
|
-
import path from "pathe";
|
5
|
-
|
6
|
-
const DupMethodList = ["skip","overwrite","move"] as const;
|
7
|
-
type DupMethod = typeof DupMethodList[number];
|
8
|
-
const DupMethodWithoutMove = DupMethodList.filter(t=>t!='move') as Exclude<DupMethod,'move'>[];
|
9
|
-
|
10
|
-
/**重命名文件或路径 */
|
11
|
-
export const CmdMapPath = (program: Command) => program
|
12
|
-
.command("Map-Path")
|
13
|
-
.alias("mappath")
|
14
|
-
.description("根据正则表达式对文件名进行映射")
|
15
|
-
.argument("<regex>", "要匹配的正则表达式, posix风格路径")
|
16
|
-
.argument("<replacement>", "替换字符串")
|
17
|
-
.option("-e, --exclude <regex>", "排除文件的正则表达式")
|
18
|
-
.option(`-d, --duplicate-handling <${DupMethodWithoutMove.join('|')}|[path:string]>`,
|
19
|
-
`处理重名文件的方式:
|
20
|
-
skip 不进行处理
|
21
|
-
overwrite 覆盖重名
|
22
|
-
其他字符串 将重名部分映射到指定目录下的对应位置, 再次重复将会覆盖`,
|
23
|
-
"skip")
|
24
|
-
.option("-r, --recursive", "是否处理子目录", false)
|
25
|
-
.option("-m, --move", "重命名而不是复制文件", false)
|
26
|
-
.option("-t, --test", "不对文件进行实际操作, 在控制台输出映射结果", false)
|
27
|
-
.action(async (regexStr, replacement, options) => {
|
28
|
-
const regex = new RegExp(regexStr);
|
29
|
-
const excludeRegex = options.exclude ? new RegExp(options.exclude) : null;
|
30
|
-
if(!DupMethodList.includes(options.duplicateHandling))
|
31
|
-
throwError(`${options.duplicateHandling} 不是有效的 duplicate-handling`);
|
32
|
-
const duplicateHandling = options.duplicateHandling as DupMethod;
|
33
|
-
const basePath = process.cwd();
|
34
|
-
// 遍历当前目录下的所有文件
|
35
|
-
const filePaths = (await UtilFT.fileSearchRegex(basePath, regex.source,{relative:options.recursive}))
|
36
|
-
.map((filePath)=>path.relative(basePath, filePath))
|
37
|
-
.filter((filePath)=>excludeRegex ? (!excludeRegex.test(filePath)) : true);
|
38
|
-
|
39
|
-
//对单个路径映射
|
40
|
-
const mapPath = async (source:string,target:string)=>{
|
41
|
-
const dir = path.parse(target).dir;
|
42
|
-
await UtilFT.ensurePathExists(dir,{dir:true});
|
43
|
-
if(options.test) return SLogger.info(`${source} -> ${target}`);
|
44
|
-
if (options.move) await fs.promises.rename(source, target);
|
45
|
-
else await fs.promises.copyFile(source, target);
|
46
|
-
}
|
47
|
-
|
48
|
-
for(const filePath of filePaths){
|
49
|
-
// 重命名文件
|
50
|
-
const newFilePath = filePath.replace(regex, replacement);
|
51
|
-
// 如果文件名发生了变化
|
52
|
-
if (newFilePath === filePath) continue;
|
53
|
-
//如果文件已存在
|
54
|
-
if(await UtilFT.pathExists(newFilePath)){
|
55
|
-
if(DupMethodWithoutMove.includes(options.duplicateHandling)){
|
56
|
-
const fixhd = duplicateHandling as Exclude<DupMethod,'move'>;
|
57
|
-
await matchProc(fixhd,{
|
58
|
-
'skip': ()=> SLogger.info(`重名文件存在,跳过:${newFilePath}`),
|
59
|
-
'overwrite': ()=> mapPath(filePath,newFilePath),
|
60
|
-
});
|
61
|
-
}else await mapPath(filePath, path.join(duplicateHandling, newFilePath));
|
62
|
-
} else await mapPath(filePath,newFilePath);
|
63
|
-
}
|
64
|
-
});
|
package/src/Command/Node.ts
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
import { Command } from 'commander';
|
2
|
-
|
3
|
-
import { SLogger, UtilFunc } from '@zwa73/utils';
|
4
|
-
|
5
|
-
/**编译并运行某个文件 */
|
6
|
-
export const CmdNode = (program:Command)=>program
|
7
|
-
.command('Node <path|path[]>')
|
8
|
-
.alias('node')
|
9
|
-
.option('-p, --project <path>','tsconfig的目录')
|
10
|
-
.description('编译并运行某个文件')
|
11
|
-
.action(async (arg, opt) => {
|
12
|
-
SLogger.info(`编译并运行: ${arg}`);
|
13
|
-
let cmd = `ts-node -r tsconfig-paths/register ${arg}`;
|
14
|
-
if(opt.project) cmd+=` -P ${opt.project}`;
|
15
|
-
await UtilFunc.exec(cmd,{outlvl:'info',errlvl:'error'});
|
16
|
-
});
|
package/src/Command/Release.ts
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
import { Command } from 'commander';
|
2
|
-
import path from 'pathe';
|
3
|
-
|
4
|
-
import { memoize, SLogger, throwError, UtilFT, UtilFunc } from '@zwa73/utils';
|
5
|
-
|
6
|
-
import { checkProject, OFFICIAL_SOURCE, PROJECT_PATH } from './RouteInterface';
|
7
|
-
import fs from 'fs';
|
8
|
-
|
9
|
-
/**解析版本号为number数组 */
|
10
|
-
function parseVersion(version: string){
|
11
|
-
const arr = version.split(".").map(Number);
|
12
|
-
if (arr.length !== 3)
|
13
|
-
throwError(`${version} 不是有效的版本号`,'error');
|
14
|
-
for (let i = 0; i < 3; i++){
|
15
|
-
if (!isFinite(arr[i]))
|
16
|
-
throwError(`${version} 不是有效的版本号`,'error');
|
17
|
-
}
|
18
|
-
return arr;
|
19
|
-
}
|
20
|
-
/**判断版本号是否有效 */
|
21
|
-
function checkVersion(oldVersion: string, newVersion: string) {
|
22
|
-
const oldParts = parseVersion(oldVersion);
|
23
|
-
const newParts = parseVersion(newVersion);
|
24
|
-
for (let i = 0; i < 3; i++) {
|
25
|
-
if (newParts[i] < oldParts[i])
|
26
|
-
throwError(`${newVersion} 低于当前版本号 ${oldVersion}`,'error');
|
27
|
-
if (newParts[i] > oldParts[i])
|
28
|
-
break;
|
29
|
-
}
|
30
|
-
}
|
31
|
-
|
32
|
-
/**更新版本号 */
|
33
|
-
async function updateVersion(newVersion?: string): Promise<string> {
|
34
|
-
const packagePath = path.join(PROJECT_PATH, "package.json");
|
35
|
-
const packageData = await memoize(UtilFT.loadJSONFile)(packagePath) as any;
|
36
|
-
if (newVersion) {
|
37
|
-
checkVersion(packageData.version, newVersion);
|
38
|
-
packageData.version = newVersion;
|
39
|
-
} else {
|
40
|
-
const version = packageData.version.split(".");
|
41
|
-
version[2] = (parseInt(version[2]) + 1).toString();
|
42
|
-
packageData.version = version.join(".");
|
43
|
-
}
|
44
|
-
await UtilFT.writeJSONFile(packagePath, packageData);
|
45
|
-
return packageData.version;
|
46
|
-
}
|
47
|
-
/**获取包名 */
|
48
|
-
async function getPackName(){
|
49
|
-
const packagePath = path.join(PROJECT_PATH, "package.json");
|
50
|
-
const packageData = await memoize(UtilFT.loadJSONFile)(packagePath) as any;
|
51
|
-
return packageData.name
|
52
|
-
.replace(/\//g,'-')
|
53
|
-
.replace(/^@/g,'');
|
54
|
-
}
|
55
|
-
|
56
|
-
/**更新版本号并发布npm包 */
|
57
|
-
export const CmdRelease = (program: Command) =>program
|
58
|
-
.command("Release")
|
59
|
-
.alias("release")
|
60
|
-
.description("更新版本号并发布包")
|
61
|
-
.option("-v, --version <version>", "指定发布的版本号 格式应为 `${number}.${number}.${number}`")
|
62
|
-
.option("-a, --access <access>", "npm publish 的 access 参数 默认 public","public")
|
63
|
-
.option("-l, --local <path>", "仅打包到本地对印目录下 如./build/",undefined)
|
64
|
-
.action(async (opt:{
|
65
|
-
version?: string;
|
66
|
-
access: string;
|
67
|
-
local?: string;
|
68
|
-
}) => {
|
69
|
-
checkProject();
|
70
|
-
SLogger.info(`开始发布项目`);
|
71
|
-
try {
|
72
|
-
const newVersion = await updateVersion(opt.version);
|
73
|
-
SLogger.info(`新版本号: ${newVersion}`);
|
74
|
-
if(opt.local){
|
75
|
-
SLogger.info("正在打包...");
|
76
|
-
const fullpath = path.join(process.cwd(),opt.local);
|
77
|
-
await UtilFT.ensurePathExists(fullpath,{dir:true});
|
78
|
-
await UtilFunc.exec(`npm pack`,{errlvl:'info'});
|
79
|
-
const packageName = await getPackName();
|
80
|
-
const filelist = await fs.promises.readdir(process.cwd());
|
81
|
-
await Promise.all(filelist
|
82
|
-
.filter(p=>new RegExp(packageName).test(p))
|
83
|
-
.map(async p=>{
|
84
|
-
const packagePath = path.join(fullpath, p);
|
85
|
-
await fs.promises.rename(p, packagePath);
|
86
|
-
}))
|
87
|
-
return;
|
88
|
-
}
|
89
|
-
SLogger.info("正在发布...");
|
90
|
-
const cmd = `npm publish --registry ${OFFICIAL_SOURCE} --access ${opt.access}`;
|
91
|
-
await UtilFunc.exec(cmd,{errlvl:'info'});
|
92
|
-
SLogger.info("发布完成");
|
93
|
-
} catch (error) {
|
94
|
-
SLogger.error(error);
|
95
|
-
}
|
96
|
-
});
|
package/src/Command/Route.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import { program } from 'commander';
|
2
|
-
|
3
|
-
import { CmdInit } from './Init';
|
4
|
-
import { CmdNode } from './Node';
|
5
|
-
import { CmdRelease } from './Release';
|
6
|
-
import { CmdMapPath } from './MapPath';
|
7
|
-
import { CmdScanDups } from './ScanDups';
|
8
|
-
import { CmdGenSchema } from './GenSchema';
|
9
|
-
import { CmdExpandMacro } from './ExpandMacro';
|
10
|
-
import { CmdGenI18n } from './GenI18n';
|
11
|
-
import { CmdInitElectron } from './InitElectron';
|
12
|
-
|
13
|
-
export async function cliRoute(){
|
14
|
-
CmdInit(program);
|
15
|
-
CmdInitElectron(program);
|
16
|
-
CmdNode(program);
|
17
|
-
CmdRelease(program);
|
18
|
-
CmdMapPath(program);
|
19
|
-
CmdScanDups(program);
|
20
|
-
CmdGenSchema(program);
|
21
|
-
CmdExpandMacro(program);
|
22
|
-
CmdGenI18n(program);
|
23
|
-
program.parse(process.argv);
|
24
|
-
}
|
@@ -1,63 +0,0 @@
|
|
1
|
-
import path from 'pathe';
|
2
|
-
|
3
|
-
import { SLogger, throwError, UtilFT, UtilFunc } from '@zwa73/utils';
|
4
|
-
|
5
|
-
/**npm镜像源 */
|
6
|
-
export const MIRROR_SOURCE = "https://registry.npmmirror.com/";
|
7
|
-
/**npm官方源 */
|
8
|
-
export const OFFICIAL_SOURCE = "https://registry.npmjs.org/";
|
9
|
-
/**data文件夹路径 */
|
10
|
-
export const DATA_PATH = path.join(__dirname,'..','..','data');
|
11
|
-
/**项目路径 */
|
12
|
-
export const PROJECT_PATH = process.cwd();
|
13
|
-
|
14
|
-
/** 检测非浮点的整数类型 */
|
15
|
-
export function parseInteger(value: string): number {
|
16
|
-
const num = Number(value);
|
17
|
-
if(!(typeof num === 'number' && isFinite(num) && Math.floor(num) === num))
|
18
|
-
throwError(`${value} 不是有效的整数数字`);
|
19
|
-
return num;
|
20
|
-
}
|
21
|
-
|
22
|
-
/** 检测任意数字类型 */
|
23
|
-
export function parseNumber(value: string):number {
|
24
|
-
const num = Number(value);
|
25
|
-
if(!(typeof value === 'number' && isFinite(value)))
|
26
|
-
throwError(`${value} 不是有效的数字`);
|
27
|
-
return num;
|
28
|
-
}
|
29
|
-
|
30
|
-
/** 检测布尔类型 */
|
31
|
-
export function parseBoolean(value: string): boolean {
|
32
|
-
return value? true:false;
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
/**在镜像源内镜像操作 */
|
37
|
-
export async function withMirrorSource(func:(()=>any)){
|
38
|
-
const out = await UtilFunc.exec('npm config get registry');
|
39
|
-
const OriginSource = out.stdout.trim()//?
|
40
|
-
SLogger.info(`正在修改npm源为 镜像源: ${MIRROR_SOURCE}`);
|
41
|
-
await UtilFunc.exec(`npm config set registry ${MIRROR_SOURCE}`);
|
42
|
-
await func();
|
43
|
-
SLogger.info(`正在修改npm源为 原始源: ${OriginSource}`);
|
44
|
-
await UtilFunc.exec(`npm config set registry ${OriginSource}`);
|
45
|
-
}
|
46
|
-
|
47
|
-
/**在官方源内镜像操作 */
|
48
|
-
export async function withOfficialSource(func:(()=>any)){
|
49
|
-
const out = await UtilFunc.exec('npm config get registry');
|
50
|
-
const OriginSource = out.stdout.trim()//?
|
51
|
-
SLogger.info(`正在修改npm源为 官方源: ${OFFICIAL_SOURCE}`);
|
52
|
-
await UtilFunc.exec(`npm config set registry ${OFFICIAL_SOURCE}`);
|
53
|
-
await func();
|
54
|
-
SLogger.info(`正在修改npm源为 原始源: ${OriginSource}`);
|
55
|
-
await UtilFunc.exec(`npm config set registry ${OriginSource}`);
|
56
|
-
}
|
57
|
-
|
58
|
-
/**检查目录是否为项目 */
|
59
|
-
export async function checkProject() {
|
60
|
-
const filePath = path.join(PROJECT_PATH,"package.json");
|
61
|
-
if(!(await UtilFT.pathExists(filePath)))
|
62
|
-
throwError(`当前目录: ${PROJECT_PATH} 不是npm项目目录, 请先使用 npm init`);
|
63
|
-
}
|
package/src/Command/ScanDups.ts
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
import { SLogger, UtilFT } from "@zwa73/utils";
|
2
|
-
import { Command } from "commander";
|
3
|
-
import fs from "fs";
|
4
|
-
import crypto from 'crypto';
|
5
|
-
import path from "pathe";
|
6
|
-
|
7
|
-
async function calculateHash(filePath:string) {
|
8
|
-
return new Promise<string>((resolve, reject) => {
|
9
|
-
const hash = crypto.createHash('md5');
|
10
|
-
const stream = fs.createReadStream(filePath);
|
11
|
-
stream.on('data', (data) => hash.update(data));
|
12
|
-
stream.on('end', () => resolve(hash.digest('hex')));
|
13
|
-
stream.on('error', reject);
|
14
|
-
});
|
15
|
-
}
|
16
|
-
|
17
|
-
|
18
|
-
/**重命名文件或路径 scan_duplicates */
|
19
|
-
export const CmdScanDups = (program: Command) => program
|
20
|
-
.command("Scan-Dups")
|
21
|
-
.alias("scandups")
|
22
|
-
.description("扫描当前目录下hash重复的文件")
|
23
|
-
.option("-re, --regex <regex>", "文件的正则表达式, 使用posix路径",".*")
|
24
|
-
.option("-o, --out <dir|console>", "输出的json文件路径, 默认 scandupsOut.json, 为 \"console\" 时无文件输出", "scandupsOut")
|
25
|
-
.option("-r, --recursive", "是否处理子目录, 默认 true", true)
|
26
|
-
.action(async (options) => {
|
27
|
-
const regex = new RegExp(options.regex);
|
28
|
-
const basePath = process.cwd();
|
29
|
-
const pList = (await UtilFT.fileSearchRegex(basePath, regex.source, {
|
30
|
-
relative: options.recursive,
|
31
|
-
})).map(async (filePath) => ({ filePath, hash: await calculateHash(filePath) }));
|
32
|
-
|
33
|
-
const hashMap = (await Promise.all(pList)).reduce((obj,cur)=>{
|
34
|
-
obj[cur.hash] = (obj[cur.hash]??[]).concat(cur.filePath);
|
35
|
-
return obj;
|
36
|
-
},{} as Record<string,string[]>);
|
37
|
-
const out:Record<string,string[]> = {};
|
38
|
-
for (const hash in hashMap) {
|
39
|
-
const duplicateFiles = hashMap[hash];
|
40
|
-
if(duplicateFiles.length<=1) continue;
|
41
|
-
out[hash] = duplicateFiles;
|
42
|
-
}
|
43
|
-
if(options.out==="console")
|
44
|
-
SLogger.info(out);
|
45
|
-
else
|
46
|
-
await UtilFT.writeJSONFile(path.join(basePath,options.out),out);
|
47
|
-
});
|
package/src/Command/index.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Route';
|
package/src/Macro.macro.ts
DELETED
package/src/QuickFunc.ts
DELETED
package/src/UtilAst.ts
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
import { AnyFunc,I18nTextData } from "@zwa73/utils";
|
2
|
-
import { SyntaxKind , KindToNodeMappings, Node} from "ts-morph";
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
export namespace UtilAst{
|
11
|
-
/**匹配Node的类型进行处理 无法匹配时返回undefined
|
12
|
-
* @param node - ast节点
|
13
|
-
* @param funcMap - 处理函数映射表
|
14
|
-
*/
|
15
|
-
export function withKind<T extends Partial<{
|
16
|
-
[P in SyntaxKind]:((n:KindToNodeMappings[P])=>unknown)
|
17
|
-
}>>(node:Node,funcMap:T):{
|
18
|
-
[P in keyof T]:T[P] extends AnyFunc ? ReturnType<T[P]> : never
|
19
|
-
}[keyof T]|undefined{
|
20
|
-
const kind = node.getKind();
|
21
|
-
const func = funcMap[kind] as any;
|
22
|
-
if(func) return func(node);
|
23
|
-
return undefined;
|
24
|
-
}
|
25
|
-
}
|
package/src/UtilDevTool.ts
DELETED
@@ -1,345 +0,0 @@
|
|
1
|
-
import path from 'pathe';
|
2
|
-
import * as TJS from 'typescript-json-schema';
|
3
|
-
import * as fs from 'fs';
|
4
|
-
import { JObject, SLogger, UtilFT, UtilFunc, dedent, throwError } from '@zwa73/utils';
|
5
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
6
|
-
|
7
|
-
export namespace UtilDT{
|
8
|
-
|
9
|
-
/**执行js/ts的可选项 */
|
10
|
-
type BatchNodeOpt = Partial<{
|
11
|
-
/**tsconfig路径 */
|
12
|
-
project:string;
|
13
|
-
}>
|
14
|
-
|
15
|
-
/**build任意ts文件的可选项 */
|
16
|
-
type BuildMatchOpt = Partial<{
|
17
|
-
/**包含的glob */
|
18
|
-
include:string|string[];
|
19
|
-
/**忽略的glob */
|
20
|
-
exclude:string|string[];
|
21
|
-
}>&BatchNodeOpt;
|
22
|
-
|
23
|
-
/**build schema的可选项 */
|
24
|
-
type BuildSchemaOpt = Partial<{
|
25
|
-
/**将会覆盖 definitions 对应内容的表 */
|
26
|
-
coverDefine:JObject;
|
27
|
-
/**schema输出路径目录 如 ./schema/ */
|
28
|
-
outDir:string;
|
29
|
-
/**包含的types正则匹配数组 默认 [/.*\/] */
|
30
|
-
includeTypes?:string[];
|
31
|
-
/**排除的types正则匹配数组 */
|
32
|
-
excludeTypes?:string[];
|
33
|
-
}>&BuildMatchOpt;
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
/**生成匹配的文件的所有type的schema
|
38
|
-
* @async
|
39
|
-
* @param dir - 基础目录
|
40
|
-
* @param opt - 可选参数
|
41
|
-
* @param opt.include - 包含的glob 默认 **\/\*.schema.ts
|
42
|
-
* @param opt.exclude - 忽略的glob
|
43
|
-
* @param opt.coverDefine - 将会覆盖 definitions 对应内容的表
|
44
|
-
* @param opt.project - tsconfig路径
|
45
|
-
* @param opt.outDir - schema输出路径目录 默认 ./schema/
|
46
|
-
* @param opt.includeTypes - 包含的types正则匹配数组 默认 [/.*\/]
|
47
|
-
* @param opt.excludeTypes - 排除的types正则匹配数组
|
48
|
-
*/
|
49
|
-
export async function generateSchema(dir:string,opt?:BuildSchemaOpt){
|
50
|
-
//生成
|
51
|
-
const settings: TJS.PartialArgs = {
|
52
|
-
required: true,
|
53
|
-
aliasRef:true,
|
54
|
-
tsNodeRegister:true,
|
55
|
-
ignoreErrors:true,
|
56
|
-
};
|
57
|
-
const compilerOptions: TJS.CompilerOptions = {
|
58
|
-
strictNullChecks: true,
|
59
|
-
};
|
60
|
-
if(opt?.project) Object.assign(compilerOptions,(await UtilFT.loadJSONFile(opt.project) as any).compilerOptions);
|
61
|
-
const files = await UtilFT.fileSearchGlob(dir,opt?.include ?? "**/*.schema.ts",{ingore:opt?.exclude});
|
62
|
-
|
63
|
-
const program = TJS.getProgramFromFiles(
|
64
|
-
files,
|
65
|
-
compilerOptions,
|
66
|
-
);
|
67
|
-
const gener = TJS.buildGenerator(program,settings)!;
|
68
|
-
//const schema = TJS.generateSchema(program, opt?.typeName??"*", settings,undefined,gener) as JObject;
|
69
|
-
const it = opt?.includeTypes?.map(t=>new RegExp(t))??[/.*/];
|
70
|
-
const et = opt?.excludeTypes?.map(t=>new RegExp(t))??[];
|
71
|
-
const p = new Project();
|
72
|
-
const types = files.map(fp => p
|
73
|
-
.addSourceFileAtPath(fp)
|
74
|
-
.getDescendantsOfKind(SyntaxKind.TypeAliasDeclaration)
|
75
|
-
.map(d=>d.getName())
|
76
|
-
).flat();
|
77
|
-
const list = gener.getUserSymbols()
|
78
|
-
.filter(t=>types.some(i=>i===t))
|
79
|
-
.filter(t=>it.some(i=>i.test(t)))
|
80
|
-
.filter(t=>!et.some(i=>i.test(t)));
|
81
|
-
const schema = gener.getSchemaForSymbols(list) as JObject;
|
82
|
-
const outDir = opt?.outDir ?? path.join(process.cwd(),'schema');
|
83
|
-
const schemasPath = path.join(outDir,'schemas.json');
|
84
|
-
//预处理
|
85
|
-
const proced = procSchema(schema,opt?.coverDefine??{});
|
86
|
-
await Promise.all([
|
87
|
-
UtilFT.writeJSONFile(schemasPath,proced),
|
88
|
-
//展开
|
89
|
-
expandSchema(proced,schemasPath),
|
90
|
-
]);
|
91
|
-
}
|
92
|
-
function procSchema(schema:JObject,coverDefine:JObject){
|
93
|
-
//覆盖
|
94
|
-
coverObj(schema["definitions"] as JObject,coverDefine);
|
95
|
-
//替换SchemaString标识符
|
96
|
-
schema = JSON.parse(JSON.stringify(schema).replace(/\^\.\*SchemaString\$/g,'^.*$'));
|
97
|
-
return schema;
|
98
|
-
}
|
99
|
-
/**展开schema以供使用 */
|
100
|
-
async function expandSchema(schema:JObject,schemasPath:string){
|
101
|
-
const plist:Promise<void>[] = [];
|
102
|
-
const definitions = schema["definitions"] as Record<string,JObject>;
|
103
|
-
//展开定义
|
104
|
-
for(const typeName in definitions){
|
105
|
-
const schema = definitions[typeName];
|
106
|
-
//展开所有object与忽略检测的类型
|
107
|
-
if(!(schema.type == "object" || schema.type == "array" || schema.type == undefined)) continue;
|
108
|
-
if((/^.+_[0-9]/).test(typeName) || (/^{./).test(typeName)) continue;
|
109
|
-
|
110
|
-
const basename = path.basename(schemasPath);
|
111
|
-
const tpath = path.join(path.dirname(schemasPath),`${typeName}.schema.json`);
|
112
|
-
if(!UtilFT.isValidFilePath(tpath)) continue;
|
113
|
-
plist.push(UtilFT.writeJSONFile(tpath,{
|
114
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
115
|
-
"$ref": `${basename}#/definitions/${typeName}`
|
116
|
-
}));
|
117
|
-
}
|
118
|
-
await Promise.all(plist);
|
119
|
-
}
|
120
|
-
/**覆盖object */
|
121
|
-
function coverObj(base:JObject,cover:JObject){
|
122
|
-
for(const k in cover){
|
123
|
-
const v = cover[k];
|
124
|
-
if( typeof v === "object" && !Array.isArray(v) &&
|
125
|
-
typeof base[k] === "object" && !Array.isArray(base[k]) )
|
126
|
-
coverObj(base[k] as JObject,v as JObject);
|
127
|
-
else
|
128
|
-
base[k] = v;
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
/**运行所有匹配的的js/ts文件
|
133
|
-
* @async
|
134
|
-
* @param dir - 基础目录
|
135
|
-
* @param opt - 可选参数
|
136
|
-
* @param opt.include - 包含的glob 默认 index.ts
|
137
|
-
* @param opt.exclude - 忽略的glob
|
138
|
-
* @param opt.project - tsconfig路径
|
139
|
-
*/
|
140
|
-
export async function matchNode(dir:string,opt?:BuildMatchOpt) {
|
141
|
-
const files = await UtilFT.fileSearchGlob(dir,opt?.include ?? "index.ts",{ingore:opt?.exclude});
|
142
|
-
await batchNode(files,opt);
|
143
|
-
}
|
144
|
-
/**运行所有js/ts文件
|
145
|
-
* @async
|
146
|
-
* @param filepath - 需要运行的文件
|
147
|
-
* @param opt - 可选参数
|
148
|
-
* @param opt.project - tsconfig路径
|
149
|
-
*/
|
150
|
-
export async function batchNode(filepath:string|string[],opt?:BatchNodeOpt) {
|
151
|
-
// 确保 filepath 总是一个数组
|
152
|
-
if (!Array.isArray(filepath)) filepath = [filepath];
|
153
|
-
// 将所有的相对路径转换为绝对路径
|
154
|
-
const absolutePaths = filepath.map(fp => path.resolve(process.cwd(), fp));
|
155
|
-
// 创建一个字符串,其中包含所有文件的 require 语句
|
156
|
-
const requires = absolutePaths.map(fp => `require('${fp}')`).join(';');
|
157
|
-
// 创建并执行 ts-node 命令
|
158
|
-
const cmd = `ts-node -r tsconfig-paths/register -e "${requires}" ${opt?.project?`-P "${opt.project}"` : ""}`;
|
159
|
-
await UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'warn' });
|
160
|
-
}
|
161
|
-
|
162
|
-
/**宏的可选参数 */
|
163
|
-
type MacroOpt = Partial<{
|
164
|
-
/**宏展开的目标文件 */
|
165
|
-
filePath:string[]|string;
|
166
|
-
/**使用glob匹配而非文件路径 */
|
167
|
-
glob:boolean;
|
168
|
-
}>
|
169
|
-
/**codeText的参数 */
|
170
|
-
type CodeTextOpt = {
|
171
|
-
/**匹配的region/comment id */
|
172
|
-
matchId:string;
|
173
|
-
/**region/comment id正则的执行结果*/
|
174
|
-
execArr:RegExpExecArray;
|
175
|
-
/**展开宏的目标文件 */
|
176
|
-
filePath:string;
|
177
|
-
/**展开宏区域的原文本 */
|
178
|
-
text:string;
|
179
|
-
/**缩进 会自动应用 */
|
180
|
-
inent:string;
|
181
|
-
}
|
182
|
-
//#region macro工具
|
183
|
-
const parseMacroPaths = (opt?:MacroOpt)=>{
|
184
|
-
const loc = UtilFunc.getFuncLoc(3);
|
185
|
-
if(!loc && !opt?.filePath) throwError(`parseMacroPaths 未能找到函数位置`);
|
186
|
-
const basePath = loc?.filePath!;
|
187
|
-
return opt?.filePath
|
188
|
-
? opt.glob
|
189
|
-
? UtilFT.fileSearchGlob(process.cwd(),opt.filePath)
|
190
|
-
: typeof opt?.filePath==="string"
|
191
|
-
? [opt?.filePath]
|
192
|
-
: opt?.filePath.map((filepath)=>filepath)
|
193
|
-
: [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/,"$1.$2")];
|
194
|
-
}
|
195
|
-
const readFile = async (basePath:string)=>
|
196
|
-
(await fs.promises.readFile(basePath,'utf-8')).replaceAll("\r\n","\n");
|
197
|
-
const parseCodeText = async (codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt:CodeTextOpt)=>{
|
198
|
-
const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
|
199
|
-
return strText.split('\n').map((line)=>`${opt.inent}${line}`).join('\n');
|
200
|
-
}
|
201
|
-
const literalRegex = (str:string)=>new RegExp(
|
202
|
-
`^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
|
203
|
-
//#endregion
|
204
|
-
/**将codeText写入对应region
|
205
|
-
* @param regionId - 区域id \`//#region ${id}\`
|
206
|
-
* @param codeText - 文本
|
207
|
-
* @param opt - 可选参数
|
208
|
-
* @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
|
209
|
-
* @param opt.glob - 使用glob匹配而非文件路径
|
210
|
-
*/
|
211
|
-
export async function regionMacro(regionId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
|
212
|
-
const plist:Promise<void>[] = [];
|
213
|
-
const filePaths = await parseMacroPaths(opt);
|
214
|
-
for(const filePath of filePaths){
|
215
|
-
const queuefunc = async ()=>{
|
216
|
-
if(!(await UtilFT.pathExists(filePath))) {
|
217
|
-
SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
|
218
|
-
return
|
219
|
-
}
|
220
|
-
let fileText = await readFile(filePath);
|
221
|
-
const regex = new RegExp(
|
222
|
-
/(^|\n)([^\S\n]*)(\/\/#region (.*)\n)/.source+
|
223
|
-
/([\s\S]*?)/.source+
|
224
|
-
/([^\S\n]*\/\/#endregion(?!\S).*)/.source
|
225
|
-
,"g")
|
226
|
-
regex.lastIndex=0;
|
227
|
-
let match:RegExpExecArray|null;
|
228
|
-
let hasMatch = false;
|
229
|
-
while(match = regex.exec(fileText)){
|
230
|
-
const id = match[4];
|
231
|
-
const prefix = match[1];
|
232
|
-
const content = match[5];
|
233
|
-
const inent = match[2];
|
234
|
-
const comment = match[3];
|
235
|
-
const endcomment = match[6];
|
236
|
-
|
237
|
-
const idregex = typeof regionId === "string"
|
238
|
-
? literalRegex(regionId) : regionId;
|
239
|
-
let idmatch = idregex.exec(id);
|
240
|
-
if(idmatch==null) continue;
|
241
|
-
hasMatch=true;
|
242
|
-
const ol = fileText.length;
|
243
|
-
const parseCode = await parseCodeText(codeText,{
|
244
|
-
matchId :idmatch[0],
|
245
|
-
execArr :idmatch,
|
246
|
-
text :dedent(content),
|
247
|
-
inent ,
|
248
|
-
filePath
|
249
|
-
});
|
250
|
-
fileText = fileText.replace(match[0], `${prefix}${inent}${comment}${parseCode}\n${endcomment}`);
|
251
|
-
regex.lastIndex += fileText.length - ol;
|
252
|
-
}
|
253
|
-
if(hasMatch)
|
254
|
-
await fs.promises.writeFile(filePath, fileText, 'utf-8');
|
255
|
-
else if(!opt?.glob) SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
|
256
|
-
}
|
257
|
-
plist.push(UtilFunc.queueProc(path.normalize(filePath),queuefunc))
|
258
|
-
}
|
259
|
-
await Promise.all(plist);
|
260
|
-
}
|
261
|
-
/**将codeText写入对应注释下
|
262
|
-
* @param commentId - 注释id \`// ${id}\`
|
263
|
-
* @param codeText - 文本
|
264
|
-
* @param opt - 可选参数
|
265
|
-
* @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
|
266
|
-
* @param opt.glob - 使用glob匹配而非文件路径
|
267
|
-
*/
|
268
|
-
export async function commentMacro(commentId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
|
269
|
-
const plist:Promise<void>[] = [];
|
270
|
-
const filePaths = await parseMacroPaths(opt);
|
271
|
-
for(const filePath of filePaths){
|
272
|
-
const queuefunc = async ()=>{
|
273
|
-
if(!(await UtilFT.pathExists(filePath))) {
|
274
|
-
SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
|
275
|
-
return
|
276
|
-
}
|
277
|
-
let fileText = await readFile(filePath);
|
278
|
-
const regex = new RegExp(
|
279
|
-
/(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source+
|
280
|
-
/([^\n]*)/.source
|
281
|
-
,"g")
|
282
|
-
let match:RegExpExecArray|null;
|
283
|
-
let hasMatch = false;
|
284
|
-
while(match = regex.exec(fileText)){
|
285
|
-
const id = match[4];
|
286
|
-
const prefix = match[1];
|
287
|
-
const content = match[6];
|
288
|
-
const inent = match[2];
|
289
|
-
const comment = match[3];
|
290
|
-
|
291
|
-
const idregex = typeof commentId === "string"
|
292
|
-
? literalRegex(commentId) : commentId;
|
293
|
-
let idmatch = idregex.exec(id);
|
294
|
-
if(idmatch==null) continue;
|
295
|
-
hasMatch=true;
|
296
|
-
const ol = fileText.length;
|
297
|
-
const parseCode = await parseCodeText(codeText,{
|
298
|
-
matchId :idmatch[0],
|
299
|
-
execArr :idmatch,
|
300
|
-
text :dedent(content),
|
301
|
-
inent ,
|
302
|
-
filePath
|
303
|
-
});
|
304
|
-
if(parseCode.includes('\n')){
|
305
|
-
SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
|
306
|
-
return;
|
307
|
-
}
|
308
|
-
fileText = fileText.replace(match[0], `${prefix}${inent}${comment}\n${parseCode}`);
|
309
|
-
regex.lastIndex += fileText.length - ol;
|
310
|
-
}
|
311
|
-
if(hasMatch)
|
312
|
-
await fs.promises.writeFile(filePath, fileText, 'utf-8');
|
313
|
-
else if(!opt?.glob) SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
|
314
|
-
}
|
315
|
-
plist.push(UtilFunc.queueProc(path.normalize(filePath),queuefunc))
|
316
|
-
}
|
317
|
-
await Promise.all(plist);
|
318
|
-
}
|
319
|
-
/**将codeText写入对应文件 不存在则创建
|
320
|
-
* @param codeText - 文本
|
321
|
-
* @param opt - 可选参数
|
322
|
-
* @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
|
323
|
-
* @param opt.glob - 使用glob匹配而非文件路径
|
324
|
-
*/
|
325
|
-
export async function fileMacro(codeText:string|((opt:Omit<CodeTextOpt,'ident'|'matchId'|'execArr'>)=>string|Promise<string>),opt?:MacroOpt){
|
326
|
-
const plist:Promise<void>[] = [];
|
327
|
-
const filePaths = await parseMacroPaths(opt);
|
328
|
-
for(const filePath of filePaths){
|
329
|
-
const queuefunc = async ()=>{
|
330
|
-
await UtilFT.ensurePathExists(filePath);
|
331
|
-
const text = await readFile(filePath);
|
332
|
-
const parseCode = await parseCodeText(codeText,{
|
333
|
-
matchId:'',
|
334
|
-
execArr:/''/.exec('')!,
|
335
|
-
text,
|
336
|
-
inent:'',
|
337
|
-
filePath
|
338
|
-
});
|
339
|
-
await fs.promises.writeFile(filePath, parseCode, 'utf-8');
|
340
|
-
}
|
341
|
-
plist.push(UtilFunc.queueProc(path.normalize(filePath),queuefunc))
|
342
|
-
}
|
343
|
-
await Promise.all(plist);
|
344
|
-
}
|
345
|
-
}
|
package/src/UtilInterface.ts
DELETED
package/src/UtilMacro.ts
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
import { UtilFT } from "@zwa73/utils";
|
2
|
-
import { commentMacro } from "./QuickFunc"
|
3
|
-
import path from "pathe";
|
4
|
-
|
5
|
-
|
6
|
-
export namespace UtilMacro{
|
7
|
-
/**根据注释批量生成导出
|
8
|
-
* @param glob - 应用的golb
|
9
|
-
* @example
|
10
|
-
*/
|
11
|
-
export function exportComment(glob:string){
|
12
|
-
commentMacro(/export (\S*)/,async ({filePath,matchId,execArr})=>{
|
13
|
-
const basedir = path.dirname(filePath);
|
14
|
-
const result = (await UtilFT.fileSearchGlob(basedir,execArr[1]))
|
15
|
-
.map((file)=>path.relative(basedir,file))
|
16
|
-
.map((file)=>path.parse(file).name)
|
17
|
-
.filter((file)=>file!=path.parse(filePath).name)
|
18
|
-
.map((file)=>`export * from './${file}'`)
|
19
|
-
.join(';');
|
20
|
-
return result.length>0? `${result};` : result;
|
21
|
-
},{glob:true,filePath:glob});
|
22
|
-
}
|
23
|
-
}
|
package/src/index.ts
DELETED
package/test.js
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
const {UtilFT} = require('@zwa73/utils')
|
10
|
-
const fs = require('fs');
|
11
|
-
const path = require('path');
|
12
|
-
async function main(){
|
13
|
-
const root = __filename;
|
14
|
-
const dirpath = path.join(__dirname,'src');
|
15
|
-
|
16
|
-
const ts = await fs.promises.readdir(dirpath,{withFileTypes:true})
|
17
|
-
ts//?
|
18
|
-
const list = await UtilFT.fileSearchRegex(dirpath, '')
|
19
|
-
.map((filePath)=>path.relative(dirpath, filePath));
|
20
|
-
|
21
|
-
console.log(
|
22
|
-
path.parse(root),
|
23
|
-
path.basename(root)
|
24
|
-
);
|
25
|
-
list.forEach((file)=>{
|
26
|
-
console.log(file)
|
27
|
-
})
|
28
|
-
}
|
29
|
-
main();
|
package/tsconfig.compile.json
DELETED
package/tsconfig.json
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"compilerOptions": {
|
3
|
-
"allowJs": true,
|
4
|
-
"strict": true,
|
5
|
-
"target": "ES2022",
|
6
|
-
"module": "commonjs",
|
7
|
-
"moduleResolution": "node",
|
8
|
-
"esModuleInterop": true,
|
9
|
-
"outDir": "./dist",
|
10
|
-
"declaration": true,
|
11
|
-
"baseUrl": ".",
|
12
|
-
"emitDecoratorMetadata": true,
|
13
|
-
"experimentalDecorators": true,
|
14
|
-
"paths": {
|
15
|
-
"@/src/*" : ["./src/*"],
|
16
|
-
"@/*" : ["./*"],
|
17
|
-
"@" : ["./src/index"]
|
18
|
-
}
|
19
|
-
},
|
20
|
-
"include": ["./src/**/*.ts", "./src/**/*.js","./jest/**/*.ts"],
|
21
|
-
"exclude": ["./node_modules/**/*"]
|
22
|
-
}
|