@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.2a88920

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.
Files changed (437) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +5 -5
  4. package/analyzer-template/packages/ai/index.ts +15 -2
  5. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +87 -51
  6. package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +98 -9
  8. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +139 -23
  9. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +6 -126
  10. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +555 -28
  11. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +88 -7
  12. package/analyzer-template/packages/ai/src/lib/completionCall.ts +198 -34
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +772 -243
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +205 -0
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +10 -2
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +43 -1
  19. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +122 -15
  20. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +160 -0
  21. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
  22. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +319 -88
  23. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
  24. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +156 -0
  25. package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
  26. package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
  27. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +642 -7
  28. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
  29. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +383 -6
  30. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
  31. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1299 -51
  32. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
  33. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
  34. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
  35. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
  36. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
  37. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +23 -6
  38. package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
  39. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
  40. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
  41. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
  42. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
  43. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
  44. package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
  45. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
  46. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
  47. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
  48. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
  49. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
  50. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
  51. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +30 -19
  52. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +14 -4
  53. package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
  54. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
  55. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
  56. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
  57. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
  58. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +189 -76
  59. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +29 -0
  60. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +77 -9
  61. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
  62. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +276 -17
  63. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
  64. package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
  65. package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
  66. package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
  67. package/analyzer-template/packages/aws/package.json +2 -2
  68. package/analyzer-template/packages/database/src/lib/kysely/db.ts +8 -1
  69. package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
  70. package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
  71. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
  72. package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
  73. package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
  74. package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
  75. package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
  76. package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
  77. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
  78. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  79. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +8 -1
  80. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  81. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  82. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
  83. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
  84. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
  85. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  86. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
  87. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
  88. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
  89. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
  90. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  91. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
  92. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  93. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
  94. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
  95. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
  96. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
  97. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
  98. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
  99. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
  100. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
  101. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
  102. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
  103. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  104. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
  105. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  106. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
  107. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
  108. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
  109. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
  110. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  111. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
  112. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  113. package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
  114. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  115. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  116. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
  117. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  118. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
  119. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
  120. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  121. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  122. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  123. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  124. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
  125. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  126. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
  127. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
  128. package/analyzer-template/packages/github/package.json +1 -1
  129. package/analyzer-template/packages/types/index.ts +1 -0
  130. package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
  131. package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
  132. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
  133. package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
  134. package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
  135. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  136. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  137. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
  138. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  139. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
  140. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
  141. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  142. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  143. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  144. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  145. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
  146. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  147. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
  148. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
  149. package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
  150. package/analyzer-template/playwright/capture.ts +20 -8
  151. package/analyzer-template/playwright/captureStatic.ts +1 -1
  152. package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
  153. package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
  154. package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
  155. package/analyzer-template/project/constructMockCode.ts +367 -37
  156. package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
  157. package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
  158. package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
  159. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
  160. package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
  161. package/analyzer-template/project/orchestrateCapture.ts +71 -6
  162. package/analyzer-template/project/reconcileMockDataKeys.ts +152 -9
  163. package/analyzer-template/project/runAnalysis.ts +4 -0
  164. package/analyzer-template/project/start.ts +35 -11
  165. package/analyzer-template/project/writeMockDataTsx.ts +127 -4
  166. package/analyzer-template/project/writeScenarioComponents.ts +101 -8
  167. package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
  168. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
  169. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
  170. package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
  171. package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
  172. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
  173. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
  174. package/background/src/lib/virtualized/project/constructMockCode.js +300 -7
  175. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  176. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
  177. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
  178. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
  179. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
  180. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
  181. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
  182. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
  183. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  184. package/background/src/lib/virtualized/project/orchestrateCapture.js +58 -6
  185. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  186. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +126 -9
  187. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  188. package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
  189. package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
  190. package/background/src/lib/virtualized/project/start.js +32 -11
  191. package/background/src/lib/virtualized/project/start.js.map +1 -1
  192. package/background/src/lib/virtualized/project/writeMockDataTsx.js +101 -4
  193. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  194. package/background/src/lib/virtualized/project/writeScenarioComponents.js +57 -8
  195. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  196. package/codeyam-cli/src/cli.js +2 -0
  197. package/codeyam-cli/src/cli.js.map +1 -1
  198. package/codeyam-cli/src/commands/debug.js +7 -5
  199. package/codeyam-cli/src/commands/debug.js.map +1 -1
  200. package/codeyam-cli/src/commands/memory.js +273 -0
  201. package/codeyam-cli/src/commands/memory.js.map +1 -0
  202. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +4 -0
  203. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  204. package/codeyam-cli/src/utils/analysisRunner.js +21 -2
  205. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  206. package/codeyam-cli/src/utils/install-skills.js +42 -6
  207. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  208. package/codeyam-cli/src/utils/queue/job.js +1 -0
  209. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  210. package/codeyam-cli/src/utils/queue/manager.js +6 -0
  211. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  212. package/codeyam-cli/src/utils/rules/index.js +5 -0
  213. package/codeyam-cli/src/utils/rules/index.js.map +1 -0
  214. package/codeyam-cli/src/utils/rules/parser.js +106 -0
  215. package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
  216. package/codeyam-cli/src/utils/rules/pathMatcher.js +18 -0
  217. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
  218. package/codeyam-cli/src/utils/rules/staleness.js +132 -0
  219. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
  220. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +2 -0
  221. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  222. package/codeyam-cli/src/webserver/app/lib/database.js +7 -3
  223. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  224. package/codeyam-cli/src/webserver/bootstrap.js +40 -0
  225. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  226. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-DsN1wKrm.js +11 -0
  227. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-DLqD3qNt.js} +1 -1
  228. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-Ba2JVPzP.js} +1 -1
  229. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CEleMv_j.js → InlineSpinner-C8lyxW9k.js} +1 -1
  230. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-aht4aafF.js} +2 -2
  231. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-CVtiBnY5.js} +1 -1
  232. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-B0GLXMsr.js} +1 -1
  233. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-xgeCVgSM.js} +1 -1
  234. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-OApQuNyq.js +16 -0
  235. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-DuDvi0jm.js} +1 -1
  236. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-DzccYyI8.js} +3 -13
  237. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-DyFZkK0l.js} +1 -1
  238. package/codeyam-cli/src/webserver/build/client/assets/_index-BwqWJOgH.js +11 -0
  239. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BwavGCpm.js +32 -0
  240. package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
  241. package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
  242. package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
  243. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-Cx24_aWc.js} +1 -1
  244. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-EPOLDU6W-CXRTFQ3F.js} +1 -1
  245. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-BOARzkeR.js} +1 -1
  246. package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +6 -0
  247. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-BdhJEx6B.js} +1 -1
  248. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BBnGWYga.js +1 -0
  249. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-BJUiQqZF.js} +12 -12
  250. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js → entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js} +1 -1
  251. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-wDWZZO1W.js → entity._sha_.create-scenario-D1T4TGjf.js} +1 -1
  252. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-CTBG2mmz.js} +1 -1
  253. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-CS2cb_eZ.js} +1 -1
  254. package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +6 -0
  255. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-DMJ7zii9.js} +1 -1
  256. package/codeyam-cli/src/webserver/build/client/assets/files-CJ6lTdTA.js +1 -0
  257. package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-CPTZZ-JZ.js} +8 -8
  258. package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +1 -0
  259. package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-B1h680n5.js} +1 -1
  260. package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-lzqtyFU8.js} +1 -1
  261. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-B7B9V-bu.js} +1 -1
  262. package/codeyam-cli/src/webserver/build/client/assets/manifest-a78b90a2.js +1 -0
  263. package/codeyam-cli/src/webserver/build/client/assets/memory--GCbFsBE.js +92 -0
  264. package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +62 -0
  265. package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-CxXUmBSd.js} +1 -1
  266. package/codeyam-cli/src/webserver/build/client/assets/{settings-B2eDuBj8.js → settings-CS5f3WzT.js} +1 -1
  267. package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-DwFIBT09.js} +1 -1
  268. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-B6LgvRJg.js} +1 -1
  269. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-C1v1PQzo.js} +1 -1
  270. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BUm0UVJm.js → useLastLogLine-aSv48UbS.js} +1 -1
  271. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-DYxHZQuP.js} +1 -1
  272. package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-mBRpZPiu.js} +1 -1
  273. package/codeyam-cli/src/webserver/build/server/assets/index-BM6TDT1Y.js +1 -0
  274. package/codeyam-cli/src/webserver/build/server/assets/server-build-dYC34MHw.js +257 -0
  275. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  276. package/codeyam-cli/src/webserver/build-info.json +5 -5
  277. package/codeyam-cli/templates/codeyam-memory-hook.sh +200 -0
  278. package/codeyam-cli/templates/codeyam:debug.md +47 -3
  279. package/codeyam-cli/templates/codeyam:diagnose.md +203 -25
  280. package/codeyam-cli/templates/codeyam:memory.md +341 -0
  281. package/codeyam-cli/templates/codeyam:new-rule.md +13 -0
  282. package/codeyam-cli/templates/rule-reflection-hook.py +160 -0
  283. package/codeyam-cli/templates/rules-instructions.md +93 -0
  284. package/package.json +8 -5
  285. package/packages/ai/index.js +7 -3
  286. package/packages/ai/index.js.map +1 -1
  287. package/packages/ai/src/lib/analyzeScope.js +70 -29
  288. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  289. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
  290. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
  291. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +78 -8
  292. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  293. package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
  294. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  295. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
  296. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
  297. package/packages/ai/src/lib/astScopes/processExpression.js +440 -27
  298. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  299. package/packages/ai/src/lib/completionCall.js +161 -30
  300. package/packages/ai/src/lib/completionCall.js.map +1 -1
  301. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +589 -166
  302. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  303. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
  304. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
  305. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
  306. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  307. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
  308. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
  309. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
  310. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
  311. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +41 -1
  312. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  313. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +104 -11
  314. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  315. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +159 -0
  316. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
  317. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
  318. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
  319. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +265 -79
  320. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  321. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
  322. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
  323. package/packages/ai/src/lib/dataStructureChunking.js +111 -0
  324. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
  325. package/packages/ai/src/lib/e2eDataTracking.js +241 -0
  326. package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
  327. package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
  328. package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
  329. package/packages/ai/src/lib/generateEntityScenarioData.js +525 -8
  330. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  331. package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
  332. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  333. package/packages/ai/src/lib/generateExecutionFlows.js +281 -4
  334. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  335. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +946 -42
  336. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  337. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
  338. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
  339. package/packages/ai/src/lib/mergeStatements.js +70 -51
  340. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  341. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
  342. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  343. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
  344. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
  345. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +15 -7
  346. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  347. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
  348. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
  349. package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
  350. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
  351. package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
  352. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  353. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
  354. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  355. package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
  356. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  357. package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
  358. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  359. package/packages/analyze/src/lib/analysisContext.js +30 -5
  360. package/packages/analyze/src/lib/analysisContext.js.map +1 -1
  361. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
  362. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
  363. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
  364. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
  365. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
  366. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  367. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
  368. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
  369. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
  370. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
  371. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
  372. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
  373. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +21 -9
  374. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  375. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +14 -4
  376. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  377. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
  378. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
  379. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
  380. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  381. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
  382. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  383. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
  384. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  385. package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
  386. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  387. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +160 -68
  388. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  389. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +25 -8
  390. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  391. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +71 -9
  392. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  393. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
  394. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  395. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +233 -9
  396. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  397. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
  398. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  399. package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
  400. package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
  401. package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
  402. package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
  403. package/packages/database/src/lib/kysely/db.js +8 -1
  404. package/packages/database/src/lib/kysely/db.js.map +1 -1
  405. package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
  406. package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  407. package/packages/database/src/lib/loadAnalyses.js +45 -2
  408. package/packages/database/src/lib/loadAnalyses.js.map +1 -1
  409. package/packages/database/src/lib/loadAnalysis.js +8 -0
  410. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  411. package/packages/database/src/lib/loadBranch.js +11 -1
  412. package/packages/database/src/lib/loadBranch.js.map +1 -1
  413. package/packages/database/src/lib/loadCommit.js +7 -0
  414. package/packages/database/src/lib/loadCommit.js.map +1 -1
  415. package/packages/database/src/lib/loadCommits.js +22 -1
  416. package/packages/database/src/lib/loadCommits.js.map +1 -1
  417. package/packages/database/src/lib/loadEntities.js +23 -4
  418. package/packages/database/src/lib/loadEntities.js.map +1 -1
  419. package/packages/database/src/lib/loadEntityBranches.js +9 -0
  420. package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
  421. package/packages/database/src/lib/updateCommitMetadata.js +5 -4
  422. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  423. package/packages/types/index.js.map +1 -1
  424. package/packages/utils/src/lib/safeFileName.js +29 -3
  425. package/packages/utils/src/lib/safeFileName.js.map +1 -1
  426. package/scripts/finalize-analyzer.cjs +3 -3
  427. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
  428. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
  429. package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
  430. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
  431. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
  432. package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
  433. package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
  434. package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
  435. package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
  436. package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
  437. package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
