fileflows 1.0.3 → 1.0.5
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/README.md +19 -11
- package/cli.mjs +7 -0
- package/config/jest-require-polyfill.cjs +20 -0
- package/config/jest-setup.mjs +28 -0
- package/config/jest.config.mjs +72 -0
- package/config/localVars.js +2 -109
- package/dist/cli.js +76 -0
- package/dist/config/localVars.js +76 -0
- package/dist/index.js +7 -0
- package/dist/lib/dataFlowGrouper.js +137 -0
- package/dist/lib/dependencyExtractor.js +46 -0
- package/dist/lib/fileClassifier.js +78 -0
- package/dist/lib/fileFlowsGenerator.js +301 -0
- package/dist/lib/fileIO.js +35 -0
- package/dist/lib/graphUtils.js +89 -0
- package/dist/lib/index.js +50 -0
- package/dist/lib/jsParser.js +131 -0
- package/dist/lib/otherFileParser.js +131 -0
- package/index.mjs +2 -0
- package/package.json +31 -14
- package/scripts/broadcast.sh +26 -0
- package/scripts/clean-bun-cache.mjs +14 -0
- package/scripts/clean-dist.mjs +7 -0
- package/scripts/ensure-runner.mjs +9 -0
- package/scripts/kill-agent.sh +24 -0
- package/scripts/kill-all-agents.sh +31 -0
- package/scripts/list-agents.sh +16 -0
- package/scripts/send-to-agent.sh +28 -0
- package/scripts/spawn-agent.sh +62 -0
- package/cli.js +0 -81
- package/config/localVars.test.js +0 -37
- package/index.js +0 -13
- package/lib/SUMMARY.md +0 -53
- package/lib/dataFlowGrouper.js +0 -150
- package/lib/dataFlowGrouper.test.js +0 -17
- package/lib/dependencyExtractor.js +0 -70
- package/lib/dependencyExtractor.test.js +0 -9
- package/lib/fileClassifier.js +0 -38
- package/lib/fileClassifier.test.js +0 -9
- package/lib/fileFlowsGenerator.js +0 -156
- package/lib/fileFlowsGenerator.test.js +0 -17
- package/lib/fileIO.js +0 -60
- package/lib/fileIO.test.js +0 -13
- package/lib/graphUtils.js +0 -139
- package/lib/graphUtils.test.js +0 -25
- package/lib/index.js +0 -29
- package/lib/index.test.js +0 -53
- package/lib/jsParser.js +0 -132
- package/lib/jsParser.test.js +0 -13
- package/lib/otherFileParser.js +0 -103
- package/lib/otherFileParser.test.js +0 -9
package/lib/graphUtils.test.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Auto-generated unit test for graphUtils.js - optimized for speed
|
|
2
|
-
const mod = require('./graphUtils.js');
|
|
3
|
-
|
|
4
|
-
describe('graphUtils.js', () => {
|
|
5
|
-
test('buildDependencyGraph works', async () => {
|
|
6
|
-
// Fast assertion - TODO: implement specific test logic
|
|
7
|
-
expect(typeof mod.buildDependencyGraph).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
test('findConnectedComponents works', async () => {
|
|
10
|
-
// Fast assertion - TODO: implement specific test logic
|
|
11
|
-
expect(typeof mod.findConnectedComponents).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
test('depthFirstSearch works', async () => {
|
|
14
|
-
// Fast assertion - TODO: implement specific test logic
|
|
15
|
-
expect(typeof mod.depthFirstSearch).toBeDefined();
|
|
16
|
-
});
|
|
17
|
-
test('groupBySimilarity works', async () => {
|
|
18
|
-
// Fast assertion - TODO: implement specific test logic
|
|
19
|
-
expect(typeof mod.groupBySimilarity).toBeDefined();
|
|
20
|
-
});
|
|
21
|
-
test('calculateRoleScore works', async () => {
|
|
22
|
-
// Fast assertion - TODO: implement specific test logic
|
|
23
|
-
expect(typeof mod.calculateRoleScore).toBeDefined();
|
|
24
|
-
});
|
|
25
|
-
});
|
package/lib/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Library aggregation module
|
|
3
|
-
* Exports all library functionality following NPM architecture guidelines
|
|
4
|
-
* Refactored: Global const declarations moved to config/localVars.js
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// 🚩AI: MAIN_LIBRARY_EXPORTS_REGISTRY - Dependencies centralized in config/localVars.js
|
|
8
|
-
function getLibraryModules() {
|
|
9
|
-
const localVars = require(`../config/localVars`);
|
|
10
|
-
const deps = localVars.getDependencies();
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
generateFileFlows: deps.generateFileFlows,
|
|
14
|
-
groupByDataFlow: deps.groupByDataFlow,
|
|
15
|
-
classifyFile: deps.classifyFile,
|
|
16
|
-
parseJSFile: deps.parseJSFile,
|
|
17
|
-
parseOtherFile: deps.parseOtherFile,
|
|
18
|
-
extractDependencies: deps.extractDependencies,
|
|
19
|
-
safeReadFileSync: deps.fileIO.safeReadFileSync,
|
|
20
|
-
safeResolvePath: deps.fileIO.safeResolvePath,
|
|
21
|
-
buildDependencyGraph: deps.graphUtils.buildDependencyGraph,
|
|
22
|
-
findConnectedComponents: deps.graphUtils.findConnectedComponents,
|
|
23
|
-
depthFirstSearch: deps.graphUtils.depthFirstSearch,
|
|
24
|
-
groupBySimilarity: deps.graphUtils.groupBySimilarity,
|
|
25
|
-
calculateRoleScore: deps.graphUtils.calculateRoleScore
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = getLibraryModules();
|
package/lib/index.test.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Auto-generated unit test for index.js - optimized for speed
|
|
2
|
-
const mod = require('./index.js');
|
|
3
|
-
|
|
4
|
-
describe('index.js', () => {
|
|
5
|
-
test('generateFileFlows works', async () => {
|
|
6
|
-
// Fast assertion - TODO: implement specific test logic
|
|
7
|
-
expect(typeof mod.generateFileFlows).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
test('groupByDataFlow works', async () => {
|
|
10
|
-
// Fast assertion - TODO: implement specific test logic
|
|
11
|
-
expect(typeof mod.groupByDataFlow).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
test('classifyFile works', async () => {
|
|
14
|
-
// Fast assertion - TODO: implement specific test logic
|
|
15
|
-
expect(typeof mod.classifyFile).toBeDefined();
|
|
16
|
-
});
|
|
17
|
-
test('parseJSFile works', async () => {
|
|
18
|
-
// Fast assertion - TODO: implement specific test logic
|
|
19
|
-
expect(typeof mod.parseJSFile).toBeDefined();
|
|
20
|
-
});
|
|
21
|
-
test('parseOtherFile works', async () => {
|
|
22
|
-
// Fast assertion - TODO: implement specific test logic
|
|
23
|
-
expect(typeof mod.parseOtherFile).toBeDefined();
|
|
24
|
-
});
|
|
25
|
-
test('extractDependencies works', async () => {
|
|
26
|
-
// Fast assertion - TODO: implement specific test logic
|
|
27
|
-
expect(typeof mod.extractDependencies).toBeDefined();
|
|
28
|
-
});
|
|
29
|
-
test('safeReadFileSync works', async () => {
|
|
30
|
-
// Fast assertion - TODO: implement specific test logic
|
|
31
|
-
expect(typeof mod.safeReadFileSync).toBeDefined();
|
|
32
|
-
});
|
|
33
|
-
test('safeResolvePath works', async () => {
|
|
34
|
-
// Fast assertion - TODO: implement specific test logic
|
|
35
|
-
expect(typeof mod.safeResolvePath).toBeDefined();
|
|
36
|
-
});
|
|
37
|
-
test('buildDependencyGraph works', async () => {
|
|
38
|
-
// Fast assertion - TODO: implement specific test logic
|
|
39
|
-
expect(typeof mod.buildDependencyGraph).toBeDefined();
|
|
40
|
-
});
|
|
41
|
-
test('findConnectedComponents works', async () => {
|
|
42
|
-
// Fast assertion - TODO: implement specific test logic
|
|
43
|
-
expect(typeof mod.findConnectedComponents).toBeDefined();
|
|
44
|
-
});
|
|
45
|
-
test('depthFirstSearch works', async () => {
|
|
46
|
-
// Fast assertion - TODO: implement specific test logic
|
|
47
|
-
expect(typeof mod.depthFirstSearch).toBeDefined();
|
|
48
|
-
});
|
|
49
|
-
test('groupBySimilarity works', async () => {
|
|
50
|
-
// Fast assertion - TODO: implement specific test logic
|
|
51
|
-
expect(typeof mod.groupBySimilarity).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
});
|
package/lib/jsParser.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JavaScript/TypeScript file parsing functionality
|
|
3
|
-
* Extracts imports, exports, functions, components, API calls, and routes
|
|
4
|
-
* @param {string} content - File content to parse
|
|
5
|
-
* @param {string} filePath - Path of the file being parsed
|
|
6
|
-
* @returns {Object} Parsed metadata including imports, exports, functions, etc.
|
|
7
|
-
*/
|
|
8
|
-
// 🚩AI: MUST_UPDATE_IF_BABEL_PARSER_CHANGES
|
|
9
|
-
function parseJSFile(content, filePath) {
|
|
10
|
-
const { parse } = require(`@babel/parser`);
|
|
11
|
-
const imports = new Set();
|
|
12
|
-
const exports = new Set();
|
|
13
|
-
const functions = new Set();
|
|
14
|
-
const components = new Set();
|
|
15
|
-
const apiCalls = new Set();
|
|
16
|
-
const reduxActions = new Set();
|
|
17
|
-
const routes = new Set();
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
const ast = parse(content, {
|
|
21
|
-
sourceType: `module`,
|
|
22
|
-
allowImportExportEverywhere: true,
|
|
23
|
-
plugins: [`jsx`, `typescript`, `decorators-legacy`],
|
|
24
|
-
errorRecovery: true,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
function visitNode(node) {
|
|
28
|
-
if (!node || typeof node !== `object`) return;
|
|
29
|
-
|
|
30
|
-
switch (node.type) {
|
|
31
|
-
case `ImportDeclaration`:
|
|
32
|
-
const source = node.source?.value;
|
|
33
|
-
if (source && !source.startsWith(`.`)) imports.add(source);
|
|
34
|
-
break;
|
|
35
|
-
case `CallExpression`:
|
|
36
|
-
// Handle require() calls - only for external modules, exclude built-in Node.js modules
|
|
37
|
-
if (node.callee?.name === `require` && node.arguments?.[0]?.value) {
|
|
38
|
-
const reqSource = node.arguments[0].value;
|
|
39
|
-
const builtInModules = [`fs`, `path`, `http`, `https`, `os`, `util`, `crypto`, `events`, `stream`];
|
|
40
|
-
if (!reqSource.startsWith(`.`) && !reqSource.startsWith(`/`) && !builtInModules.includes(reqSource)) {
|
|
41
|
-
imports.add(reqSource);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const callee = node.callee;
|
|
46
|
-
if (callee?.type === `MemberExpression`) {
|
|
47
|
-
const obj = callee.object?.name;
|
|
48
|
-
const prop = callee.property?.name;
|
|
49
|
-
if ([`fetch`, `axios`, `http`, `https`, `api`].includes(obj) || [`get`, `post`, `put`, `delete`, `call`].includes(prop)) {
|
|
50
|
-
apiCalls.add(`${obj}.${prop}`);
|
|
51
|
-
}
|
|
52
|
-
if (obj === `dispatch` && prop) reduxActions.add(prop);
|
|
53
|
-
// Handle Express routes like app.get(), router.post(), express.put()
|
|
54
|
-
if ([`app`, `router`, `express`].includes(obj) && [`get`, `post`, `put`, `delete`, `patch`].includes(prop)) {
|
|
55
|
-
const routeArg = node.arguments?.[0];
|
|
56
|
-
if (routeArg?.value) {
|
|
57
|
-
routes.add(`${prop.toUpperCase()} ${routeArg.value}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (callee?.name === `fetch` || callee?.name === `axios`) {
|
|
62
|
-
apiCalls.add(`${callee.name}.call`);
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
case `ExportNamedDeclaration`:
|
|
66
|
-
node.specifiers?.forEach(spec => {
|
|
67
|
-
if (spec.exported?.name) exports.add(spec.exported.name);
|
|
68
|
-
});
|
|
69
|
-
if (node.declaration?.declarations) {
|
|
70
|
-
node.declaration.declarations.forEach(decl => {
|
|
71
|
-
if (decl.id?.name) exports.add(decl.id.name);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
if (node.declaration?.id?.name) {
|
|
75
|
-
exports.add(node.declaration.id.name);
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
case `ExportDefaultDeclaration`:
|
|
79
|
-
exports.add(`default`);
|
|
80
|
-
break;
|
|
81
|
-
case `FunctionDeclaration`:
|
|
82
|
-
if (node.id?.name) {
|
|
83
|
-
functions.add(node.id.name);
|
|
84
|
-
// Check if it's a React component (simplified check)
|
|
85
|
-
if (node.id.name[0] === node.id.name[0].toUpperCase()) {
|
|
86
|
-
components.add(node.id.name);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
case `VariableDeclarator`:
|
|
91
|
-
if ((node.init?.type === `ArrowFunctionExpression` || node.init?.type === `FunctionExpression`) && node.id?.name) {
|
|
92
|
-
functions.add(node.id.name);
|
|
93
|
-
if (node.id.name[0] === node.id.name[0].toUpperCase()) {
|
|
94
|
-
components.add(node.id.name);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Recursively visit child nodes
|
|
101
|
-
for (const key in node) {
|
|
102
|
-
const value = node[key];
|
|
103
|
-
if (Array.isArray(value)) {
|
|
104
|
-
value.forEach(visitNode);
|
|
105
|
-
} else if (value && typeof value === `object`) {
|
|
106
|
-
visitNode(value);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
visitNode(ast);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
// Log parse errors for debugging but don't crash
|
|
114
|
-
require('qerrors').logWarn(`JavaScript parsing failed for ${filePath}`, 'parseJSFile', {
|
|
115
|
-
context: 'JS_PARSE_ERROR',
|
|
116
|
-
filePath: filePath,
|
|
117
|
-
errorMessage: err.message
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
Imports: [...imports].sort(),
|
|
123
|
-
Exports: [...exports].sort(),
|
|
124
|
-
Functions: [...functions].sort(),
|
|
125
|
-
Components: [...components].sort(),
|
|
126
|
-
ApiCalls: [...apiCalls].sort(),
|
|
127
|
-
ReduxActions: [...reduxActions].sort(),
|
|
128
|
-
Routes: [...routes].sort(),
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = parseJSFile;
|
package/lib/jsParser.test.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Auto-generated unit test for jsParser.js - optimized for speed
|
|
2
|
-
const mod = require('./jsParser.js');
|
|
3
|
-
|
|
4
|
-
describe('jsParser.js', () => {
|
|
5
|
-
test('parseJSFile works', async () => {
|
|
6
|
-
// Fast assertion - TODO: implement specific test logic
|
|
7
|
-
expect(typeof mod.parseJSFile).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
test('visitNode works', async () => {
|
|
10
|
-
// Fast assertion - TODO: implement specific test logic
|
|
11
|
-
expect(typeof mod.visitNode).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
});
|
package/lib/otherFileParser.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Non-JavaScript file parsing functionality
|
|
3
|
-
* Handles JSON, Markdown, YAML, ENV, GraphQL, Shell, HTML files
|
|
4
|
-
* @param {string} content - File content to parse
|
|
5
|
-
* @param {string} relPath - Relative path of the file
|
|
6
|
-
* @param {string} ext - File extension
|
|
7
|
-
* @returns {Object} Parsed metadata specific to file type
|
|
8
|
-
*/
|
|
9
|
-
function parseOtherFile(content, relPath, ext) {
|
|
10
|
-
const localVars = require(`../config/localVars`);
|
|
11
|
-
const lines = content.split(`\n`);
|
|
12
|
-
|
|
13
|
-
switch (ext) {
|
|
14
|
-
case `json`:
|
|
15
|
-
try {
|
|
16
|
-
const parsed = JSON.parse(content);
|
|
17
|
-
const keys = Object.keys(parsed);
|
|
18
|
-
const summary = [parsed.name || parsed.title || 'JSON Configuration'].filter(Boolean);
|
|
19
|
-
return {
|
|
20
|
-
Keys: keys.slice(0, localVars.MAX_JSON_KEYS),
|
|
21
|
-
Summary: summary
|
|
22
|
-
};
|
|
23
|
-
} catch {
|
|
24
|
-
return { Keys: [], Summary: ['Malformed JSON'] };
|
|
25
|
-
}
|
|
26
|
-
case `md`:
|
|
27
|
-
const headings = lines
|
|
28
|
-
.filter((l) => l.startsWith(`#`))
|
|
29
|
-
.map((l) => l.replace(/^#+ /, ``))
|
|
30
|
-
.slice(0, 5);
|
|
31
|
-
const firstHeading = headings[0];
|
|
32
|
-
return {
|
|
33
|
-
Headings: headings,
|
|
34
|
-
Summary: firstHeading ? [firstHeading] : []
|
|
35
|
-
};
|
|
36
|
-
case `yml`:
|
|
37
|
-
case `yaml`:
|
|
38
|
-
const yamlKeys = lines
|
|
39
|
-
.filter((l) => /^[a-zA-Z0-9_]+:/.test(l))
|
|
40
|
-
.slice(0, localVars.MAX_YAML_KEYS)
|
|
41
|
-
.map((l) => l.split(`:`)[0]);
|
|
42
|
-
const yamlName = lines.find(l => l.includes('name:'))?.split(':')[1]?.trim() || 'YAML Configuration';
|
|
43
|
-
return {
|
|
44
|
-
Keys: yamlKeys,
|
|
45
|
-
Summary: [yamlName]
|
|
46
|
-
};
|
|
47
|
-
case `env`:
|
|
48
|
-
return {
|
|
49
|
-
Vars: lines
|
|
50
|
-
.filter((l) => l.includes(`=`))
|
|
51
|
-
.map((l) => l.split(`=`)[0])
|
|
52
|
-
};
|
|
53
|
-
case `graphql`:
|
|
54
|
-
const types = lines
|
|
55
|
-
.filter((l) => /^(query|mutation|type)\s+/.test(l))
|
|
56
|
-
.map((l) => l.trim().split(/\s+/)[1])
|
|
57
|
-
.filter(Boolean);
|
|
58
|
-
return {
|
|
59
|
-
Types: types,
|
|
60
|
-
Summary: ['GraphQL Schema']
|
|
61
|
-
};
|
|
62
|
-
case `sh`:
|
|
63
|
-
const commands = lines
|
|
64
|
-
.filter(l => l.trim() && !l.startsWith('#'))
|
|
65
|
-
.slice(0, localVars.MAX_SHELL_COMMANDS)
|
|
66
|
-
.map(l => l.trim().split(/\s+/)[0])
|
|
67
|
-
.filter(cmd => cmd && !cmd.includes('='));
|
|
68
|
-
const scriptPurpose = content.includes('deploy') ? 'deployment' : 'shell script';
|
|
69
|
-
return {
|
|
70
|
-
Commands: [...new Set(commands)],
|
|
71
|
-
Summary: [scriptPurpose]
|
|
72
|
-
};
|
|
73
|
-
case `html`:
|
|
74
|
-
// Simple and reliable HTML tag extraction
|
|
75
|
-
const tagLines = lines.filter(line => line.includes('<') && !line.includes('</'));
|
|
76
|
-
const tags = [];
|
|
77
|
-
|
|
78
|
-
for (const line of tagLines) {
|
|
79
|
-
const matches = line.match(/<([a-zA-Z][a-zA-Z0-9]*)/g);
|
|
80
|
-
if (matches) {
|
|
81
|
-
matches.forEach(match => {
|
|
82
|
-
const tagName = match.substring(1).toLowerCase();
|
|
83
|
-
if (tagName && !tags.includes(tagName)) {
|
|
84
|
-
tags.push(tagName);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Extract title from HTML
|
|
91
|
-
const titleMatch = content.match(/<title[^>]*>(.*?)<\/title>/is);
|
|
92
|
-
const title = titleMatch ? titleMatch[1].trim() : 'HTML Document';
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
Tags: tags.slice(0, localVars.MAX_HTML_TAGS),
|
|
96
|
-
Summary: [title]
|
|
97
|
-
};
|
|
98
|
-
default:
|
|
99
|
-
return { Summary: ['Unknown file type'] };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = parseOtherFile;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Auto-generated unit test for otherFileParser.js - optimized for speed
|
|
2
|
-
const mod = require('./otherFileParser.js');
|
|
3
|
-
|
|
4
|
-
describe('otherFileParser.js', () => {
|
|
5
|
-
test('parseOtherFile works', async () => {
|
|
6
|
-
// Fast assertion - TODO: implement specific test logic
|
|
7
|
-
expect(typeof mod.parseOtherFile).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
});
|