ai-worktool 1.0.0

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.
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.parseTsFile = parseTsFile;
40
+ exports.createTsConfigFile = createTsConfigFile;
41
+ const typescript_1 = __importDefault(require("typescript"));
42
+ const fs = __importStar(require("fs/promises")); // 使用promises版本的fs
43
+ /**
44
+ * 创建TypeScript源文件
45
+ * @param filePath 要创建源文件的文件路径
46
+ * @returns 解析为ts.SourceFile的Promise对象
47
+ */
48
+ async function createSourceFile(filePath) {
49
+ const fileContent = await fs.readFile(filePath, 'utf8');
50
+ return typescript_1.default.createSourceFile(filePath, fileContent, typescript_1.default.ScriptTarget.Latest, true);
51
+ }
52
+ /**
53
+ * 获取节点在源文件中的行号
54
+ * @param sourceFile TypeScript源文件对象
55
+ * @param position 节点在源文件中的位置索引
56
+ * @returns 对应的行号(从1开始计数)
57
+ */
58
+ function getLineNumber(sourceFile, position) {
59
+ return sourceFile.getLineAndCharacterOfPosition(position).line + 1;
60
+ }
61
+ /**
62
+ * 获取参数的JSDoc注释描述
63
+ * @param paramName 参数名称
64
+ * @param jsDoc JSDoc注释对象
65
+ * @param sourceFile TypeScript源文件对象
66
+ * @returns 参数的描述信息,若不存在则返回undefined
67
+ */
68
+ function getParameterDescription(paramName, jsDoc, sourceFile) {
69
+ if (!jsDoc || !jsDoc.tags) {
70
+ return undefined;
71
+ }
72
+ const paramTag = jsDoc.tags.find((tag) => tag.tagName.getText(sourceFile) === 'param' &&
73
+ tag.name?.getText(sourceFile) === paramName);
74
+ return paramTag?.comment?.toString();
75
+ }
76
+ /**
77
+ * 解析参数信息
78
+ * @param param 参数声明节点
79
+ * @param sourceFile TypeScript源文件对象
80
+ * @param jsDoc JSDoc注释对象
81
+ * @returns 包含参数详细信息的ParameterInfo对象
82
+ */
83
+ function parseParameter(param, sourceFile, jsDoc) {
84
+ const paramName = param.name.getText(sourceFile);
85
+ const paramType = param.type ? param.type.getText(sourceFile) : 'any';
86
+ const isOptional = !!param.questionToken || !!param.initializer;
87
+ const description = getParameterDescription(paramName, jsDoc, sourceFile);
88
+ return {
89
+ name: paramName,
90
+ type: paramType,
91
+ isOptional,
92
+ description
93
+ };
94
+ }
95
+ /**
96
+ * 获取节点的源代码
97
+ * @param node TypeScript AST节点
98
+ * @param sourceFile TypeScript源文件对象
99
+ * @returns 节点对应的源代码字符串
100
+ */
101
+ function getNodeSourceCode(node, sourceFile) {
102
+ return sourceFile.getFullText().substring(node.getFullStart(), node.getEnd());
103
+ }
104
+ /**
105
+ * 获取节点的JSDoc注释
106
+ * @param node TypeScript AST节点
107
+ * @returns 节点的JSDoc注释数组,若不存在则返回undefined
108
+ */
109
+ function getJsDocComment(node) {
110
+ return node.jsDoc;
111
+ }
112
+ /**
113
+ * 检查节点是否在导出的模块中
114
+ * @param node TypeScript AST节点
115
+ * @returns 若节点在导出的模块中则返回true,否则返回false
116
+ */
117
+ function isInExportedModule(node) {
118
+ let current = node.parent;
119
+ while (current) {
120
+ if (typescript_1.default.isModuleDeclaration(current) && current.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword)) {
121
+ return true;
122
+ }
123
+ current = current.parent;
124
+ }
125
+ return false;
126
+ }
127
+ /**
128
+ * 解析TypeScript文件,提取导入信息和导出函数信息
129
+ * @param filePath 要解析的TypeScript文件路径
130
+ * @returns 解析结果的Promise对象,包含文件路径、导入信息和导出函数信息
131
+ */
132
+ async function parseTsFile(filePath) {
133
+ const sourceFile = await createSourceFile(filePath);
134
+ const result = {
135
+ filePath,
136
+ imports: [],
137
+ exportedFunctions: []
138
+ };
139
+ /**
140
+ * 访问AST节点并提取信息
141
+ * @param node 当前访问的AST节点
142
+ */
143
+ function visitNode(node) {
144
+ // 处理导入语句
145
+ if (typescript_1.default.isImportDeclaration(node)) {
146
+ const moduleSpecifier = node.moduleSpecifier.text;
147
+ const importInfo = {
148
+ moduleSpecifier,
149
+ namedImports: []
150
+ };
151
+ // 处理命名导入
152
+ if (node.importClause?.namedBindings && typescript_1.default.isNamedImports(node.importClause.namedBindings)) {
153
+ importInfo.namedImports = node.importClause.namedBindings.elements.map((element) => element.name.text);
154
+ }
155
+ // 处理默认导入
156
+ if (node.importClause?.name) {
157
+ importInfo.defaultImport = node.importClause.name.text;
158
+ }
159
+ // 处理命名空间导入
160
+ if (node.importClause?.namedBindings && typescript_1.default.isNamespaceImport(node.importClause.namedBindings)) {
161
+ importInfo.namespaceImport = node.importClause.namedBindings.name.text;
162
+ }
163
+ result.imports.push(importInfo);
164
+ }
165
+ // 处理导出函数
166
+ if (typescript_1.default.isFunctionDeclaration(node) &&
167
+ (node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword) || isInExportedModule(node))) {
168
+ if (node.name) {
169
+ const jsDocs = getJsDocComment(node);
170
+ const mainJsDoc = jsDocs?.[0];
171
+ const functionInfo = {
172
+ name: node.name.text,
173
+ parameters: node.parameters.map((param) => parseParameter(param, sourceFile, mainJsDoc)),
174
+ returnType: node.type ? node.type.getText(sourceFile) : 'void',
175
+ isAsync: !!node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.AsyncKeyword),
176
+ isGenerator: !!node.asteriskToken,
177
+ sourceCode: getNodeSourceCode(node, sourceFile),
178
+ startLine: getLineNumber(sourceFile, node.getStart()),
179
+ endLine: getLineNumber(sourceFile, node.getEnd()),
180
+ description: mainJsDoc?.comment?.toString(),
181
+ example: mainJsDoc?.tags?.find((tag) => tag.tagName.text === 'example')?.comment?.toString()
182
+ };
183
+ result.exportedFunctions.push(functionInfo);
184
+ }
185
+ }
186
+ // 处理导出的箭头函数
187
+ if (typescript_1.default.isVariableDeclaration(node) &&
188
+ node.initializer &&
189
+ typescript_1.default.isArrowFunction(node.initializer) &&
190
+ node.parent &&
191
+ typescript_1.default.isVariableDeclarationList(node.parent) &&
192
+ node.parent.parent &&
193
+ typescript_1.default.isVariableStatement(node.parent.parent) &&
194
+ node.parent.parent.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword)) {
195
+ if (node.name && typescript_1.default.isIdentifier(node.name)) {
196
+ const arrowFunction = node.initializer;
197
+ const jsDocs = getJsDocComment(node.parent.parent);
198
+ const mainJsDoc = jsDocs?.[0];
199
+ const functionInfo = {
200
+ name: node.name.text,
201
+ parameters: arrowFunction.parameters.map((param) => parseParameter(param, sourceFile, mainJsDoc)),
202
+ returnType: arrowFunction.type ? arrowFunction.type.getText(sourceFile) : 'void',
203
+ isAsync: !!arrowFunction.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.AsyncKeyword),
204
+ isGenerator: false, // 箭头函数不能是生成器
205
+ sourceCode: getNodeSourceCode(arrowFunction, sourceFile),
206
+ startLine: getLineNumber(sourceFile, arrowFunction.getStart()),
207
+ endLine: getLineNumber(sourceFile, arrowFunction.getEnd()),
208
+ description: mainJsDoc?.comment?.toString()
209
+ };
210
+ result.exportedFunctions.push(functionInfo);
211
+ }
212
+ }
213
+ // 递归访问子节点
214
+ typescript_1.default.forEachChild(node, (child) => visitNode(child));
215
+ }
216
+ // 开始访问节点
217
+ visitNode(sourceFile);
218
+ return result;
219
+ }
220
+ /**
221
+ * 创建tsconfig.json文件
222
+ * @param outputPath tsconfig.json文件的输出路径(包含文件名)
223
+ * @param compilerOptions TypeScript编译器选项
224
+ * @param include 需要包含的文件路径数组,默认为空数组,多个路径逗号分隔,例如 src/**\/*.ts,tests/**\/*.spec.ts
225
+ * @param exclude 需要排除的文件路径数组,默认为空数组,多个路径逗号分隔,例如 src/**\/*.js,tests/**\/*.spec.js
226
+ * @returns 当文件创建成功时解析的Promise
227
+ * @throws {Error} 如果文件写入过程中发生错误则抛出异常
228
+ */
229
+ async function createTsConfigFile(outputPath, compilerOptions, include = [], exclude = []) {
230
+ const tsconfigContent = {
231
+ compilerOptions: typeof compilerOptions === 'string' ? JSON.parse(compilerOptions) : compilerOptions,
232
+ include: Array.isArray(include) ? include : include?.split(','),
233
+ exclude: Array.isArray(exclude) ? exclude : exclude?.split(',')
234
+ };
235
+ try {
236
+ await fs.writeFile(outputPath, JSON.stringify(tsconfigContent, null, 2), 'utf8');
237
+ }
238
+ catch (error) {
239
+ throw new Error(`创建tsconfig.json失败: ${error.message}`);
240
+ }
241
+ }
242
+ //# sourceMappingURL=typescript.js.map
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createVitestConfigFile = createVitestConfigFile;
37
+ exports.runVitestTests = runVitestTests;
38
+ const child_process_1 = require("child_process");
39
+ const fs = __importStar(require("fs/promises"));
40
+ const path = __importStar(require("path"));
41
+ /**
42
+ * 创建 Vitest 配置文件
43
+ */
44
+ async function createVitestConfigFile(configPath, options = {}) {
45
+ try {
46
+ await fs.access(configPath);
47
+ return null;
48
+ }
49
+ catch {
50
+ // 继续创建文件
51
+ }
52
+ options = typeof options === 'string' ? JSON.parse(options) : options;
53
+ const defaultConfig = {
54
+ include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],
55
+ exclude: ['node_modules/**', 'dist/**'],
56
+ extensions: ['js', 'ts', 'jsx', 'tsx'],
57
+ coverage: {
58
+ enabled: true,
59
+ reporter: ['text', 'lcov', 'json-summary'],
60
+ reportsDirectory: 'coverage',
61
+ include: ['src/**/*.{js,ts,jsx,tsx}'],
62
+ exclude: ['**/*.d.ts', 'src/mocks/**', 'node_modules/**']
63
+ }
64
+ };
65
+ const mergedConfig = { ...defaultConfig, ...options };
66
+ const configContent = `export default ${JSON.stringify(mergedConfig, null, 2)};\n`;
67
+ const dirPath = path.dirname(configPath);
68
+ await fs.mkdir(dirPath, { recursive: true });
69
+ await fs.writeFile(configPath, configContent, 'utf-8');
70
+ return configPath;
71
+ }
72
+ /**
73
+ * 执行 Vitest 测试
74
+ */
75
+ async function runVitestTests(projectRoot, coverageDir = 'coverage', configPath) {
76
+ coverageDir = coverageDir || 'coverage';
77
+ return new Promise((resolve, reject) => {
78
+ const now = Date.now();
79
+ const testResultsFile = path.join(projectRoot, coverageDir, 'test-results.json');
80
+ const vitestCommand = configPath
81
+ ? `npx vitest run --coverage --reporter=json --outputFile="${testResultsFile}" --config ${configPath}`
82
+ : `npx vitest run --coverage --reporter=json --outputFile="${testResultsFile}"`;
83
+ const childProcess = (0, child_process_1.exec)(vitestCommand, { cwd: projectRoot, encoding: 'utf-8' });
84
+ let stdout = '';
85
+ let stderr = '';
86
+ childProcess.stdout?.on('data', (data) => (stdout += data));
87
+ childProcess.stderr?.on('data', (data) => (stderr += data));
88
+ childProcess.on('close', async (code) => {
89
+ const state = await getTestResultsState(projectRoot, coverageDir);
90
+ resolve({
91
+ testResultsFile,
92
+ success: code === 0,
93
+ noTestsFound: stderr.includes('No tests found'),
94
+ exitCode: code,
95
+ stdout,
96
+ stderr
97
+ });
98
+ });
99
+ childProcess.on('error', (err) => reject(err));
100
+ });
101
+ }
102
+ async function getTestResultsState(projectRoot, coverageDir) {
103
+ const testResultsPath = path.join(projectRoot, coverageDir, 'test-results.json');
104
+ return (await fileExists(testResultsPath)) ? fs.stat(testResultsPath) : null;
105
+ }
106
+ async function fileExists(path) {
107
+ try {
108
+ await fs.access(path);
109
+ return true;
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ //# sourceMappingURL=vitest.js.map