@@ -205,16 +205,88 @@ export default function fillInSchemaGapsAndUnknowns(
205
205
  }
206
206
  }
207
207
 
208
+ /**
209
+ * Pre-built indexes that can be reused across multiple calls to fillInDirectSchemaGapsAndUnknowns.
210
+ * Build once with buildSchemaIndexes(), then pass to all calls processing the same schema.
211
+ */
212
+ export interface SchemaIndexes {
213
+ functionKeysMapping: Record<string, string[]>;
214
+ prefixMaxDepth: Map<string, number>;
215
+ }
216
+
217
+ /**
218
+ * Build indexes for a schema that can be reused across multiple calls.
219
+ * This avoids rebuilding indexes (~1-2 seconds for 18k keys) on every call.
220
+ *
221
+ * @param schema - The schema to build indexes from (typically the full dependency schema)
222
+ * @returns Indexes that can be passed to fillInDirectSchemaGapsAndUnknowns
223
+ */
224
+ export function buildSchemaIndexes(
225
+ schema: Record<string, string>,
226
+ ): SchemaIndexes {
227
+ // Build functionKeysMapping + prefixMaxDepth in a single pass
228
+ // Avoid repeated split/join work by caching parts and building prefixes incrementally.
229
+ const functionKeysMapping: Record<string, string[]> = {};
230
+ const prefixMaxDepth = new Map<string, number>();
231
+ const partsCache = new Map<string, string[]>();
232
+
233
+ for (const key in schema) {
234
+ const parts = getCachedParts(partsCache, key);
235
+ const lastPart = parts[parts.length - 1];
236
+ const prefixes = buildPrefixParts(parts);
237
+
238
+ if (
239
+ key.endsWith(')') ||
240
+ schema[key] === 'function' ||
241
+ lastPart === 'length'
242
+ ) {
243
+ const allButLastPart = parts.length > 1 ? prefixes[parts.length - 2] : '';
244
+ functionKeysMapping[allButLastPart] ||= [];
245
+ functionKeysMapping[allButLastPart].push(lastPart);
246
+ }
247
+
248
+ for (let i = 0; i < prefixes.length; i++) {
249
+ const prefix = prefixes[i];
250
+ const existingMax = prefixMaxDepth.get(prefix) ?? 0;
251
+ if (parts.length > existingMax) {
252
+ prefixMaxDepth.set(prefix, parts.length);
253
+ }
254
+ }
255
+ }
256
+
257
+ return { functionKeysMapping, prefixMaxDepth };
258
+ }
259
+
208
260
  export function fillInDirectSchemaGapsAndUnknowns({
209
261
  scopeName,
210
262
  schema,
211
263
  mergedSchema,
212
264
  attempts = 0,
265
+ // Pre-built indexes from buildSchemaIndexes() - use for cross-call caching
266
+ prebuiltIndexes,
267
+ // Internal: pre-computed indexes to avoid rebuilding on recursion
268
+ _functionKeysMapping,
269
+ _prefixMaxDepth,
270
+ _partsCache,
271
+ _prefixPartsCache,
272
+ _knownTypeCache,
273
+ _guessTypeCache,
274
+ _nameHintCache,
213
275
  }: {
214
276
  scopeName?: string;
215
277
  schema: Record<string, string>;
216
278
  mergedSchema?: Record<string, string>;
217
279
  attempts?: number;
280
+ /** Pre-built indexes from buildSchemaIndexes() - pass to reuse across multiple calls */
281
+ prebuiltIndexes?: SchemaIndexes;
282
+ // Internal: pre-computed indexes to avoid rebuilding on recursion (used by recursive calls)
283
+ _functionKeysMapping?: Record<string, string[]>;
284
+ _prefixMaxDepth?: Map<string, number>;
285
+ _partsCache?: Map<string, string[]>;
286
+ _prefixPartsCache?: Map<string, string[]>;
287
+ _knownTypeCache?: Map<string, string | undefined>;
288
+ _guessTypeCache?: Map<string, string | undefined>;
289
+ _nameHintCache?: Map<string, string | undefined>;
218
290
  }) {
219
291
  try {
220
292
  const existingSchema = (path: any) => {
@@ -225,105 +297,204 @@ export function fillInDirectSchemaGapsAndUnknowns({
225
297
  }
226
298
  };
227
299
 
228
- const functionKeysMapping = [...Object.keys(schema)]
229
- .filter((key) => {
230
- if (key.endsWith(')') || schema[key] === 'function') return true;
231
- const parts = splitOutsideParenthesesAndArrays(key);
232
- if (parts[parts.length - 1] === 'length') return true;
233
- })
234
- .reduce(
235
- (acc, key) => {
236
- const parts = splitOutsideParenthesesAndArrays(key);
237
- const allButLastPart = joinParenthesesAndArrays(parts.slice(0, -1));
300
+ const partsCache = _partsCache ?? new Map<string, string[]>();
301
+ const prefixPartsCache = _prefixPartsCache ?? new Map<string, string[]>();
302
+ const knownTypeCache =
303
+ _knownTypeCache ?? new Map<string, string | undefined>();
304
+ const guessTypeCache =
305
+ _guessTypeCache ?? new Map<string, string | undefined>();
306
+ const nameHintCache =
307
+ _nameHintCache ?? new Map<string, string | undefined>();
308
+
309
+ const getParts = (path: string) => getCachedParts(partsCache, path);
310
+ const getPrefixParts = (path: string) => {
311
+ const cached = prefixPartsCache.get(path);
312
+ if (cached) return cached;
313
+ const prefixes = buildPrefixParts(getParts(path));
314
+ prefixPartsCache.set(path, prefixes);
315
+ return prefixes;
316
+ };
317
+
318
+ // Index resolution priority:
319
+ // 1. _functionKeysMapping/_prefixMaxDepth (from recursive calls within this invocation)
320
+ // 2. prebuiltIndexes (from cross-call caching - built once, reused across multiple calls)
321
+ // 3. Build new indexes (fallback - expensive for large schemas)
322
+ const functionKeysMapping =
323
+ _functionKeysMapping ??
324
+ prebuiltIndexes?.functionKeysMapping ??
325
+ (() => {
326
+ const mapping: Record<string, string[]> = {};
327
+ for (const key in schema) {
328
+ const parts = getParts(key);
238
329
  const lastPart = parts[parts.length - 1];
239
- acc[allButLastPart] ||= [];
240
- acc[allButLastPart].push(lastPart);
241
- return acc;
242
- },
243
- {} as Record<string, string[]>,
244
- );
330
+ if (
331
+ key.endsWith(')') ||
332
+ schema[key] === 'function' ||
333
+ lastPart === 'length'
334
+ ) {
335
+ const prefixes = getPrefixParts(key);
336
+ const allButLastPart =
337
+ parts.length > 1 ? prefixes[parts.length - 2] : '';
338
+ mapping[allButLastPart] ||= [];
339
+ mapping[allButLastPart].push(lastPart);
340
+ }
341
+ }
342
+ return mapping;
343
+ })();
344
+
345
+ // Build prefix index for O(1) lookups in checkIfObjectOrFunction
346
+ // Maps each prefix to the max depth of keys that have this prefix
347
+ // This replaces O(n) scans with O(1) lookups, fixing the O(n²) bottleneck
348
+ let prefixMaxDepth =
349
+ _prefixMaxDepth ?? prebuiltIndexes?.prefixMaxDepth ?? null;
350
+ if (!prefixMaxDepth) {
351
+ prefixMaxDepth = new Map<string, number>();
352
+ const targetSchema = mergedSchema ?? schema;
353
+ for (const key in targetSchema) {
354
+ const keyParts = getParts(key);
355
+ const prefixes = buildPrefixParts(keyParts);
356
+ // Record each prefix of this key with its max depth
357
+ for (let i = 0; i < prefixes.length; i++) {
358
+ const prefix = prefixes[i];
359
+ const existingMax = prefixMaxDepth.get(prefix) ?? 0;
360
+ if (keyParts.length > existingMax) {
361
+ prefixMaxDepth.set(prefix, keyParts.length);
362
+ }
363
+ }
364
+ }
365
+ }
245
366
 
246
- let changeMade = false;
247
- const guessTypeForPath = (path: string, defaultType = 'string') => {
248
- let knownType = checkIfKnownType(path, functionKeysMapping);
249
- if (!knownType) {
250
- // Use mergedSchema for type inference if available (has more complete nested paths)
251
- // Fall back to schema if mergedSchema is not provided
252
- knownType = checkIfObjectOrFunction(path, mergedSchema ?? schema);
367
+ // O(1) replacement for checkIfObjectOrFunction
368
+ const checkIfObjectOrFunctionFast = (path: string): string | undefined => {
369
+ const maxDepth = prefixMaxDepth!.get(path);
370
+
371
+ if (maxDepth === undefined) return undefined; // No key starts with this path
372
+
373
+ const pathParts = getParts(path);
374
+ // Check if path's last part ends with ')' → function
375
+ const lastPart = pathParts[pathParts.length - 1];
376
+ if (lastPart?.endsWith(')')) {
377
+ return 'function';
253
378
  }
254
379
 
255
- if (knownType && schema[path] !== knownType) {
256
- return knownType;
380
+ // Check if there are deeper keys
381
+ if (maxDepth > pathParts.length) {
382
+ return 'object';
257
383
  }
258
384
 
259
- const keyParts = splitOutsideParenthesesAndArrays(path);
260
- const lastPart = keyParts[keyParts.length - 1];
385
+ return undefined;
386
+ };
261
387
 
388
+ let changeMade = false;
389
+ const getKnownType = (path: string) => {
390
+ if (knownTypeCache.has(path)) return knownTypeCache.get(path);
391
+ const known = checkIfKnownType(path, functionKeysMapping);
392
+ knownTypeCache.set(path, known);
393
+ return known;
394
+ };
395
+ const guessTypeFromName = (lastPart: string, defaultType: string) => {
396
+ if (nameHintCache.has(lastPart)) {
397
+ return nameHintCache.get(lastPart) ?? defaultType;
398
+ }
399
+
400
+ let hint: string | undefined;
262
401
  if (isLikelyBoolean(lastPart)) {
263
- return 'boolean';
402
+ hint = 'boolean';
264
403
  } else if (isLikelyDate(lastPart)) {
265
- return 'date';
404
+ hint = 'date';
266
405
  } else if (isLikelyAction(lastPart)) {
267
- return 'function';
406
+ hint = 'function';
268
407
  } else if (pluralize.isPlural(lastPart)) {
269
- return 'number';
270
- } else {
271
- return defaultType;
408
+ // Default to number instead of array - safer for JSX rendering
409
+ // Arrays cause "Objects are not valid as a React child" errors when rendered directly
410
+ hint = 'number';
272
411
  }
412
+
413
+ nameHintCache.set(lastPart, hint);
414
+ return hint ?? defaultType;
415
+ };
416
+ const guessTypeForPath = (path: string, defaultType = 'string') => {
417
+ const cacheKey = `${path}|${defaultType}`;
418
+ if (guessTypeCache.has(cacheKey)) {
419
+ return guessTypeCache.get(cacheKey);
420
+ }
421
+
422
+ let knownType = getKnownType(path);
423
+ if (!knownType) {
424
+ // Use optimized O(1) prefix lookup instead of O(n) scan
425
+ knownType = checkIfObjectOrFunctionFast(path);
426
+ }
427
+
428
+ if (knownType) {
429
+ guessTypeCache.set(cacheKey, knownType);
430
+ return knownType;
431
+ }
432
+
433
+ const keyParts = getParts(path);
434
+ const lastPart = keyParts[keyParts.length - 1];
435
+ const guessed = guessTypeFromName(lastPart, defaultType);
436
+ guessTypeCache.set(cacheKey, guessed);
437
+ return guessed;
273
438
  };
274
439
 
275
440
  for (const key in schema) {
276
441
  if (!schema[key]) schema[key] = 'unknown';
277
442
  if (schema[key].includes(' | unknown')) {
278
- schema[key] = schema[key].replace(' | unknown', '');
279
- changeMade = true;
443
+ const cleaned = schema[key].replace(' | unknown', '');
444
+ if (schema[key] !== cleaned) {
445
+ schema[key] = cleaned;
446
+ changeMade = true;
447
+ }
280
448
  } else if (schema[key].startsWith('unknown | ')) {
281
449
  // Handle "unknown | undefined" -> "string | undefined"
282
450
  const remainingType = schema[key].substring('unknown | '.length);
283
451
  const newType = guessTypeForPath(key, 'string');
284
452
  if (newType) {
285
- schema[key] = `${newType} | ${remainingType}`;
286
- changeMade = true;
453
+ const replacement = `${newType} | ${remainingType}`;
454
+ if (schema[key] !== replacement) {
455
+ schema[key] = replacement;
456
+ changeMade = true;
457
+ }
287
458
  }
288
459
  } else if (schema[key] === 'unknown') {
289
460
  const newType = guessTypeForPath(key, 'string');
290
- if (newType) {
461
+ if (newType && schema[key] !== newType) {
291
462
  schema[key] = newType;
292
463
  changeMade = true;
293
464
  }
294
465
  }
295
466
 
296
- const keyParts = splitOutsideParenthesesAndArrays(key);
467
+ const keyParts = getParts(key);
468
+ const prefixParts = getPrefixParts(key);
297
469
  for (let i = 0; i < keyParts.length; i++) {
298
- const subPathParts = keyParts.slice(0, i + 1);
299
- const lastSubPathPart = subPathParts[subPathParts.length - 1];
300
-
301
- const previousSubPathParts = subPathParts.slice(0, i);
302
- if (previousSubPathParts.length === 0) continue;
303
-
304
- const previousSubPath = joinParenthesesAndArrays(previousSubPathParts);
305
-
306
- if (
307
- cleanOutBoundary(lastSubPathPart).match(/\[\d*\]/) &&
308
- !lastSubPathPart.match(/signature\[\d+\]/)
309
- ) {
310
- // Fix 39: Don't overwrite explicit 'object' types with 'array'
311
- // This handles spurious [] paths from components like JsonNode that handle
312
- // both arrays and objects. When metadata is explicitly typed as 'object',
313
- // paths like metadata[] (from dynamic iteration) should not change it.
314
- if (
315
- schema[previousSubPath] !== 'array' &&
316
- schema[previousSubPath] !== 'object'
317
- ) {
318
- schema[previousSubPath] = 'array';
319
- changeMade = true;
470
+ if (i === 0) continue;
471
+ const lastSubPathPart = keyParts[i];
472
+ const previousSubPath = prefixParts[i - 1];
473
+ const isSignatureIndex =
474
+ lastSubPathPart.includes('signature[') &&
475
+ SIGNATURE_INDEX_REGEX.test(lastSubPathPart);
476
+
477
+ if (lastSubPathPart.includes('[')) {
478
+ const cleaned = cleanOutBoundary(lastSubPathPart);
479
+ if (cleaned.match(/\[\d*\]/) && !isSignatureIndex) {
480
+ // Fix 39: Don't overwrite explicit 'object' types with 'array'
481
+ // This handles spurious [] paths from components like JsonNode that handle
482
+ // both arrays and objects. When metadata is explicitly typed as 'object',
483
+ // paths like metadata[] (from dynamic iteration) should not change it.
484
+ if (
485
+ schema[previousSubPath] !== 'array' &&
486
+ schema[previousSubPath] !== 'object'
487
+ ) {
488
+ schema[previousSubPath] = 'array';
489
+ changeMade = true;
490
+ }
320
491
  }
321
492
  }
322
493
 
323
494
  const isFunction =
324
495
  lastSubPathPart.endsWith(')') ||
325
496
  lastSubPathPart === 'functionCallReturnValue' ||
326
- lastSubPathPart.match(/signature\[\d+\]/);
497
+ isSignatureIndex;
327
498
 
328
499
  if (
329
500
  !isFunction &&
@@ -331,8 +502,7 @@ export function fillInDirectSchemaGapsAndUnknowns({
331
502
  schema[previousSubPath],
332
503
  )
333
504
  ) {
334
- const newValue =
335
- checkIfKnownType(previousSubPath, functionKeysMapping) ?? 'object';
505
+ const newValue = getKnownType(previousSubPath) ?? 'object';
336
506
 
337
507
  if (
338
508
  !schema[previousSubPath] ||
@@ -347,8 +517,7 @@ export function fillInDirectSchemaGapsAndUnknowns({
347
517
  if (isFunction && !existingSchema(previousSubPath)) {
348
518
  schema[previousSubPath] = previousSubPath.endsWith(')')
349
519
  ? 'function'
350
- : (checkIfKnownType(previousSubPath, functionKeysMapping) ??
351
- 'object');
520
+ : (getKnownType(previousSubPath) ?? 'object');
352
521
  changeMade = true;
353
522
  }
354
523
 
@@ -358,10 +527,12 @@ export function fillInDirectSchemaGapsAndUnknowns({
358
527
  const functionReturnValuePath = `${previousSubPath}.functionCallReturnValue`;
359
528
 
360
529
  // Extract the method name from lastSubPathPart (e.g., "then()" -> "then")
361
- const methodName = lastSubPathPart.split('(')[0];
362
- const isPromiseMethod = ['then', 'catch', 'finally'].includes(
363
- methodName,
364
- );
530
+ const parenIndex = lastSubPathPart.indexOf('(');
531
+ const methodName =
532
+ parenIndex === -1
533
+ ? lastSubPathPart
534
+ : lastSubPathPart.slice(0, parenIndex);
535
+ const isPromiseMethod = PROMISE_METHODS.has(methodName);
365
536
  const isPreviousAsync = schema[previousSubPath] === 'async-function';
366
537
 
367
538
  // Don't set to 'function' if this is a promise method on an async function
@@ -386,6 +557,15 @@ export function fillInDirectSchemaGapsAndUnknowns({
386
557
  schema,
387
558
  mergedSchema,
388
559
  attempts: ++attempts,
560
+ prebuiltIndexes,
561
+ // Pass pre-computed indexes to avoid rebuilding on each recursive call
562
+ _functionKeysMapping: functionKeysMapping,
563
+ _prefixMaxDepth: prefixMaxDepth,
564
+ _partsCache: partsCache,
565
+ _prefixPartsCache: prefixPartsCache,
566
+ _knownTypeCache: knownTypeCache,
567
+ _guessTypeCache: guessTypeCache,
568
+ _nameHintCache: nameHintCache,
389
569
  });
390
570
  }
391
571
 
@@ -395,9 +575,10 @@ export function fillInDirectSchemaGapsAndUnknowns({
395
575
  // However, if the parent could be an 'object' or other type, keep .length as it may be
396
576
  // a custom property.
397
577
  for (const key of Object.keys(schema)) {
398
- const parts = splitOutsideParenthesesAndArrays(key);
578
+ const parts = getParts(key);
399
579
  if (parts[parts.length - 1] === 'length') {
400
- const parentPath = joinParenthesesAndArrays(parts.slice(0, -1));
580
+ const prefixes = getPrefixParts(key);
581
+ const parentPath = parts.length > 1 ? prefixes[parts.length - 2] : '';
401
582
  const parentType = schema[parentPath];
402
583
  if (parentType) {
403
584
  // Split union types and filter out nullable parts
@@ -434,6 +615,35 @@ export function fillInDirectSchemaGapsAndUnknowns({
434
615
  }
435
616
  }
436
617
 
618
+ const SIGNATURE_INDEX_REGEX = /signature\[\d+\]/;
619
+ const PROMISE_METHODS = new Set(['then', 'catch', 'finally']);
620
+
621
+ function getCachedParts(cache: Map<string, string[]>, path: string): string[] {
622
+ const cached = cache.get(path);
623
+ if (cached) return cached;
624
+ const parts = splitOutsideParenthesesAndArrays(path);
625
+ cache.set(path, parts);
626
+ return parts;
627
+ }
628
+
629
+ function buildPrefixParts(parts: string[]): string[] {
630
+ if (parts.length === 0) return [];
631
+ const prefixes = new Array(parts.length);
632
+ let prefix = '';
633
+ for (let i = 0; i < parts.length; i++) {
634
+ const part = parts[i];
635
+ if (i === 0) {
636
+ prefix = part;
637
+ } else if (part.startsWith('[') || part.startsWith('(')) {
638
+ prefix += part;
639
+ } else {
640
+ prefix += `.${part}`;
641
+ }
642
+ prefixes[i] = prefix;
643
+ }
644
+ return prefixes;
645
+ }
646
+
437
647
  function checkIfObjectOrFunction(path: string, schema: ScopeNode['schema']) {
438
648
  const pathParts = splitOutsideParenthesesAndArrays(path);
439
649
  for (const structureKey in schema) {
@@ -486,6 +696,17 @@ const STRONG_ARRAY_METHODS = new Set([
486
696
  'with',
487
697
  ]);
488
698
 
699
+ /**
700
+ * Check if a method call argument looks like a string literal.
701
+ * String literals start with ' or " (e.g., includes('foo'), indexOf("bar"))
702
+ */
703
+ function hasStringLiteralArgument(methodCall: string): boolean {
704
+ const parenIndex = methodCall.indexOf('(');
705
+ if (parenIndex === -1) return false;
706
+ const arg = methodCall.slice(parenIndex + 1).trim();
707
+ return arg.startsWith("'") || arg.startsWith('"') || arg.startsWith('`');
708
+ }
709
+
489
710
  function checkIfKnownType(
490
711
  key: string,
491
712
  functionAndAttributesKeysMapping: Record<string, string[]>,
@@ -495,19 +716,20 @@ function checkIfKnownType(
495
716
  let hasStrongArrayEvidence = false;
496
717
  let hasOnlyAmbiguousArrayMethods = true;
497
718
  let hasLengthAccess = false;
498
- let hasArrayStringAmbiguousMethod = false;
719
+ let hasIncludesOrIndexOfWithVariable = false;
720
+
721
+ const entries = functionAndAttributesKeysMapping[key];
722
+ if (!entries || entries.length === 0) return;
499
723
 
500
- for (const functionOrAttributeName of functionAndAttributesKeysMapping[key] ??
501
- []) {
724
+ for (const functionOrAttributeName of entries) {
502
725
  // Extract the method name without arguments for checking against ambiguous list
503
726
  const methodName = functionOrAttributeName.split('(')[0].trim();
504
727
 
728
+ const knownType = knownMethodCalls(functionOrAttributeName);
505
729
  const couldBeArray =
506
- knownMethodCalls(functionOrAttributeName).includes('array') ||
507
- functionOrAttributeName === 'length';
730
+ knownType.includes('array') || functionOrAttributeName === 'length';
508
731
  const couldBeString =
509
- knownMethodCalls(functionOrAttributeName).includes('string') ||
510
- functionOrAttributeName === 'length';
732
+ knownType.includes('string') || functionOrAttributeName === 'length';
511
733
 
512
734
  // Track .length access
513
735
  if (functionOrAttributeName === 'length') {
@@ -515,8 +737,15 @@ function checkIfKnownType(
515
737
  }
516
738
 
517
739
  // Track methods that exist on both arrays and strings (like includes, indexOf)
518
- if (couldBeArray && couldBeString && functionOrAttributeName !== 'length') {
519
- hasArrayStringAmbiguousMethod = true;
740
+ // Check if .includes() or .indexOf() is called with a variable argument (not a string literal).
741
+ // Pattern: arr.includes(item) -> likely array (checking if item exists)
742
+ // Pattern: str.includes('substring') -> likely string (checking for substring)
743
+ if (
744
+ (methodName === 'includes' || methodName === 'indexOf') &&
745
+ functionOrAttributeName.includes('(') &&
746
+ !hasStringLiteralArgument(functionOrAttributeName)
747
+ ) {
748
+ hasIncludesOrIndexOfWithVariable = true;
520
749
  }
521
750
 
522
751
  // Check if this is strong evidence of an array (unambiguous array methods)
@@ -549,18 +778,20 @@ function checkIfKnownType(
549
778
  return 'array';
550
779
  }
551
780
 
552
- // When we have BOTH .length AND an ambiguous method like .includes(),
553
- // prefer array. This pattern (checking .length AND calling .includes)
554
- // is very common with arrays (e.g., arr.length > 0 && arr.includes(x))
555
- // but rare with strings (you'd typically just call str.includes(x))
556
- if (isArray && hasLengthAccess && hasArrayStringAmbiguousMethod) {
781
+ // When .includes() or .indexOf() is called with a variable argument AND we have .length,
782
+ // prefer array. This pattern (arr.length > 0 && arr.includes(item)) is common for arrays.
783
+ // But str.includes('literal') is common for strings - that case is handled by hasStringLiteralArgument.
784
+ if (isArray && hasLengthAccess && hasIncludesOrIndexOfWithVariable) {
557
785
  return 'array';
558
786
  }
559
787
 
788
+ // When both array and string are possible, prefer string.
789
+ // Strings have .length, .slice(), .includes(), etc. just like arrays.
790
+ // We only infer 'array' if we have STRONG evidence (like .map, .filter, .reduce).
560
791
  if (isString) return 'string';
561
792
 
562
- // Only infer array if we have strong evidence OR not only ambiguous methods
563
- // This prevents router.push() from being incorrectly inferred as an array
793
+ // Only infer array if we have strong evidence (already handled above)
794
+ // or non-ambiguous array methods that don't exist on strings
564
795
  if (isArray && !hasOnlyAmbiguousArrayMethods) {
565
796
  return 'array';
566
797
  }
@@ -0,0 +1,129 @@
1
+ import { awsLog } from '~codeyam/utils';
2
+
3
+ /**
4
+ * Fixes null values for ID fields when the schema indicates they should be non-null numbers.
5
+ *
6
+ * The LLM sometimes generates `null` for ID fields (e.g., `"id": null`) when the schema
7
+ * type is `"number"` or `"number | undefined"` (but NOT `"number | null"`). This causes
8
+ * runtime issues when code checks `if (!data?.id)` expecting a truthy value.
9
+ *
10
+ * This function traverses data and schema together:
11
+ * - If field name looks like an ID field AND value is null AND schema doesn't allow null,
12
+ * replace with a valid default value (1 for numbers, generated UUID for strings)
13
+ *
14
+ * @param data The data object with potential null ID values
15
+ * @param schema The schema describing expected types
16
+ * @param path Current path in the data structure (for logging)
17
+ * @returns The data with null IDs fixed (mutates original)
18
+ */
19
+ export default function fixNullIdsBySchema<T>(
20
+ data: T,
21
+ schema: unknown,
22
+ path: string = '',
23
+ ): T {
24
+ // Handle null/undefined data
25
+ if (data === null || data === undefined) {
26
+ return data;
27
+ }
28
+
29
+ // Only process objects
30
+ if (typeof data !== 'object') {
31
+ return data;
32
+ }
33
+
34
+ // Handle arrays
35
+ if (Array.isArray(data)) {
36
+ // For arrays, the schema should be an array with one element describing the item type
37
+ const itemSchema = Array.isArray(schema) ? schema[0] : undefined;
38
+ for (let i = 0; i < data.length; i++) {
39
+ data[i] = fixNullIdsBySchema(data[i], itemSchema, `${path}[${i}]`);
40
+ }
41
+ return data;
42
+ }
43
+
44
+ // Handle objects
45
+ const dataObj = data as Record<string, unknown>;
46
+ const schemaObj = schema as Record<string, unknown> | undefined;
47
+
48
+ for (const key of Object.keys(dataObj)) {
49
+ const value = dataObj[key];
50
+ const fieldSchema = schemaObj?.[key];
51
+ const fieldPath = path ? `${path}.${key}` : key;
52
+
53
+ if (value === null && isIdField(key)) {
54
+ // Check if schema indicates this should be a non-null number
55
+ const replacement = getIdReplacementValue(fieldSchema);
56
+ if (replacement !== null) {
57
+ dataObj[key] = replacement;
58
+ awsLog(
59
+ `CodeYam: Fixed null ID field "${fieldPath}": null -> ${replacement}`,
60
+ );
61
+ }
62
+ } else if (typeof value === 'object' && value !== null) {
63
+ // Recursively process nested objects/arrays
64
+ fixNullIdsBySchema(value, fieldSchema, fieldPath);
65
+ }
66
+ }
67
+
68
+ return data;
69
+ }
70
+
71
+ /**
72
+ * Pattern for field names that are likely ID fields.
73
+ * Matches: id, Id, ID, userId, user_id, quoteId, quote_id, etc.
74
+ */
75
+ const ID_FIELD_PATTERNS = [
76
+ /^id$/i, // Exact match for "id", "Id", "ID"
77
+ /Id$/, // Ends with "Id" (camelCase): userId, quoteId
78
+ /_id$/i, // Ends with "_id" (snake_case): user_id, quote_id
79
+ /^.*_id$/i, // Contains "_id": some_object_id
80
+ ];
81
+
82
+ /**
83
+ * Determines if a field name looks like an ID field.
84
+ */
85
+ function isIdField(fieldName: string): boolean {
86
+ return ID_FIELD_PATTERNS.some((pattern) => pattern.test(fieldName));
87
+ }
88
+
89
+ /**
90
+ * Gets the replacement value for a null ID based on schema type.
91
+ * Returns null if the schema allows null values (no replacement needed).
92
+ *
93
+ * @param fieldSchema The schema type for the field
94
+ * @returns Replacement value (1 for numbers, generated string for strings) or null if no replacement
95
+ */
96
+ function getIdReplacementValue(fieldSchema: unknown): number | string | null {
97
+ // If no schema for this field, be conservative - don't replace
98
+ if (fieldSchema === undefined || fieldSchema === null) {
99
+ return null;
100
+ }
101
+
102
+ // If schema is a string type definition
103
+ if (typeof fieldSchema === 'string') {
104
+ // If schema explicitly allows null, don't replace
105
+ if (fieldSchema.includes('null')) {
106
+ return null;
107
+ }
108
+
109
+ // If schema is a number type, return 1 as default
110
+ if (
111
+ fieldSchema === 'number' ||
112
+ fieldSchema.startsWith('number') ||
113
+ fieldSchema.includes('number')
114
+ ) {
115
+ return 1;
116
+ }
117
+
118
+ // If schema is a string type, return a generated ID
119
+ if (
120
+ fieldSchema === 'string' ||
121
+ fieldSchema.startsWith('string') ||
122
+ fieldSchema.includes('string')
123
+ ) {
124
+ return 'id-1';
125
+ }
126
+ }
127
+
128
+ return null;
129
+ }