@aiready/core 0.5.5 → 0.7.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.
- package/dist/index.d.mts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +172 -2
- package/dist/index.mjs +169 -2
- package/package.json +16 -12
package/dist/index.d.mts
CHANGED
|
@@ -54,6 +54,9 @@ interface AIReadyConfig {
|
|
|
54
54
|
focus?: 'fragmentation' | 'cohesion' | 'depth' | 'all';
|
|
55
55
|
includeNodeModules?: boolean;
|
|
56
56
|
maxResults?: number;
|
|
57
|
+
domainKeywords?: string[];
|
|
58
|
+
domainPatterns?: string[];
|
|
59
|
+
pathDomainMap?: Record<string, string>;
|
|
57
60
|
};
|
|
58
61
|
};
|
|
59
62
|
output?: {
|
|
@@ -76,11 +79,45 @@ interface Report {
|
|
|
76
79
|
};
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
declare const DEFAULT_EXCLUDE: string[];
|
|
79
83
|
declare function scanFiles(options: ScanOptions): Promise<string[]>;
|
|
80
84
|
declare function readFileContent(filePath: string): Promise<string>;
|
|
81
85
|
declare function getFileExtension(filePath: string): string;
|
|
82
86
|
declare function isSourceFile(filePath: string): boolean;
|
|
83
87
|
|
|
88
|
+
interface ExportWithImports {
|
|
89
|
+
name: string;
|
|
90
|
+
type: 'function' | 'class' | 'const' | 'type' | 'interface' | 'default';
|
|
91
|
+
imports: string[];
|
|
92
|
+
dependencies: string[];
|
|
93
|
+
typeReferences: string[];
|
|
94
|
+
loc?: {
|
|
95
|
+
start: {
|
|
96
|
+
line: number;
|
|
97
|
+
column: number;
|
|
98
|
+
};
|
|
99
|
+
end: {
|
|
100
|
+
line: number;
|
|
101
|
+
column: number;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
interface FileImport {
|
|
106
|
+
source: string;
|
|
107
|
+
specifiers: string[];
|
|
108
|
+
isTypeOnly: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse TypeScript/JavaScript file and extract exports with their import dependencies
|
|
112
|
+
*/
|
|
113
|
+
declare function parseFileExports(code: string, filePath: string): {
|
|
114
|
+
exports: ExportWithImports[];
|
|
115
|
+
imports: FileImport[];
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Calculate import-based similarity between two exports (Jaccard index)
|
|
119
|
+
*/
|
|
120
|
+
declare function calculateImportSimilarity(export1: ExportWithImports, export2: ExportWithImports): number;
|
|
84
121
|
interface ASTNode {
|
|
85
122
|
type: string;
|
|
86
123
|
loc?: {
|
|
@@ -144,4 +181,4 @@ declare function handleCLIError(error: unknown, commandName: string): never;
|
|
|
144
181
|
*/
|
|
145
182
|
declare function getElapsedTime(startTime: number): string;
|
|
146
183
|
|
|
147
|
-
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, estimateTokens, extractFunctions, extractImports, getElapsedTime, getFileExtension, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, parseCode, readFileContent, resolveOutputPath, scanFiles };
|
|
184
|
+
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, DEFAULT_EXCLUDE, type ExportWithImports, type FileImport, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, calculateImportSimilarity, estimateTokens, extractFunctions, extractImports, getElapsedTime, getFileExtension, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, parseCode, parseFileExports, readFileContent, resolveOutputPath, scanFiles };
|
package/dist/index.d.ts
CHANGED
|
@@ -54,6 +54,9 @@ interface AIReadyConfig {
|
|
|
54
54
|
focus?: 'fragmentation' | 'cohesion' | 'depth' | 'all';
|
|
55
55
|
includeNodeModules?: boolean;
|
|
56
56
|
maxResults?: number;
|
|
57
|
+
domainKeywords?: string[];
|
|
58
|
+
domainPatterns?: string[];
|
|
59
|
+
pathDomainMap?: Record<string, string>;
|
|
57
60
|
};
|
|
58
61
|
};
|
|
59
62
|
output?: {
|
|
@@ -76,11 +79,45 @@ interface Report {
|
|
|
76
79
|
};
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
declare const DEFAULT_EXCLUDE: string[];
|
|
79
83
|
declare function scanFiles(options: ScanOptions): Promise<string[]>;
|
|
80
84
|
declare function readFileContent(filePath: string): Promise<string>;
|
|
81
85
|
declare function getFileExtension(filePath: string): string;
|
|
82
86
|
declare function isSourceFile(filePath: string): boolean;
|
|
83
87
|
|
|
88
|
+
interface ExportWithImports {
|
|
89
|
+
name: string;
|
|
90
|
+
type: 'function' | 'class' | 'const' | 'type' | 'interface' | 'default';
|
|
91
|
+
imports: string[];
|
|
92
|
+
dependencies: string[];
|
|
93
|
+
typeReferences: string[];
|
|
94
|
+
loc?: {
|
|
95
|
+
start: {
|
|
96
|
+
line: number;
|
|
97
|
+
column: number;
|
|
98
|
+
};
|
|
99
|
+
end: {
|
|
100
|
+
line: number;
|
|
101
|
+
column: number;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
interface FileImport {
|
|
106
|
+
source: string;
|
|
107
|
+
specifiers: string[];
|
|
108
|
+
isTypeOnly: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse TypeScript/JavaScript file and extract exports with their import dependencies
|
|
112
|
+
*/
|
|
113
|
+
declare function parseFileExports(code: string, filePath: string): {
|
|
114
|
+
exports: ExportWithImports[];
|
|
115
|
+
imports: FileImport[];
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Calculate import-based similarity between two exports (Jaccard index)
|
|
119
|
+
*/
|
|
120
|
+
declare function calculateImportSimilarity(export1: ExportWithImports, export2: ExportWithImports): number;
|
|
84
121
|
interface ASTNode {
|
|
85
122
|
type: string;
|
|
86
123
|
loc?: {
|
|
@@ -144,4 +181,4 @@ declare function handleCLIError(error: unknown, commandName: string): never;
|
|
|
144
181
|
*/
|
|
145
182
|
declare function getElapsedTime(startTime: number): string;
|
|
146
183
|
|
|
147
|
-
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, estimateTokens, extractFunctions, extractImports, getElapsedTime, getFileExtension, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, parseCode, readFileContent, resolveOutputPath, scanFiles };
|
|
184
|
+
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, DEFAULT_EXCLUDE, type ExportWithImports, type FileImport, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, calculateImportSimilarity, estimateTokens, extractFunctions, extractImports, getElapsedTime, getFileExtension, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, parseCode, parseFileExports, readFileContent, resolveOutputPath, scanFiles };
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
|
|
24
|
+
calculateImportSimilarity: () => calculateImportSimilarity,
|
|
23
25
|
estimateTokens: () => estimateTokens,
|
|
24
26
|
extractFunctions: () => extractFunctions,
|
|
25
27
|
extractImports: () => extractImports,
|
|
@@ -32,6 +34,7 @@ __export(index_exports, {
|
|
|
32
34
|
loadMergedConfig: () => loadMergedConfig,
|
|
33
35
|
mergeConfigWithDefaults: () => mergeConfigWithDefaults,
|
|
34
36
|
parseCode: () => parseCode,
|
|
37
|
+
parseFileExports: () => parseFileExports,
|
|
35
38
|
readFileContent: () => readFileContent,
|
|
36
39
|
resolveOutputPath: () => resolveOutputPath,
|
|
37
40
|
scanFiles: () => scanFiles
|
|
@@ -85,11 +88,12 @@ async function scanFiles(options) {
|
|
|
85
88
|
const {
|
|
86
89
|
rootDir,
|
|
87
90
|
include = ["**/*.{ts,tsx,js,jsx,py,java}"],
|
|
88
|
-
exclude
|
|
91
|
+
exclude
|
|
89
92
|
} = options;
|
|
93
|
+
const finalExclude = exclude ? [.../* @__PURE__ */ new Set([...DEFAULT_EXCLUDE, ...exclude])] : DEFAULT_EXCLUDE;
|
|
90
94
|
const files = await (0, import_glob.glob)(include, {
|
|
91
95
|
cwd: rootDir,
|
|
92
|
-
ignore:
|
|
96
|
+
ignore: finalExclude,
|
|
93
97
|
absolute: true
|
|
94
98
|
});
|
|
95
99
|
return files;
|
|
@@ -106,6 +110,169 @@ function isSourceFile(filePath) {
|
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
// src/utils/ast-parser.ts
|
|
113
|
+
var import_typescript_estree = require("@typescript-eslint/typescript-estree");
|
|
114
|
+
function parseFileExports(code, filePath) {
|
|
115
|
+
try {
|
|
116
|
+
const ast = (0, import_typescript_estree.parse)(code, {
|
|
117
|
+
loc: true,
|
|
118
|
+
range: true,
|
|
119
|
+
jsx: filePath.endsWith(".tsx") || filePath.endsWith(".jsx"),
|
|
120
|
+
filePath
|
|
121
|
+
});
|
|
122
|
+
const imports = extractFileImports(ast);
|
|
123
|
+
const exports2 = extractExportsWithDependencies(ast, imports);
|
|
124
|
+
return { exports: exports2, imports };
|
|
125
|
+
} catch (error) {
|
|
126
|
+
return { exports: [], imports: [] };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function extractFileImports(ast) {
|
|
130
|
+
const imports = [];
|
|
131
|
+
for (const node of ast.body) {
|
|
132
|
+
if (node.type === "ImportDeclaration") {
|
|
133
|
+
const source = node.source.value;
|
|
134
|
+
const specifiers = [];
|
|
135
|
+
const isTypeOnly = node.importKind === "type";
|
|
136
|
+
for (const spec of node.specifiers) {
|
|
137
|
+
if (spec.type === "ImportSpecifier") {
|
|
138
|
+
const imported = spec.imported;
|
|
139
|
+
const importName = imported.type === "Identifier" ? imported.name : imported.value;
|
|
140
|
+
specifiers.push(importName);
|
|
141
|
+
} else if (spec.type === "ImportDefaultSpecifier") {
|
|
142
|
+
specifiers.push("default");
|
|
143
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
144
|
+
specifiers.push("*");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
imports.push({ source, specifiers, isTypeOnly });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return imports;
|
|
151
|
+
}
|
|
152
|
+
function extractExportsWithDependencies(ast, fileImports) {
|
|
153
|
+
const exports2 = [];
|
|
154
|
+
const importedNames = new Set(fileImports.flatMap((imp) => imp.specifiers));
|
|
155
|
+
for (const node of ast.body) {
|
|
156
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
157
|
+
if (node.declaration) {
|
|
158
|
+
const exportNodes = extractFromDeclaration(node.declaration);
|
|
159
|
+
for (const exp of exportNodes) {
|
|
160
|
+
const usedImports = findUsedImports(node.declaration, importedNames);
|
|
161
|
+
const typeReferences = extractTypeReferences(node.declaration);
|
|
162
|
+
exports2.push({
|
|
163
|
+
...exp,
|
|
164
|
+
imports: usedImports,
|
|
165
|
+
dependencies: [],
|
|
166
|
+
typeReferences,
|
|
167
|
+
loc: node.loc
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
172
|
+
const usedImports = findUsedImports(node.declaration, importedNames);
|
|
173
|
+
const typeReferences = extractTypeReferences(node.declaration);
|
|
174
|
+
exports2.push({
|
|
175
|
+
name: "default",
|
|
176
|
+
type: "default",
|
|
177
|
+
imports: usedImports,
|
|
178
|
+
dependencies: [],
|
|
179
|
+
typeReferences,
|
|
180
|
+
loc: node.loc
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return exports2;
|
|
185
|
+
}
|
|
186
|
+
function extractFromDeclaration(declaration) {
|
|
187
|
+
const results = [];
|
|
188
|
+
if (declaration.type === "FunctionDeclaration" && "id" in declaration && declaration.id) {
|
|
189
|
+
results.push({ name: declaration.id.name, type: "function" });
|
|
190
|
+
} else if (declaration.type === "ClassDeclaration" && "id" in declaration && declaration.id) {
|
|
191
|
+
results.push({ name: declaration.id.name, type: "class" });
|
|
192
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
193
|
+
for (const declarator of declaration.declarations) {
|
|
194
|
+
if (declarator.id.type === "Identifier") {
|
|
195
|
+
results.push({ name: declarator.id.name, type: "const" });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} else if (declaration.type === "TSTypeAliasDeclaration") {
|
|
199
|
+
results.push({ name: declaration.id.name, type: "type" });
|
|
200
|
+
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
201
|
+
results.push({ name: declaration.id.name, type: "interface" });
|
|
202
|
+
}
|
|
203
|
+
return results;
|
|
204
|
+
}
|
|
205
|
+
function findUsedImports(node, importedNames) {
|
|
206
|
+
const usedImports = /* @__PURE__ */ new Set();
|
|
207
|
+
function visit(n) {
|
|
208
|
+
if (n.type === "Identifier" && importedNames.has(n.name)) {
|
|
209
|
+
usedImports.add(n.name);
|
|
210
|
+
}
|
|
211
|
+
for (const key in n) {
|
|
212
|
+
const value = n[key];
|
|
213
|
+
if (value && typeof value === "object") {
|
|
214
|
+
if (Array.isArray(value)) {
|
|
215
|
+
value.forEach((child) => {
|
|
216
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
217
|
+
visit(child);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
} else if ("type" in value) {
|
|
221
|
+
visit(value);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
visit(node);
|
|
227
|
+
return Array.from(usedImports);
|
|
228
|
+
}
|
|
229
|
+
function calculateImportSimilarity(export1, export2) {
|
|
230
|
+
if (export1.imports.length === 0 && export2.imports.length === 0) {
|
|
231
|
+
return 1;
|
|
232
|
+
}
|
|
233
|
+
const set1 = new Set(export1.imports);
|
|
234
|
+
const set2 = new Set(export2.imports);
|
|
235
|
+
const intersection = new Set([...set1].filter((x) => set2.has(x)));
|
|
236
|
+
const union = /* @__PURE__ */ new Set([...set1, ...set2]);
|
|
237
|
+
return intersection.size / union.size;
|
|
238
|
+
}
|
|
239
|
+
function extractTypeReferences(node) {
|
|
240
|
+
const types = /* @__PURE__ */ new Set();
|
|
241
|
+
function visit(n) {
|
|
242
|
+
if (!n || typeof n !== "object") return;
|
|
243
|
+
if (n.type === "TSTypeReference" && n.typeName) {
|
|
244
|
+
if (n.typeName.type === "Identifier") {
|
|
245
|
+
types.add(n.typeName.name);
|
|
246
|
+
} else if (n.typeName.type === "TSQualifiedName") {
|
|
247
|
+
let current = n.typeName;
|
|
248
|
+
while (current.type === "TSQualifiedName") {
|
|
249
|
+
if (current.right?.type === "Identifier") {
|
|
250
|
+
types.add(current.right.name);
|
|
251
|
+
}
|
|
252
|
+
current = current.left;
|
|
253
|
+
}
|
|
254
|
+
if (current.type === "Identifier") {
|
|
255
|
+
types.add(current.name);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (n.type === "TSInterfaceHeritage" && n.expression) {
|
|
260
|
+
if (n.expression.type === "Identifier") {
|
|
261
|
+
types.add(n.expression.name);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
for (const key of Object.keys(n)) {
|
|
265
|
+
const value = n[key];
|
|
266
|
+
if (Array.isArray(value)) {
|
|
267
|
+
value.forEach(visit);
|
|
268
|
+
} else if (value && typeof value === "object") {
|
|
269
|
+
visit(value);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
visit(node);
|
|
274
|
+
return Array.from(types);
|
|
275
|
+
}
|
|
109
276
|
function parseCode(code, language) {
|
|
110
277
|
return null;
|
|
111
278
|
}
|
|
@@ -235,6 +402,8 @@ function getElapsedTime(startTime) {
|
|
|
235
402
|
}
|
|
236
403
|
// Annotate the CommonJS export names for ESM import in node:
|
|
237
404
|
0 && (module.exports = {
|
|
405
|
+
DEFAULT_EXCLUDE,
|
|
406
|
+
calculateImportSimilarity,
|
|
238
407
|
estimateTokens,
|
|
239
408
|
extractFunctions,
|
|
240
409
|
extractImports,
|
|
@@ -247,6 +416,7 @@ function getElapsedTime(startTime) {
|
|
|
247
416
|
loadMergedConfig,
|
|
248
417
|
mergeConfigWithDefaults,
|
|
249
418
|
parseCode,
|
|
419
|
+
parseFileExports,
|
|
250
420
|
readFileContent,
|
|
251
421
|
resolveOutputPath,
|
|
252
422
|
scanFiles
|
package/dist/index.mjs
CHANGED
|
@@ -52,11 +52,12 @@ async function scanFiles(options) {
|
|
|
52
52
|
const {
|
|
53
53
|
rootDir,
|
|
54
54
|
include = ["**/*.{ts,tsx,js,jsx,py,java}"],
|
|
55
|
-
exclude
|
|
55
|
+
exclude
|
|
56
56
|
} = options;
|
|
57
|
+
const finalExclude = exclude ? [.../* @__PURE__ */ new Set([...DEFAULT_EXCLUDE, ...exclude])] : DEFAULT_EXCLUDE;
|
|
57
58
|
const files = await glob(include, {
|
|
58
59
|
cwd: rootDir,
|
|
59
|
-
ignore:
|
|
60
|
+
ignore: finalExclude,
|
|
60
61
|
absolute: true
|
|
61
62
|
});
|
|
62
63
|
return files;
|
|
@@ -73,6 +74,169 @@ function isSourceFile(filePath) {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// src/utils/ast-parser.ts
|
|
77
|
+
import { parse } from "@typescript-eslint/typescript-estree";
|
|
78
|
+
function parseFileExports(code, filePath) {
|
|
79
|
+
try {
|
|
80
|
+
const ast = parse(code, {
|
|
81
|
+
loc: true,
|
|
82
|
+
range: true,
|
|
83
|
+
jsx: filePath.endsWith(".tsx") || filePath.endsWith(".jsx"),
|
|
84
|
+
filePath
|
|
85
|
+
});
|
|
86
|
+
const imports = extractFileImports(ast);
|
|
87
|
+
const exports = extractExportsWithDependencies(ast, imports);
|
|
88
|
+
return { exports, imports };
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return { exports: [], imports: [] };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function extractFileImports(ast) {
|
|
94
|
+
const imports = [];
|
|
95
|
+
for (const node of ast.body) {
|
|
96
|
+
if (node.type === "ImportDeclaration") {
|
|
97
|
+
const source = node.source.value;
|
|
98
|
+
const specifiers = [];
|
|
99
|
+
const isTypeOnly = node.importKind === "type";
|
|
100
|
+
for (const spec of node.specifiers) {
|
|
101
|
+
if (spec.type === "ImportSpecifier") {
|
|
102
|
+
const imported = spec.imported;
|
|
103
|
+
const importName = imported.type === "Identifier" ? imported.name : imported.value;
|
|
104
|
+
specifiers.push(importName);
|
|
105
|
+
} else if (spec.type === "ImportDefaultSpecifier") {
|
|
106
|
+
specifiers.push("default");
|
|
107
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
108
|
+
specifiers.push("*");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
imports.push({ source, specifiers, isTypeOnly });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return imports;
|
|
115
|
+
}
|
|
116
|
+
function extractExportsWithDependencies(ast, fileImports) {
|
|
117
|
+
const exports = [];
|
|
118
|
+
const importedNames = new Set(fileImports.flatMap((imp) => imp.specifiers));
|
|
119
|
+
for (const node of ast.body) {
|
|
120
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
121
|
+
if (node.declaration) {
|
|
122
|
+
const exportNodes = extractFromDeclaration(node.declaration);
|
|
123
|
+
for (const exp of exportNodes) {
|
|
124
|
+
const usedImports = findUsedImports(node.declaration, importedNames);
|
|
125
|
+
const typeReferences = extractTypeReferences(node.declaration);
|
|
126
|
+
exports.push({
|
|
127
|
+
...exp,
|
|
128
|
+
imports: usedImports,
|
|
129
|
+
dependencies: [],
|
|
130
|
+
typeReferences,
|
|
131
|
+
loc: node.loc
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
136
|
+
const usedImports = findUsedImports(node.declaration, importedNames);
|
|
137
|
+
const typeReferences = extractTypeReferences(node.declaration);
|
|
138
|
+
exports.push({
|
|
139
|
+
name: "default",
|
|
140
|
+
type: "default",
|
|
141
|
+
imports: usedImports,
|
|
142
|
+
dependencies: [],
|
|
143
|
+
typeReferences,
|
|
144
|
+
loc: node.loc
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return exports;
|
|
149
|
+
}
|
|
150
|
+
function extractFromDeclaration(declaration) {
|
|
151
|
+
const results = [];
|
|
152
|
+
if (declaration.type === "FunctionDeclaration" && "id" in declaration && declaration.id) {
|
|
153
|
+
results.push({ name: declaration.id.name, type: "function" });
|
|
154
|
+
} else if (declaration.type === "ClassDeclaration" && "id" in declaration && declaration.id) {
|
|
155
|
+
results.push({ name: declaration.id.name, type: "class" });
|
|
156
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
157
|
+
for (const declarator of declaration.declarations) {
|
|
158
|
+
if (declarator.id.type === "Identifier") {
|
|
159
|
+
results.push({ name: declarator.id.name, type: "const" });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} else if (declaration.type === "TSTypeAliasDeclaration") {
|
|
163
|
+
results.push({ name: declaration.id.name, type: "type" });
|
|
164
|
+
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
165
|
+
results.push({ name: declaration.id.name, type: "interface" });
|
|
166
|
+
}
|
|
167
|
+
return results;
|
|
168
|
+
}
|
|
169
|
+
function findUsedImports(node, importedNames) {
|
|
170
|
+
const usedImports = /* @__PURE__ */ new Set();
|
|
171
|
+
function visit(n) {
|
|
172
|
+
if (n.type === "Identifier" && importedNames.has(n.name)) {
|
|
173
|
+
usedImports.add(n.name);
|
|
174
|
+
}
|
|
175
|
+
for (const key in n) {
|
|
176
|
+
const value = n[key];
|
|
177
|
+
if (value && typeof value === "object") {
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
value.forEach((child) => {
|
|
180
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
181
|
+
visit(child);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
} else if ("type" in value) {
|
|
185
|
+
visit(value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
visit(node);
|
|
191
|
+
return Array.from(usedImports);
|
|
192
|
+
}
|
|
193
|
+
function calculateImportSimilarity(export1, export2) {
|
|
194
|
+
if (export1.imports.length === 0 && export2.imports.length === 0) {
|
|
195
|
+
return 1;
|
|
196
|
+
}
|
|
197
|
+
const set1 = new Set(export1.imports);
|
|
198
|
+
const set2 = new Set(export2.imports);
|
|
199
|
+
const intersection = new Set([...set1].filter((x) => set2.has(x)));
|
|
200
|
+
const union = /* @__PURE__ */ new Set([...set1, ...set2]);
|
|
201
|
+
return intersection.size / union.size;
|
|
202
|
+
}
|
|
203
|
+
function extractTypeReferences(node) {
|
|
204
|
+
const types = /* @__PURE__ */ new Set();
|
|
205
|
+
function visit(n) {
|
|
206
|
+
if (!n || typeof n !== "object") return;
|
|
207
|
+
if (n.type === "TSTypeReference" && n.typeName) {
|
|
208
|
+
if (n.typeName.type === "Identifier") {
|
|
209
|
+
types.add(n.typeName.name);
|
|
210
|
+
} else if (n.typeName.type === "TSQualifiedName") {
|
|
211
|
+
let current = n.typeName;
|
|
212
|
+
while (current.type === "TSQualifiedName") {
|
|
213
|
+
if (current.right?.type === "Identifier") {
|
|
214
|
+
types.add(current.right.name);
|
|
215
|
+
}
|
|
216
|
+
current = current.left;
|
|
217
|
+
}
|
|
218
|
+
if (current.type === "Identifier") {
|
|
219
|
+
types.add(current.name);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (n.type === "TSInterfaceHeritage" && n.expression) {
|
|
224
|
+
if (n.expression.type === "Identifier") {
|
|
225
|
+
types.add(n.expression.name);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
for (const key of Object.keys(n)) {
|
|
229
|
+
const value = n[key];
|
|
230
|
+
if (Array.isArray(value)) {
|
|
231
|
+
value.forEach(visit);
|
|
232
|
+
} else if (value && typeof value === "object") {
|
|
233
|
+
visit(value);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
visit(node);
|
|
238
|
+
return Array.from(types);
|
|
239
|
+
}
|
|
76
240
|
function parseCode(code, language) {
|
|
77
241
|
return null;
|
|
78
242
|
}
|
|
@@ -201,6 +365,8 @@ function getElapsedTime(startTime) {
|
|
|
201
365
|
return ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
202
366
|
}
|
|
203
367
|
export {
|
|
368
|
+
DEFAULT_EXCLUDE,
|
|
369
|
+
calculateImportSimilarity,
|
|
204
370
|
estimateTokens,
|
|
205
371
|
extractFunctions,
|
|
206
372
|
extractImports,
|
|
@@ -213,6 +379,7 @@ export {
|
|
|
213
379
|
loadMergedConfig,
|
|
214
380
|
mergeConfigWithDefaults,
|
|
215
381
|
parseCode,
|
|
382
|
+
parseFileExports,
|
|
216
383
|
readFileContent,
|
|
217
384
|
resolveOutputPath,
|
|
218
385
|
scanFiles
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Shared utilities for AIReady analysis tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
"import": "./dist/index.mjs"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
17
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
18
|
+
"lint": "eslint src",
|
|
19
|
+
"clean": "rm -rf dist",
|
|
20
|
+
"prepublishOnly": "pnpm build",
|
|
21
|
+
"release": "pnpm build && pnpm publish --no-git-checks"
|
|
22
|
+
},
|
|
15
23
|
"keywords": [
|
|
16
24
|
"aiready",
|
|
17
25
|
"code-analysis",
|
|
@@ -34,18 +42,14 @@
|
|
|
34
42
|
"CONTRIBUTING.md"
|
|
35
43
|
],
|
|
36
44
|
"devDependencies": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
45
|
+
"eslint": "^9.17.0",
|
|
46
|
+
"tsup": "^8.3.5"
|
|
39
47
|
},
|
|
40
48
|
"dependencies": {
|
|
49
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
50
|
+
"@typescript-eslint/typescript-estree": "^8.53.0",
|
|
51
|
+
"chalk": "^5.4.1",
|
|
41
52
|
"glob": "^13.0.0",
|
|
42
|
-
"
|
|
43
|
-
},
|
|
44
|
-
"scripts": {
|
|
45
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
46
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
47
|
-
"lint": "eslint src",
|
|
48
|
-
"clean": "rm -rf dist",
|
|
49
|
-
"release": "pnpm build && pnpm publish --no-git-checks"
|
|
53
|
+
"typescript": "^5.9.3"
|
|
50
54
|
}
|
|
51
|
-
}
|
|
55
|
+
}
|