@codeyam/codeyam-cli 0.1.21 → 0.1.23
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/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +31 -8
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
- package/analyzer-template/packages/analyze/index.ts +4 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
- package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +239 -58
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1684 -1462
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +71 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +545 -94
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +456 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +11 -3
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +140 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +50 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +33 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js +217 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
- package/codeyam-cli/src/utils/analysisRunner.js +28 -1
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/analyzer.js +4 -2
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +136 -5
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorPreview.js +5 -3
- package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +60 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/editorSeedAdapter.js +42 -2
- package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.server.js +16 -0
- package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -1
- package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
- package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
- package/codeyam-cli/src/utils/queue/job.js +20 -2
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/testRunner.js +199 -1
- package/codeyam-cli/src/utils/testRunner.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +30 -11
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +35 -0
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-CQENLSrF.js +36 -0
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CJzc4vOH.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DMv5ESGo.js +96 -0
- package/codeyam-cli/src/webserver/build/client/assets/{editorPreview-NTuLi4Xg.js → editorPreview-CluPkvXJ.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-Blfy9UlN.js → entity._sha._-ByHz6rAQ.js} +13 -12
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-BA5L8bU-.js → entity._sha.scenarios._scenarioId.dev-CmLO432x.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-D4dmRgvO.js → entity._sha.scenarios._scenarioId.fullscreen-Bz9sCUF_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-oyPmV37k.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{manifest-5025e428.js → manifest-1a45e154.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-BCx1S8Z3.js → root-D2_tktnk.js} +6 -6
- package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-By5slFjw.js +16 -0
- package/codeyam-cli/src/webserver/build/server/assets/{index-C91yWWCI.js → index-DXaOwBnm.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-Dkas-RUS.js → init-CLG1LjQM.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-NZmUqQv6.js +688 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/editorProxy.js +55 -3
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/idleDetector.js +15 -0
- package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +8 -2
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/codeyam-editor-reference.md +8 -6
- package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +42 -34
- package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +2 -2
- package/package.json +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
- package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
- package/packages/ai/src/lib/astScopes/paths.js +12 -3
- package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +23 -9
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/analyze/index.js +1 -1
- package/packages/analyze/index.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +120 -28
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1368 -1193
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DODLxLcw.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-Dx-h1rJK.js +0 -130
- package/codeyam-cli/src/webserver/build/client/assets/globals-BrPXT1iR.css +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-C1kjC9UJ.js +0 -13
- package/codeyam-cli/src/webserver/build/server/assets/server-build-pulXLTrG.js +0 -640
package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts
CHANGED
|
@@ -6,6 +6,20 @@ import type {
|
|
|
6
6
|
ReadonlyEntity,
|
|
7
7
|
} from '~codeyam/types';
|
|
8
8
|
import { ImmutableAnalysisContext } from '../../analysisContext';
|
|
9
|
+
import { awsLogDebugLevel } from '~codeyam/utils';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Tracks statistics across the recursive dependency validation.
|
|
13
|
+
* Shared by all recursive calls to provide a complete picture.
|
|
14
|
+
*/
|
|
15
|
+
interface ValidationStats {
|
|
16
|
+
totalVisited: number;
|
|
17
|
+
skippedDuplicate: number;
|
|
18
|
+
skippedMissing: number;
|
|
19
|
+
skippedTrivial: number;
|
|
20
|
+
maxDepth: number;
|
|
21
|
+
startTime: number;
|
|
22
|
+
}
|
|
9
23
|
|
|
10
24
|
export default function validateDependencyAnalyses({
|
|
11
25
|
analysis,
|
|
@@ -13,12 +27,18 @@ export default function validateDependencyAnalyses({
|
|
|
13
27
|
entity,
|
|
14
28
|
context,
|
|
15
29
|
dependentAnalyses,
|
|
30
|
+
_depth = 0,
|
|
31
|
+
_stats,
|
|
16
32
|
}: {
|
|
17
33
|
analysis?: Analysis;
|
|
18
34
|
readonlyAnalysis?: ReadonlyAnalysis;
|
|
19
35
|
entity: ReadonlyEntity;
|
|
20
36
|
context: ImmutableAnalysisContext;
|
|
21
37
|
dependentAnalyses?: ReadonlyAnalysisMap;
|
|
38
|
+
/** Recursion depth (internal, do not set) */
|
|
39
|
+
_depth?: number;
|
|
40
|
+
/** Shared stats tracker (internal, do not set) */
|
|
41
|
+
_stats?: ValidationStats;
|
|
22
42
|
}): { dependentAnalyses: ReadonlyAnalysisMap } {
|
|
23
43
|
if (!readonlyAnalysis) readonlyAnalysis = analysis;
|
|
24
44
|
if (!readonlyAnalysis) {
|
|
@@ -32,6 +52,28 @@ export default function validateDependencyAnalyses({
|
|
|
32
52
|
);
|
|
33
53
|
}
|
|
34
54
|
|
|
55
|
+
// Initialize stats on the root call
|
|
56
|
+
const isRootCall = _depth === 0;
|
|
57
|
+
if (!_stats) {
|
|
58
|
+
_stats = {
|
|
59
|
+
totalVisited: 0,
|
|
60
|
+
skippedDuplicate: 0,
|
|
61
|
+
skippedMissing: 0,
|
|
62
|
+
skippedTrivial: 0,
|
|
63
|
+
maxDepth: 0,
|
|
64
|
+
startTime: Date.now(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (_depth > _stats.maxDepth) _stats.maxDepth = _depth;
|
|
68
|
+
|
|
69
|
+
const importCount = entity.metadata?.importedExports?.length ?? 0;
|
|
70
|
+
if (isRootCall && importCount > 0) {
|
|
71
|
+
awsLogDebugLevel(
|
|
72
|
+
2,
|
|
73
|
+
`validateDeps: ${entity.name} has ${importCount} imports to validate`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
35
77
|
if (
|
|
36
78
|
dependentAnalyses &&
|
|
37
79
|
dependentAnalyses[readonlyAnalysis.filePath]?.[
|
|
@@ -45,6 +87,12 @@ export default function validateDependencyAnalyses({
|
|
|
45
87
|
})
|
|
46
88
|
) {
|
|
47
89
|
// already processed this analysis
|
|
90
|
+
if (isRootCall) {
|
|
91
|
+
awsLogDebugLevel(
|
|
92
|
+
2,
|
|
93
|
+
`validateDeps: ${entity.name} already fully processed (cache hit)`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
48
96
|
return { dependentAnalyses };
|
|
49
97
|
}
|
|
50
98
|
|
|
@@ -69,9 +117,20 @@ export default function validateDependencyAnalyses({
|
|
|
69
117
|
|
|
70
118
|
// if the entity has duplicate dependencies, handle gracefully
|
|
71
119
|
if (dependentAnalyses[dependencyFilePath]?.[dependencyName]) {
|
|
120
|
+
_stats.skippedDuplicate++;
|
|
72
121
|
continue;
|
|
73
122
|
}
|
|
74
123
|
|
|
124
|
+
_stats.totalVisited++;
|
|
125
|
+
|
|
126
|
+
// Emit periodic progress so the spinner stays alive for large trees
|
|
127
|
+
if (_stats.totalVisited % 50 === 0) {
|
|
128
|
+
awsLogDebugLevel(
|
|
129
|
+
1,
|
|
130
|
+
`Validating dependencies... (${_stats.totalVisited} resolved, depth ${_depth})`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
75
134
|
// Check if dependency analysis exists in context
|
|
76
135
|
const dependentAnalysis = context.getAnalysis(
|
|
77
136
|
dependencyFilePath,
|
|
@@ -86,21 +145,20 @@ export default function validateDependencyAnalyses({
|
|
|
86
145
|
);
|
|
87
146
|
|
|
88
147
|
if (!dependentEntity) {
|
|
89
|
-
|
|
90
|
-
// `CodeYam: validateDependencyAnalyses: Missing dependent entity ${dependencyFilePath}:${dependencyName} for ${entity.filePath}:${entity.name}. This is likely a bug.`,
|
|
91
|
-
// );
|
|
148
|
+
_stats.skippedMissing++;
|
|
92
149
|
continue;
|
|
93
150
|
}
|
|
94
151
|
|
|
95
152
|
// ignore trivial missing dependencies
|
|
96
|
-
if (!['library', 'visual'].includes(dependentEntity.entityType))
|
|
153
|
+
if (!['library', 'visual'].includes(dependentEntity.entityType)) {
|
|
154
|
+
_stats.skippedTrivial++;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
97
157
|
|
|
98
158
|
if (!dependentEntity?.metadata?.hasCircularDependency) {
|
|
99
159
|
// TODO: This no longer seems to happen thanks to fixes elsewhere, but leave the warning
|
|
100
|
-
// console.warn(
|
|
101
|
-
// `CodeYam: validateDependencyAnalyses: Missing analysis for dependency ${entity.filePath}:${entity.name} -> ${dependencyFilePath}:${dependencyName}, should be marked as having circular dependencies.`,
|
|
102
|
-
// );
|
|
103
160
|
}
|
|
161
|
+
_stats.skippedMissing++;
|
|
104
162
|
continue;
|
|
105
163
|
}
|
|
106
164
|
|
|
@@ -136,9 +194,6 @@ export default function validateDependencyAnalyses({
|
|
|
136
194
|
if (analysis) {
|
|
137
195
|
// Track dependency relationship in analysis metadata
|
|
138
196
|
if (!analysis.metadata.dependentAnalyses.includes(dependentAnalysis.id)) {
|
|
139
|
-
// console.log(
|
|
140
|
-
// `CodeYam: validateDependencyAnalyses: Establishing dependency ${analysis.filePath}:${analysis.entityName} -> ${dependentAnalysis.filePath}:${dependentAnalysis.entityName}.`,
|
|
141
|
-
// );
|
|
142
197
|
analysis.metadata.dependentAnalyses.push(dependentAnalysis.id);
|
|
143
198
|
}
|
|
144
199
|
}
|
|
@@ -152,9 +207,26 @@ export default function validateDependencyAnalyses({
|
|
|
152
207
|
entity: dependentEntity,
|
|
153
208
|
context: context,
|
|
154
209
|
dependentAnalyses,
|
|
210
|
+
_depth: _depth + 1,
|
|
211
|
+
_stats,
|
|
155
212
|
});
|
|
156
213
|
}
|
|
157
214
|
}
|
|
158
215
|
|
|
216
|
+
// Log summary on root call completion
|
|
217
|
+
if (isRootCall) {
|
|
218
|
+
const elapsed = Date.now() - _stats.startTime;
|
|
219
|
+
const totalDeps = Object.values(dependentAnalyses).reduce(
|
|
220
|
+
(sum, fileMap) => sum + Object.keys(fileMap).length,
|
|
221
|
+
0,
|
|
222
|
+
);
|
|
223
|
+
awsLogDebugLevel(
|
|
224
|
+
1,
|
|
225
|
+
`Dependency validation complete for ${entity.name}: ${totalDeps} dependencies resolved, ` +
|
|
226
|
+
`${_stats.skippedDuplicate} duplicates skipped, ${_stats.skippedMissing} missing, ` +
|
|
227
|
+
`${_stats.skippedTrivial} trivial, max depth ${_stats.maxDepth}, ${elapsed}ms`,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
159
231
|
return { dependentAnalyses };
|
|
160
232
|
}
|
|
@@ -3,6 +3,8 @@ import { ProjectAnalyzer } from '../ProjectAnalyzer';
|
|
|
3
3
|
import { generateSha } from '~codeyam/database';
|
|
4
4
|
import { isNextRoute } from '~codeyam/utils';
|
|
5
5
|
|
|
6
|
+
const warnedLayoutPaths = new Set<string>();
|
|
7
|
+
|
|
6
8
|
export default function analyzeNextRoute(
|
|
7
9
|
file: File,
|
|
8
10
|
projectAnalyzer: ProjectAnalyzer,
|
|
@@ -56,9 +58,12 @@ export default function analyzeNextRoute(
|
|
|
56
58
|
|
|
57
59
|
// Ensure entities array exists before trying to use it
|
|
58
60
|
if (!layout.entities) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
if (!warnedLayoutPaths.has(layout.path)) {
|
|
62
|
+
warnedLayoutPaths.add(layout.path);
|
|
63
|
+
console.log(
|
|
64
|
+
`CodeYam Warning: layout.entities not populated for ${layout.path}, skipping implicit dependency`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
69
|
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
clearAttributesFromMapping,
|
|
12
12
|
mergeJsonTypeDefinitions,
|
|
13
13
|
} from '~codeyam/ai';
|
|
14
|
-
import mergeInDependentDataStructure
|
|
15
|
-
|
|
14
|
+
import mergeInDependentDataStructure, {
|
|
15
|
+
DataStructureTimeoutError,
|
|
16
|
+
} from './mergeInDependentDataStructure';
|
|
17
|
+
import { awsLog, awsLogDebugLevel } from '~codeyam/utils';
|
|
16
18
|
import gatherDataForMocks from './gatherDataForMocks';
|
|
17
19
|
import enrichArrayTypesFromChildSignatures from './enrichArrayTypesFromChildSignatures';
|
|
18
20
|
import enrichUnknownTypesFromSourceEquivalencies from './enrichUnknownTypesFromSourceEquivalencies';
|
|
@@ -328,12 +330,23 @@ export default function generateDataStructure({
|
|
|
328
330
|
|
|
329
331
|
// Recursive function to traverse the dependency tree
|
|
330
332
|
const processedAnalyses = new Set<string>();
|
|
333
|
+
const traverseStart = Date.now();
|
|
334
|
+
const TRAVERSE_TIMEOUT_MS = 2_000;
|
|
335
|
+
let traverseCount = 0;
|
|
331
336
|
const traverseDependencyTree = (analyses: ReadonlyAnalysisMap) => {
|
|
332
337
|
for (const filePath in analyses) {
|
|
333
338
|
for (const name in analyses[filePath]) {
|
|
334
339
|
const analysisKey = `${filePath}:${name}`;
|
|
335
340
|
if (processedAnalyses.has(analysisKey)) continue;
|
|
336
341
|
processedAnalyses.add(analysisKey);
|
|
342
|
+
traverseCount++;
|
|
343
|
+
|
|
344
|
+
if (Date.now() - traverseStart > TRAVERSE_TIMEOUT_MS) {
|
|
345
|
+
throw new DataStructureTimeoutError(
|
|
346
|
+
entity.name,
|
|
347
|
+
Date.now() - traverseStart,
|
|
348
|
+
);
|
|
349
|
+
}
|
|
337
350
|
|
|
338
351
|
const childAnalysis = analyses[filePath][name];
|
|
339
352
|
const childEntity = childAnalysis?.entity;
|
|
@@ -443,6 +456,25 @@ export default function generateDataStructure({
|
|
|
443
456
|
// Start traversal from direct non-mocked children
|
|
444
457
|
traverseDependencyTree(nonMockedDependentAnalyses);
|
|
445
458
|
|
|
459
|
+
const traverseElapsed = Date.now() - traverseStart;
|
|
460
|
+
const childSchemaKeyCount = Object.values(childDependencySchemas).reduce(
|
|
461
|
+
(sum, fileMap) =>
|
|
462
|
+
sum +
|
|
463
|
+
Object.values(fileMap).reduce(
|
|
464
|
+
(s, schema) =>
|
|
465
|
+
s +
|
|
466
|
+
Object.keys(schema.signatureSchema || {}).length +
|
|
467
|
+
Object.keys(schema.returnValueSchema || {}).length,
|
|
468
|
+
0,
|
|
469
|
+
),
|
|
470
|
+
0,
|
|
471
|
+
);
|
|
472
|
+
awsLogDebugLevel(
|
|
473
|
+
1,
|
|
474
|
+
`Dependency tree traversal for ${entity.name}: ${traverseCount} analyses, ` +
|
|
475
|
+
`${childSchemaKeyCount} child schema keys, ${allImportedExports.length} imports, ${traverseElapsed}ms`,
|
|
476
|
+
);
|
|
477
|
+
|
|
446
478
|
// console.info(
|
|
447
479
|
// 'CODEYAM DEBUG: start merge',
|
|
448
480
|
// JSON.stringify(
|
|
@@ -484,6 +516,14 @@ export default function generateDataStructure({
|
|
|
484
516
|
dependencySchemas: isolatedDataStructure.dependencySchemas,
|
|
485
517
|
});
|
|
486
518
|
|
|
519
|
+
const mergeStart = Date.now();
|
|
520
|
+
// Shared deadline for all phases from merge onward
|
|
521
|
+
const genDeadline = mergeStart + 5_000; // 5s total budget for all phases
|
|
522
|
+
awsLogDebugLevel(
|
|
523
|
+
1,
|
|
524
|
+
`Starting mergeInDependentDataStructure for ${entity.name}...`,
|
|
525
|
+
);
|
|
526
|
+
|
|
487
527
|
const mergedDataStructure = mergeInDependentDataStructure({
|
|
488
528
|
importedExports: allImportedExports,
|
|
489
529
|
dependentAnalyses: nonMockedDependentAnalyses,
|
|
@@ -498,6 +538,14 @@ export default function generateDataStructure({
|
|
|
498
538
|
dependencySchemas: isolatedDataStructure?.dependencySchemas || {},
|
|
499
539
|
});
|
|
500
540
|
|
|
541
|
+
const mergeTimedOut = !!(mergedDataStructure as any).timedOut;
|
|
542
|
+
awsLogDebugLevel(
|
|
543
|
+
1,
|
|
544
|
+
`mergeInDependentDataStructure ${mergeTimedOut ? 'PARTIAL' : 'complete'} for ${entity.name}: ` +
|
|
545
|
+
`${Object.keys(mergedDataStructure.signatureSchema).length} sig, ` +
|
|
546
|
+
`${Object.keys(mergedDataStructure.returnValueSchema).length} ret, ${Date.now() - mergeStart}ms`,
|
|
547
|
+
);
|
|
548
|
+
|
|
501
549
|
mergedDataStructure.environmentVariables =
|
|
502
550
|
isolatedDataStructure.environmentVariables || [];
|
|
503
551
|
|
|
@@ -511,6 +559,7 @@ export default function generateDataStructure({
|
|
|
511
559
|
// Merge collected child dependency schemas into mergedDataStructure.
|
|
512
560
|
// This ensures that when gatherDataForMocks looks up schemas for child imports,
|
|
513
561
|
// the child's schemas are available.
|
|
562
|
+
const childMergeStart = Date.now();
|
|
514
563
|
for (const schemaFilePath in childDependencySchemas) {
|
|
515
564
|
for (const schemaName in childDependencySchemas[schemaFilePath]) {
|
|
516
565
|
mergedDataStructure.dependencySchemas[schemaFilePath] ||= {};
|
|
@@ -561,7 +610,13 @@ export default function generateDataStructure({
|
|
|
561
610
|
}
|
|
562
611
|
}
|
|
563
612
|
|
|
613
|
+
awsLogDebugLevel(
|
|
614
|
+
1,
|
|
615
|
+
`Child schema merge for ${entity.name}: ${Date.now() - childMergeStart}ms`,
|
|
616
|
+
);
|
|
617
|
+
|
|
564
618
|
// Transformation tracing: capture after child schemas merged
|
|
619
|
+
const snapshotStart = Date.now();
|
|
565
620
|
transformationTracer.snapshot(entity.name, 'childSchemasMerged', {
|
|
566
621
|
signatureSchema: mergedDataStructure.signatureSchema,
|
|
567
622
|
returnValueSchema: mergedDataStructure.returnValueSchema,
|
|
@@ -588,71 +643,134 @@ export default function generateDataStructure({
|
|
|
588
643
|
// ),
|
|
589
644
|
// );
|
|
590
645
|
|
|
646
|
+
awsLogDebugLevel(
|
|
647
|
+
1,
|
|
648
|
+
`Transformation snapshot for ${entity.name}: ${Date.now() - snapshotStart}ms`,
|
|
649
|
+
);
|
|
650
|
+
|
|
591
651
|
// Deduplicate function schemas in the merged data structure
|
|
592
652
|
// The merge process might introduce duplicates even if individual schemas were clean
|
|
593
|
-
|
|
594
|
-
const sigBefore = { ...mergedDataStructure.signatureSchema };
|
|
595
|
-
mergedDataStructure.signatureSchema = deduplicateFunctionSchemas(
|
|
596
|
-
mergedDataStructure.signatureSchema,
|
|
597
|
-
);
|
|
598
|
-
transformationTracer.traceSchemaTransformResult(
|
|
599
|
-
entity.name,
|
|
600
|
-
'deduplicateFunctionSchemas',
|
|
601
|
-
sigBefore,
|
|
602
|
-
mergedDataStructure.signatureSchema,
|
|
603
|
-
{ schemaType: 'signature' },
|
|
604
|
-
);
|
|
653
|
+
const dedupStart = Date.now();
|
|
605
654
|
|
|
606
|
-
|
|
607
|
-
const
|
|
608
|
-
mergedDataStructure.returnValueSchema = deduplicateFunctionSchemas(
|
|
655
|
+
const sigKeyCount = Object.keys(mergedDataStructure.signatureSchema).length;
|
|
656
|
+
const retKeyCount = Object.keys(
|
|
609
657
|
mergedDataStructure.returnValueSchema,
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
658
|
+
).length;
|
|
659
|
+
|
|
660
|
+
// Skip dedup on very large schemas — the O(keys × variants × keyLength) cost
|
|
661
|
+
// is not worth it for schemas with 10K+ keys where function dedup rarely matters.
|
|
662
|
+
const DEDUP_KEY_THRESHOLD = 10_000;
|
|
663
|
+
|
|
664
|
+
if (sigKeyCount < DEDUP_KEY_THRESHOLD) {
|
|
665
|
+
const sigBefore = { ...mergedDataStructure.signatureSchema };
|
|
666
|
+
mergedDataStructure.signatureSchema = deduplicateFunctionSchemas(
|
|
667
|
+
mergedDataStructure.signatureSchema,
|
|
668
|
+
);
|
|
669
|
+
transformationTracer.traceSchemaTransformResult(
|
|
670
|
+
entity.name,
|
|
671
|
+
'deduplicateFunctionSchemas',
|
|
672
|
+
sigBefore,
|
|
673
|
+
mergedDataStructure.signatureSchema,
|
|
674
|
+
{ schemaType: 'signature' },
|
|
675
|
+
);
|
|
676
|
+
} else {
|
|
677
|
+
awsLogDebugLevel(
|
|
678
|
+
2,
|
|
679
|
+
`${entity.name}: skipping sig dedup (${sigKeyCount} keys > ${DEDUP_KEY_THRESHOLD})`,
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (retKeyCount < DEDUP_KEY_THRESHOLD) {
|
|
684
|
+
const rvBefore = { ...mergedDataStructure.returnValueSchema };
|
|
685
|
+
mergedDataStructure.returnValueSchema = deduplicateFunctionSchemas(
|
|
686
|
+
mergedDataStructure.returnValueSchema,
|
|
687
|
+
);
|
|
688
|
+
transformationTracer.traceSchemaTransformResult(
|
|
689
|
+
entity.name,
|
|
690
|
+
'deduplicateFunctionSchemas',
|
|
691
|
+
rvBefore,
|
|
692
|
+
mergedDataStructure.returnValueSchema,
|
|
693
|
+
{ schemaType: 'returnValue' },
|
|
694
|
+
);
|
|
695
|
+
} else {
|
|
696
|
+
awsLogDebugLevel(
|
|
697
|
+
2,
|
|
698
|
+
`${entity.name}: skipping ret dedup (${retKeyCount} keys > ${DEDUP_KEY_THRESHOLD})`,
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
awsLogDebugLevel(
|
|
703
|
+
1,
|
|
704
|
+
`${entity.name}: root schema dedup ${Date.now() - dedupStart}ms (sig=${sigKeyCount}, ret=${retKeyCount})`,
|
|
617
705
|
);
|
|
618
706
|
|
|
619
707
|
// Also deduplicate dependency schemas and clear known attributes
|
|
708
|
+
let depProcessed = 0;
|
|
709
|
+
const depStart = Date.now();
|
|
620
710
|
for (const filePath in mergedDataStructure.dependencySchemas) {
|
|
621
711
|
for (const depEntityName in mergedDataStructure.dependencySchemas[
|
|
622
712
|
filePath
|
|
623
713
|
]) {
|
|
714
|
+
if (Date.now() > genDeadline) {
|
|
715
|
+
throw new DataStructureTimeoutError(
|
|
716
|
+
entity.name,
|
|
717
|
+
Date.now() - mergeStart,
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
|
|
624
721
|
const depSchema =
|
|
625
722
|
mergedDataStructure.dependencySchemas[filePath][depEntityName];
|
|
723
|
+
const depSigKeys = Object.keys(depSchema.signatureSchema || {}).length;
|
|
724
|
+
const depRetKeys = Object.keys(
|
|
725
|
+
depSchema.returnValueSchema || {},
|
|
726
|
+
).length;
|
|
626
727
|
|
|
627
|
-
|
|
628
|
-
const depSigBefore = { ...depSchema.signatureSchema };
|
|
629
|
-
depSchema.signatureSchema = deduplicateFunctionSchemas(
|
|
630
|
-
depSchema.signatureSchema,
|
|
631
|
-
);
|
|
632
|
-
transformationTracer.traceSchemaTransformResult(
|
|
633
|
-
entity.name,
|
|
634
|
-
'deduplicateFunctionSchemas',
|
|
635
|
-
depSigBefore,
|
|
636
|
-
depSchema.signatureSchema,
|
|
637
|
-
{ filePath, dependencyName: depEntityName, schemaType: 'signature' },
|
|
638
|
-
);
|
|
728
|
+
const depOpStart = Date.now();
|
|
639
729
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
730
|
+
if (depSigKeys < DEDUP_KEY_THRESHOLD) {
|
|
731
|
+
const depSigBefore = { ...depSchema.signatureSchema };
|
|
732
|
+
depSchema.signatureSchema = deduplicateFunctionSchemas(
|
|
733
|
+
depSchema.signatureSchema,
|
|
734
|
+
);
|
|
735
|
+
transformationTracer.traceSchemaTransformResult(
|
|
736
|
+
entity.name,
|
|
737
|
+
'deduplicateFunctionSchemas',
|
|
738
|
+
depSigBefore,
|
|
739
|
+
depSchema.signatureSchema,
|
|
740
|
+
{
|
|
741
|
+
filePath,
|
|
742
|
+
dependencyName: depEntityName,
|
|
743
|
+
schemaType: 'signature',
|
|
744
|
+
},
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if (depRetKeys < DEDUP_KEY_THRESHOLD) {
|
|
749
|
+
const depRvBefore = { ...depSchema.returnValueSchema };
|
|
750
|
+
depSchema.returnValueSchema = deduplicateFunctionSchemas(
|
|
751
|
+
depSchema.returnValueSchema,
|
|
752
|
+
);
|
|
753
|
+
transformationTracer.traceSchemaTransformResult(
|
|
754
|
+
entity.name,
|
|
755
|
+
'deduplicateFunctionSchemas',
|
|
756
|
+
depRvBefore,
|
|
757
|
+
depSchema.returnValueSchema,
|
|
758
|
+
{
|
|
759
|
+
filePath,
|
|
760
|
+
dependencyName: depEntityName,
|
|
761
|
+
schemaType: 'returnValue',
|
|
762
|
+
},
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const depOpElapsed = Date.now() - depOpStart;
|
|
767
|
+
if (depOpElapsed > 1000) {
|
|
768
|
+
awsLogDebugLevel(
|
|
769
|
+
2,
|
|
770
|
+
`${entity.name}: slow dep dedup ${depEntityName} sig=${depSigKeys} ret=${depRetKeys} ${depOpElapsed}ms`,
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
depProcessed++;
|
|
656
774
|
|
|
657
775
|
// Infer function types from child component usage BEFORE fillInSchemaGapsAndUnknowns.
|
|
658
776
|
// When a hook returns a property with type 'unknown' that is passed to a child
|
|
@@ -729,13 +847,33 @@ export default function generateDataStructure({
|
|
|
729
847
|
// Fill in type gaps BEFORE clearing attributes, so evidence like .includes()
|
|
730
848
|
// is used for type inference before being deleted
|
|
731
849
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
850
|
+
const FILL_IN_KEY_THRESHOLD = 5_000;
|
|
851
|
+
const fillStart = Date.now();
|
|
852
|
+
|
|
853
|
+
if (depSigKeys < FILL_IN_KEY_THRESHOLD) {
|
|
854
|
+
depSchema.signatureSchema = fillInDirectSchemaGapsAndUnknowns({
|
|
855
|
+
schema: depSchema.signatureSchema,
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (depRetKeys < FILL_IN_KEY_THRESHOLD) {
|
|
860
|
+
depSchema.returnValueSchema = fillInDirectSchemaGapsAndUnknowns({
|
|
861
|
+
schema: depSchema.returnValueSchema,
|
|
862
|
+
});
|
|
863
|
+
} else {
|
|
864
|
+
awsLogDebugLevel(
|
|
865
|
+
2,
|
|
866
|
+
`${entity.name}: skipping fillInGaps for ${depEntityName} ret (${depRetKeys} keys > ${FILL_IN_KEY_THRESHOLD})`,
|
|
867
|
+
);
|
|
868
|
+
}
|
|
735
869
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
870
|
+
const fillElapsed = Date.now() - fillStart;
|
|
871
|
+
if (fillElapsed > 1000) {
|
|
872
|
+
awsLogDebugLevel(
|
|
873
|
+
2,
|
|
874
|
+
`${entity.name}: slow fillInGaps ${depEntityName} sig=${depSigKeys} ret=${depRetKeys} ${fillElapsed}ms`,
|
|
875
|
+
);
|
|
876
|
+
}
|
|
739
877
|
|
|
740
878
|
// Trace clearAttributesFromMapping on dependency schemas
|
|
741
879
|
transformationTracer.traceSchemaTransform(
|
|
@@ -760,15 +898,46 @@ export default function generateDataStructure({
|
|
|
760
898
|
}
|
|
761
899
|
}
|
|
762
900
|
|
|
901
|
+
awsLogDebugLevel(
|
|
902
|
+
1,
|
|
903
|
+
`${entity.name}: dep schema processing: ${depProcessed} deps in ${Date.now() - depStart}ms`,
|
|
904
|
+
);
|
|
905
|
+
awsLogDebugLevel(
|
|
906
|
+
1,
|
|
907
|
+
`Dedup + dep schema processing for ${entity.name}: ${Date.now() - dedupStart}ms`,
|
|
908
|
+
);
|
|
909
|
+
|
|
763
910
|
// Transformation tracing: capture after deduplication
|
|
911
|
+
const dedupSnapshotStart = Date.now();
|
|
764
912
|
transformationTracer.snapshot(entity.name, 'deduplicated', {
|
|
765
913
|
signatureSchema: mergedDataStructure.signatureSchema,
|
|
766
914
|
returnValueSchema: mergedDataStructure.returnValueSchema,
|
|
767
915
|
dependencySchemas: mergedDataStructure.dependencySchemas,
|
|
768
916
|
});
|
|
769
917
|
|
|
918
|
+
awsLogDebugLevel(
|
|
919
|
+
1,
|
|
920
|
+
`Dedup snapshot for ${entity.name}: ${Date.now() - dedupSnapshotStart}ms`,
|
|
921
|
+
);
|
|
922
|
+
|
|
770
923
|
analysis.metadata ||= {};
|
|
771
924
|
analysis.metadata.mergedDataStructure = mergedDataStructure;
|
|
925
|
+
if (mergeTimedOut) {
|
|
926
|
+
(analysis.metadata as any).mergeTimedOut = true;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
const checkGenDeadline = (phase: string) => {
|
|
930
|
+
if (Date.now() > genDeadline) {
|
|
931
|
+
throw new DataStructureTimeoutError(
|
|
932
|
+
entity.name,
|
|
933
|
+
Date.now() - mergeStart,
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
awsLogDebugLevel(
|
|
937
|
+
1,
|
|
938
|
+
`${entity.name}: ${phase} complete (${Date.now() - mergeStart}ms total)`,
|
|
939
|
+
);
|
|
940
|
+
};
|
|
772
941
|
|
|
773
942
|
// Enrich mocked dependency array types with fields from child component signatures
|
|
774
943
|
// This ensures that when getSurveysAction returns { data: array }, and SurveyCard
|
|
@@ -787,6 +956,8 @@ export default function generateDataStructure({
|
|
|
787
956
|
),
|
|
788
957
|
);
|
|
789
958
|
|
|
959
|
+
checkGenDeadline('enrichArrayTypes');
|
|
960
|
+
|
|
790
961
|
// Transformation tracing: capture after array types enriched
|
|
791
962
|
transformationTracer.snapshot(entity.name, 'arrayTypesEnriched', {
|
|
792
963
|
signatureSchema: mergedDataStructure.signatureSchema,
|
|
@@ -811,6 +982,8 @@ export default function generateDataStructure({
|
|
|
811
982
|
),
|
|
812
983
|
);
|
|
813
984
|
|
|
985
|
+
checkGenDeadline('enrichUnknownTypes');
|
|
986
|
+
|
|
814
987
|
// Transformation tracing: capture after unknown types enriched
|
|
815
988
|
transformationTracer.snapshot(entity.name, 'unknownTypesEnriched', {
|
|
816
989
|
signatureSchema: mergedDataStructure.signatureSchema,
|
|
@@ -831,6 +1004,8 @@ export default function generateDataStructure({
|
|
|
831
1004
|
{ entityName: entity.name },
|
|
832
1005
|
);
|
|
833
1006
|
|
|
1007
|
+
checkGenDeadline('gatherDataForMocks');
|
|
1008
|
+
|
|
834
1009
|
// Transformation tracing: capture after dataForMocks gathered
|
|
835
1010
|
transformationTracer.snapshot(entity.name, 'dataForMocksGathered', {
|
|
836
1011
|
signatureSchema: mergedDataStructure.signatureSchema,
|
|
@@ -860,6 +1035,8 @@ export default function generateDataStructure({
|
|
|
860
1035
|
}
|
|
861
1036
|
}
|
|
862
1037
|
|
|
1038
|
+
checkGenDeadline('mergeChildDataForMocks');
|
|
1039
|
+
|
|
863
1040
|
const finalizedArgumentsSchema = { ...mergedDataStructure.signatureSchema };
|
|
864
1041
|
|
|
865
1042
|
// Trace fillInDirectSchemaGapsAndUnknowns
|
|
@@ -880,9 +1057,13 @@ export default function generateDataStructure({
|
|
|
880
1057
|
{ stage: 'finalization' },
|
|
881
1058
|
);
|
|
882
1059
|
|
|
1060
|
+
checkGenDeadline('fillInGaps+clearAttributes');
|
|
1061
|
+
|
|
883
1062
|
const argumentsSchema = convertDotNotation(finalizedArgumentsSchema)
|
|
884
1063
|
.signature as JsonTypeDefinition[];
|
|
885
1064
|
|
|
1065
|
+
checkGenDeadline('convertDotNotation');
|
|
1066
|
+
|
|
886
1067
|
analysis.metadata.scenariosDataStructure = {
|
|
887
1068
|
arguments: argumentsSchema,
|
|
888
1069
|
dataForMocks,
|