@codeyam/codeyam-cli 0.1.0-bleeding-edge.8afd3ee → 0.1.0-staging.09652b8

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 (220) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +1 -1
  4. package/analyzer-template/packages/ai/index.ts +0 -1
  5. package/analyzer-template/packages/ai/scripts/ai-test-matrix.mjs +424 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +6 -16
  7. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +197 -0
  8. package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +28 -2
  9. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +113 -4
  10. package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +1 -3
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +430 -7
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +12 -6
  13. package/analyzer-template/packages/ai/src/lib/generateChangesEntityDocumentation.ts +20 -2
  14. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +56 -160
  15. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +79 -265
  16. package/analyzer-template/packages/ai/src/lib/generateEntityDocumentation.ts +16 -2
  17. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +53 -154
  18. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +84 -254
  19. package/analyzer-template/packages/ai/src/lib/generateStatementAnalysis.ts +48 -71
  20. package/analyzer-template/packages/ai/src/lib/getLLMCallStats.ts +0 -14
  21. package/analyzer-template/packages/ai/src/lib/modelInfo.ts +15 -0
  22. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.ts +8 -33
  23. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +54 -62
  24. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +93 -109
  25. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.ts +8 -27
  26. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +33 -38
  27. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +30 -30
  28. package/analyzer-template/packages/ai/src/lib/types/index.ts +2 -0
  29. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +15 -7
  30. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +28 -21
  31. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.ts +18 -11
  32. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
  33. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
  34. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  35. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.d.ts.map +1 -1
  36. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
  37. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
  38. package/analyzer-template/packages/github/dist/utils/index.d.ts +1 -0
  39. package/analyzer-template/packages/github/dist/utils/index.d.ts.map +1 -1
  40. package/analyzer-template/packages/github/dist/utils/index.js +1 -0
  41. package/analyzer-template/packages/github/dist/utils/index.js.map +1 -1
  42. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
  43. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  44. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  45. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
  46. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  47. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  48. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
  49. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
  50. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  51. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  52. package/analyzer-template/packages/ui-components/src/scenario-editor/components/DataItemEditor.tsx +1 -1
  53. package/analyzer-template/packages/utils/dist/utils/index.d.ts +1 -0
  54. package/analyzer-template/packages/utils/dist/utils/index.d.ts.map +1 -1
  55. package/analyzer-template/packages/utils/dist/utils/index.js +1 -0
  56. package/analyzer-template/packages/utils/dist/utils/index.js.map +1 -1
  57. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
  58. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  59. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  60. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
  61. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  62. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  63. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
  64. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
  65. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  66. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  67. package/analyzer-template/packages/utils/index.ts +1 -0
  68. package/analyzer-template/packages/utils/src/lib/frameworks/getNextRoutePath.ts +2 -1
  69. package/analyzer-template/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.ts +2 -1
  70. package/analyzer-template/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.ts +33 -0
  71. package/analyzer-template/project/startScenarioCapture.ts +24 -0
  72. package/analyzer-template/project/trackGeneratedFiles.ts +41 -0
  73. package/analyzer-template/project/writeMockDataTsx.ts +94 -4
  74. package/analyzer-template/project/writeScenarioComponents.ts +35 -27
  75. package/background/src/lib/virtualized/project/startScenarioCapture.js +18 -0
  76. package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
  77. package/background/src/lib/virtualized/project/trackGeneratedFiles.js +30 -0
  78. package/background/src/lib/virtualized/project/trackGeneratedFiles.js.map +1 -0
  79. package/background/src/lib/virtualized/project/writeMockDataTsx.js +71 -3
  80. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  81. package/background/src/lib/virtualized/project/writeScenarioComponents.js +15 -11
  82. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  83. package/codeyam-cli/src/commands/init.js +4 -23
  84. package/codeyam-cli/src/commands/init.js.map +1 -1
  85. package/codeyam-cli/src/utils/webappDetection.js +2 -1
  86. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  87. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-B9Sf8e9w.js +1 -0
  88. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-B0oiPem-.js → InteractivePreview-CDnfNKKQ.js} +3 -3
  89. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DUS-3h7I.js +3 -0
  90. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-BKKG1s2B.js → LogViewer-TJzDQku1.js} +1 -1
  91. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BgdlWM6p.js +1 -0
  92. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bl6GY-OE.js +6 -0
  93. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DmjXUj6m.js → ScenarioViewer-BDq8RX50.js} +1 -1
  94. package/codeyam-cli/src/webserver/build/client/assets/_index-Bh3y3Wsl.js +1 -0
  95. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-tq7Bl6-t.js +10 -0
  96. package/codeyam-cli/src/webserver/build/client/assets/{chart-column-VXBS6qOn.js → chart-column-q9_nHfwv.js} +1 -1
  97. package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-DvL0YqDJ.js +26 -0
  98. package/codeyam-cli/src/webserver/build/client/assets/{circle-alert-n5GUC2AS.js → circle-alert-CKMpA1v_.js} +1 -1
  99. package/codeyam-cli/src/webserver/build/client/assets/{clock-DKqtX8js.js → clock-Wnfog8Qw.js} +1 -1
  100. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-C_ixaqqh.js +1 -0
  101. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BHiWkb_W.js → entity._sha._-3bYjyojg.js} +10 -10
  102. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DtfwpN9J.js +1 -0
  103. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-QecTs_sq.js +5 -0
  104. package/codeyam-cli/src/webserver/build/client/assets/entry.client-hnkEgHrC.js +5 -0
  105. package/codeyam-cli/src/webserver/build/client/assets/file-text-CvCVdKLW.js +1 -0
  106. package/codeyam-cli/src/webserver/build/client/assets/files-DgUCYhbd.js +1 -0
  107. package/codeyam-cli/src/webserver/build/client/assets/git-WoKohOtW.js +12 -0
  108. package/codeyam-cli/src/webserver/build/client/assets/globals-DZfbt0u5.css +1 -0
  109. package/codeyam-cli/src/webserver/build/client/assets/index-Vvbl94Xc.js +8 -0
  110. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-v3c6DFp4.js → loader-circle-Bxm63UxG.js} +1 -1
  111. package/codeyam-cli/src/webserver/build/client/assets/manifest-c90b8608.js +1 -0
  112. package/codeyam-cli/src/webserver/build/client/assets/root-DrVZQamX.js +16 -0
  113. package/codeyam-cli/src/webserver/build/client/assets/{search-DA14wXpu.js → search-CJkk16Ct.js} +1 -1
  114. package/codeyam-cli/src/webserver/build/client/assets/{settings-COJUrwGu.js → settings-ConzHeiL.js} +1 -1
  115. package/codeyam-cli/src/webserver/build/client/assets/settings-LuiJ1UIm.js +1 -0
  116. package/codeyam-cli/src/webserver/build/client/assets/simulations-B9LRwAej.js +1 -0
  117. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-Lumm1t01.js → useLastLogLine-CpUcCv1V.js} +1 -1
  118. package/codeyam-cli/src/webserver/build/client/assets/useToast-DOxmMaSg.js +1 -0
  119. package/codeyam-cli/src/webserver/build/client/assets/{zap-BvukH0eN.js → zap-D5R1FAcH.js} +1 -1
  120. package/codeyam-cli/src/webserver/build/server/assets/index-DzbqTxoN.js +1 -0
  121. package/codeyam-cli/src/webserver/build/server/assets/server-build-DGGis3OZ.js +166 -0
  122. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  123. package/codeyam-cli/src/webserver/build-info.json +5 -5
  124. package/codeyam-cli/src/webserver/server.js +1 -1
  125. package/codeyam-cli/src/webserver/server.js.map +1 -1
  126. package/codeyam-cli/templates/codeyam-setup-skill.md +5 -0
  127. package/package.json +7 -7
  128. package/packages/ai/index.js +0 -1
  129. package/packages/ai/index.js.map +1 -1
  130. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +6 -15
  131. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  132. package/packages/ai/src/lib/astScopes/methodSemantics.js +134 -0
  133. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  134. package/packages/ai/src/lib/astScopes/paths.js +28 -3
  135. package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
  136. package/packages/ai/src/lib/astScopes/processExpression.js +99 -3
  137. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  138. package/packages/ai/src/lib/checkAllAttributes.js +1 -3
  139. package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
  140. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +308 -2
  141. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  142. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +12 -6
  143. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  144. package/packages/ai/src/lib/generateChangesEntityDocumentation.js +19 -1
  145. package/packages/ai/src/lib/generateChangesEntityDocumentation.js.map +1 -1
  146. package/packages/ai/src/lib/generateChangesEntityScenarioData.js +55 -156
  147. package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
  148. package/packages/ai/src/lib/generateChangesEntityScenarios.js +79 -262
  149. package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
  150. package/packages/ai/src/lib/generateEntityDocumentation.js +15 -1
  151. package/packages/ai/src/lib/generateEntityDocumentation.js.map +1 -1
  152. package/packages/ai/src/lib/generateEntityScenarioData.js +52 -152
  153. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  154. package/packages/ai/src/lib/generateEntityScenarios.js +88 -258
  155. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  156. package/packages/ai/src/lib/generateStatementAnalysis.js +46 -71
  157. package/packages/ai/src/lib/generateStatementAnalysis.js.map +1 -1
  158. package/packages/ai/src/lib/getLLMCallStats.js +0 -14
  159. package/packages/ai/src/lib/getLLMCallStats.js.map +1 -1
  160. package/packages/ai/src/lib/modelInfo.js +15 -0
  161. package/packages/ai/src/lib/modelInfo.js.map +1 -1
  162. package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js +8 -33
  163. package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js.map +1 -1
  164. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +35 -41
  165. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
  166. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +59 -72
  167. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
  168. package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js +8 -27
  169. package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js.map +1 -1
  170. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +24 -27
  171. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  172. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +21 -22
  173. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
  174. package/packages/ai/src/lib/types/index.js +2 -0
  175. package/packages/ai/src/lib/types/index.js.map +1 -1
  176. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +16 -7
  177. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  178. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
  179. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  180. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
  181. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
  182. package/packages/utils/index.js +1 -0
  183. package/packages/utils/index.js.map +1 -1
  184. package/packages/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  185. package/packages/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  186. package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  187. package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  188. package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  189. package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  190. package/analyzer-template/packages/ai/src/lib/generateEntityDataMap.ts +0 -375
  191. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-rqv54FUY.js +0 -1
  192. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DqXXjAJ7.js +0 -3
  193. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DU_jxCPD.js +0 -1
  194. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-5DY-YIxu.js +0 -6
  195. package/codeyam-cli/src/webserver/build/client/assets/_index-DvSrcxsk.js +0 -1
  196. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CsaMd9mb.js +0 -10
  197. package/codeyam-cli/src/webserver/build/client/assets/components-Dj-Ggnl2.js +0 -40
  198. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BbR3FwNc.js +0 -1
  199. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-L7M9Vr5z.js +0 -1
  200. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-C9w-q7P3.js +0 -5
  201. package/codeyam-cli/src/webserver/build/client/assets/entry.client-CdGoUs8A.js +0 -1
  202. package/codeyam-cli/src/webserver/build/client/assets/file-text-B6Er7j5k.js +0 -1
  203. package/codeyam-cli/src/webserver/build/client/assets/files-KcDVw1FY.js +0 -1
  204. package/codeyam-cli/src/webserver/build/client/assets/git-B9uZ8eSJ.js +0 -12
  205. package/codeyam-cli/src/webserver/build/client/assets/globals-B0f88RTV.css +0 -1
  206. package/codeyam-cli/src/webserver/build/client/assets/manifest-fca08d7e.js +0 -1
  207. package/codeyam-cli/src/webserver/build/client/assets/root-Cf8VBqIb.js +0 -16
  208. package/codeyam-cli/src/webserver/build/client/assets/settings-NU_ZquhK.js +0 -1
  209. package/codeyam-cli/src/webserver/build/client/assets/simulations-CNaMJ-nR.js +0 -1
  210. package/codeyam-cli/src/webserver/build/client/assets/useToast-BRShB17p.js +0 -1
  211. package/codeyam-cli/src/webserver/build/client/cy-logo-cli.svg +0 -13
  212. package/codeyam-cli/src/webserver/build/client/favicon.svg +0 -13
  213. package/codeyam-cli/src/webserver/build/server/assets/index-DHr4rT4u.js +0 -1
  214. package/codeyam-cli/src/webserver/build/server/assets/server-build-Bi1mj14J.js +0 -166
  215. package/codeyam-cli/src/webserver/public/cy-logo-cli.svg +0 -13
  216. package/codeyam-cli/src/webserver/public/favicon.svg +0 -13
  217. package/packages/ai/src/lib/generateEntityDataMap.js +0 -335
  218. package/packages/ai/src/lib/generateEntityDataMap.js.map +0 -1
  219. package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js +0 -17
  220. package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js.map +0 -1
@@ -423,6 +423,194 @@ export class ArrayMapSemantics implements MethodSemantics {
423
423
  }
424
424
  }
425
425
 
426
+ /**
427
+ * Array flatMap method semantics
428
+ *
429
+ * flatMap() maps each element using a mapping function, then flattens the result into a new array
430
+ */
431
+ export class ArrayFlatMapSemantics implements MethodSemantics {
432
+ getReturnType(): string {
433
+ return 'array';
434
+ }
435
+
436
+ addEquivalences(
437
+ methodCallPath: StructuredPath,
438
+ sourcePath: StructuredPath,
439
+ context: AnalysisContext,
440
+ ): void {
441
+ // Mark source as array
442
+ context.addType(sourcePath, 'array');
443
+
444
+ // Get the last function call segment to access the arguments
445
+ const lastFunctionCallSegment = methodCallPath.getLastFunctionCallSegment();
446
+
447
+ if (lastFunctionCallSegment && lastFunctionCallSegment.args.length > 0) {
448
+ // The first argument is the callback
449
+ const callbackPath = lastFunctionCallSegment.args[0];
450
+
451
+ // Add the callback to the structure
452
+ context.addType(callbackPath, 'function');
453
+
454
+ // Mark that the callback's first parameter receives array elements
455
+ context.addEquivalence(
456
+ callbackPath.withParameter(0),
457
+ sourcePath.withElement('*'),
458
+ );
459
+ }
460
+ }
461
+
462
+ isComplete(): boolean {
463
+ return true;
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Array at method semantics
469
+ *
470
+ * at() returns the element at the given index, supporting negative indices
471
+ */
472
+ export class ArrayAtSemantics implements MethodSemantics {
473
+ getReturnType(): string {
474
+ return 'unknown'; // Returns element type or undefined
475
+ }
476
+
477
+ addEquivalences(
478
+ methodCallPath: StructuredPath,
479
+ sourcePath: StructuredPath,
480
+ context: AnalysisContext,
481
+ ): void {
482
+ // Mark source as array
483
+ context.addType(sourcePath, 'array');
484
+
485
+ // The return value is equivalent to an array element
486
+ context.addEquivalence(
487
+ methodCallPath.withReturnValues(),
488
+ sourcePath.withElement('*'),
489
+ );
490
+ }
491
+
492
+ isComplete(): boolean {
493
+ return true;
494
+ }
495
+ }
496
+
497
+ /**
498
+ * Array findLast method semantics
499
+ *
500
+ * findLast() returns the last element that passes the test, or undefined
501
+ */
502
+ export class ArrayFindLastSemantics implements MethodSemantics {
503
+ getReturnType(): string {
504
+ return 'unknown'; // Could be any type from the array or undefined
505
+ }
506
+
507
+ addEquivalences(
508
+ methodCallPath: StructuredPath,
509
+ sourcePath: StructuredPath,
510
+ context: AnalysisContext,
511
+ ): void {
512
+ // Mark source as array
513
+ context.addType(sourcePath, 'array');
514
+
515
+ // Get the last function call segment to access the arguments
516
+ const functionCallSegment = methodCallPath.getLastFunctionCallSegment();
517
+
518
+ if (functionCallSegment && functionCallSegment.args.length > 0) {
519
+ // The first argument is the callback
520
+ const callbackPath = functionCallSegment.args[0];
521
+
522
+ // Add the callback to the structure
523
+ context.addType(callbackPath, 'function');
524
+
525
+ // Mark that the callback's first parameter receives array elements
526
+ context.addEquivalence(
527
+ callbackPath.withParameter(0),
528
+ sourcePath.withElement('*'),
529
+ );
530
+ }
531
+ }
532
+
533
+ isComplete(): boolean {
534
+ return true;
535
+ }
536
+ }
537
+
538
+ /**
539
+ * Object.fromEntries method semantics
540
+ *
541
+ * fromEntries() transforms a list of key-value pairs into an object
542
+ */
543
+ export class ObjectFromEntriesSemantics implements MethodSemantics {
544
+ getReturnType(): string {
545
+ return 'object';
546
+ }
547
+
548
+ addEquivalences(
549
+ methodCallPath: StructuredPath,
550
+ sourcePath: StructuredPath,
551
+ context: AnalysisContext,
552
+ ): void {
553
+ // The source path would be Object, not particularly useful
554
+ // The argument is an iterable of key-value pairs
555
+ const functionCallSegment = methodCallPath.getLastFunctionCallSegment();
556
+
557
+ if (functionCallSegment && functionCallSegment.args.length > 0) {
558
+ // Mark the argument as an array (iterable of entries)
559
+ const entriesPath = functionCallSegment.args[0];
560
+ context.addType(entriesPath, 'array');
561
+ }
562
+ }
563
+
564
+ isComplete(): boolean {
565
+ return true;
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Promise.then method semantics
571
+ *
572
+ * then() registers a callback to be called when the promise resolves,
573
+ * and returns a new promise that resolves to the callback's return value
574
+ */
575
+ export class PromiseThenSemantics implements MethodSemantics {
576
+ getReturnType(): string {
577
+ return 'unknown'; // Returns a Promise resolving to the callback's return
578
+ }
579
+
580
+ addEquivalences(
581
+ methodCallPath: StructuredPath,
582
+ sourcePath: StructuredPath,
583
+ context: AnalysisContext,
584
+ ): void {
585
+ // Get the callback argument
586
+ const functionCallSegment = methodCallPath.getLastFunctionCallSegment();
587
+
588
+ if (functionCallSegment && functionCallSegment.args.length > 0) {
589
+ const callbackPath = functionCallSegment.args[0];
590
+
591
+ // Mark the callback as a function
592
+ context.addType(callbackPath, 'function');
593
+
594
+ // The callback's first parameter receives the resolved value of the source promise
595
+ // For promise.then(response => ...), response = promise's resolved value
596
+ // Note: Don't add .functionCallReturnValue - the system adds it automatically
597
+ // via toRightHandSideString() when storing equivalences
598
+ context.addEquivalence(callbackPath.withParameter(0), sourcePath);
599
+
600
+ // The .then() return value (when chained) resolves to the callback's return
601
+ // This enables chained .then() calls to track through
602
+ context.addEquivalence(
603
+ methodCallPath.withProperty('functionCallReturnValue'),
604
+ callbackPath.withProperty('returnValue'),
605
+ );
606
+ }
607
+ }
608
+
609
+ isComplete(): boolean {
610
+ return true;
611
+ }
612
+ }
613
+
426
614
  /**
427
615
  * UseMemo React hook semantics
428
616
  *
@@ -513,13 +701,22 @@ export function createMethodRegistry(): MethodSemanticsRegistry {
513
701
  // Register array methods
514
702
  registry.register('filter', new ArrayFilterSemantics(), 'Array');
515
703
  registry.register('map', new ArrayMapSemantics(), 'Array');
704
+ registry.register('flatMap', new ArrayFlatMapSemantics(), 'Array');
516
705
  registry.register('join', new ArrayJoinSemantics(), 'Array');
517
706
  registry.register('find', new ArrayFindSemantics(), 'Array');
707
+ registry.register('findLast', new ArrayFindLastSemantics(), 'Array');
708
+ registry.register('at', new ArrayAtSemantics(), 'Array');
518
709
  registry.register('reduce', new ArrayReduceSemantics(), 'Array');
519
710
  registry.register('concat', new ArrayConcatSemantics(), 'Array');
520
711
  registry.register('slice', new ArraySliceSemantics(), 'Array');
521
712
  registry.register('splice', new ArraySpliceSemantics(), 'Array');
522
713
 
714
+ // Register Object methods
715
+ registry.register('fromEntries', new ObjectFromEntriesSemantics(), 'Object');
716
+
717
+ // Register Promise methods
718
+ registry.register('then', new PromiseThenSemantics(), 'Promise');
719
+
523
720
  // Register React hooks
524
721
  registry.register('useState', new UseStateSemantics(), 'React');
525
722
  registry.register('useMemo', new UseMemoSemantics(), 'React');
@@ -17,6 +17,25 @@ interface ToStringWithSegmentsOptions {
17
17
  withNestedReturnValues?: boolean;
18
18
  }
19
19
 
20
+ /**
21
+ * Check if a string is a valid JavaScript identifier (can use dot notation)
22
+ * Valid identifiers start with a letter, underscore, or dollar sign
23
+ * and contain only letters, digits, underscores, and dollar signs
24
+ *
25
+ * Also allows computed property markers like *f.path* (wrapped in asterisks)
26
+ * which are used internally to represent dynamic property accesses
27
+ */
28
+ function isValidIdentifier(name: string): boolean {
29
+ if (!name || name.length === 0) return false;
30
+ // First char: letter, underscore, or dollar sign
31
+ // Rest: letter, digit, underscore, or dollar sign
32
+ // Also allow computed property markers like *expression*
33
+ return (
34
+ /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ||
35
+ (name.startsWith('*') && name.endsWith('*'))
36
+ );
37
+ }
38
+
20
39
  /**
21
40
  * A structured representation of a variable or property path
22
41
  *
@@ -335,8 +354,15 @@ export class StructuredPath {
335
354
  switch (segment.type) {
336
355
  case PathRelationship.PROPERTY:
337
356
  const propSegment = segment as PropertySegment;
338
- if (result) result += '.';
339
- result += propSegment.name;
357
+ // Use bracket notation for property names that aren't valid identifiers
358
+ // (e.g. names with spaces, hyphens, starting with numbers, etc.)
359
+ if (isValidIdentifier(propSegment.name)) {
360
+ if (result) result += '.';
361
+ result += propSegment.name;
362
+ } else {
363
+ // Use bracket notation with quoted string for non-identifier names
364
+ result += `['${propSegment.name}']`;
365
+ }
340
366
  break;
341
367
 
342
368
  case PathRelationship.ELEMENT:
@@ -326,6 +326,46 @@ export function processExpression({
326
326
  if (targetPath) {
327
327
  context.addEquivalence(targetPath, nodePath);
328
328
  context.addType(targetPath, inferredNodeType);
329
+
330
+ // Propagate sub-properties from the identifier to the targetPath
331
+ // This handles cases like: dataItem={{ structure: completeDataStructure }}
332
+ // where completeDataStructure was defined as { 'Function Arguments': dataStructure.arguments }
333
+ // We need to propagate completeDataStructure['Function Arguments'] to
334
+ // ChildComponent().signature[0].dataItem.structure['Function Arguments']
335
+ const nodePathStr = nodePath.toString();
336
+ const equivalentVariables = context.getEquivalentVariables();
337
+ const structure = context.getStructure();
338
+
339
+ // Propagate existing equivalencies for sub-properties
340
+ for (const [key, value] of Object.entries(equivalentVariables)) {
341
+ // Check if this equivalency is for a sub-property of the identifier
342
+ // e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
343
+ if (
344
+ key.startsWith(nodePathStr + '.') ||
345
+ key.startsWith(nodePathStr + '[')
346
+ ) {
347
+ const subPath = key.substring(nodePathStr.length);
348
+ const newTargetPath = StructuredPath.fromBase(
349
+ targetPath.toString() + subPath,
350
+ );
351
+ const valuePath = StructuredPath.fromBase(value);
352
+ context.addEquivalence(newTargetPath, valuePath);
353
+ }
354
+ }
355
+
356
+ // Propagate existing structure entries for sub-properties
357
+ for (const [key, value] of Object.entries(structure)) {
358
+ if (
359
+ key.startsWith(nodePathStr + '.') ||
360
+ key.startsWith(nodePathStr + '[')
361
+ ) {
362
+ const subPath = key.substring(nodePathStr.length);
363
+ const newTargetPath = StructuredPath.fromBase(
364
+ targetPath.toString() + subPath,
365
+ );
366
+ context.addType(newTargetPath, value);
367
+ }
368
+ }
329
369
  }
330
370
  context.addType(nodePath, inferredNodeType);
331
371
  return true;
@@ -1009,24 +1049,27 @@ export function processExpression({
1009
1049
  context.addType(valuePath, valueType);
1010
1050
  } else if (ts.isSpreadAssignment(property)) {
1011
1051
  // Handle spread: { ...obj }
1012
- // Process the spread expression first (without targetPath for now)
1013
- processExpression({ node: property.expression, context });
1014
-
1015
1052
  // Create a path for this spread source
1016
1053
  let spreadSourcePath: StructuredPath | null = null;
1017
1054
 
1018
1055
  // Handle simple identifier spread: { ...obj }
1019
1056
  if (ts.isIdentifier(property.expression)) {
1057
+ // Process the spread expression first
1058
+ processExpression({ node: property.expression, context });
1059
+
1020
1060
  spreadSourcePath = StructuredPath.fromBase(
1021
1061
  property.expression.text,
1022
1062
  );
1023
1063
  // Establish equivalence between the target and the spread source
1024
1064
  context.addEquivalence(targetPath, spreadSourcePath);
1025
- // and we kow obj is an object
1065
+ // and we know obj is an object
1026
1066
  context.addType(spreadSourcePath, 'object');
1027
1067
  }
1028
1068
  // Handle property access spread: { ...obj.prop }
1029
1069
  else if (ts.isPropertyAccessExpression(property.expression)) {
1070
+ // Process the spread expression first
1071
+ processExpression({ node: property.expression, context });
1072
+
1030
1073
  spreadSourcePath = StructuredPath.fromNode(
1031
1074
  property.expression,
1032
1075
  context.sourceFile,
@@ -1035,8 +1078,55 @@ export function processExpression({
1035
1078
  context.addEquivalence(targetPath, spreadSourcePath);
1036
1079
  }
1037
1080
  }
1081
+ // Handle object literal spread: { ...{ key: value } }
1082
+ // This propagates sub-properties from the spread object to the target
1083
+ else if (ts.isObjectLiteralExpression(property.expression)) {
1084
+ // Recursively process the spread object literal WITH targetPath
1085
+ // This ensures sub-properties like { args: x } become targetPath.args = x
1086
+ processExpression({
1087
+ node: property.expression,
1088
+ context,
1089
+ targetPath,
1090
+ });
1091
+ }
1092
+ // Handle conditional spread: { ...(x ? {...} : {}) }
1093
+ else if (ts.isParenthesizedExpression(property.expression)) {
1094
+ // Unwrap parentheses and process
1095
+ const unwrapped = property.expression.expression;
1096
+
1097
+ // Handle conditional expression inside parens: (x ? {...} : {})
1098
+ if (ts.isConditionalExpression(unwrapped)) {
1099
+ // Process both branches - whenTrue and whenFalse
1100
+ // For tracing, we care about non-empty branches
1101
+ if (ts.isObjectLiteralExpression(unwrapped.whenTrue)) {
1102
+ processExpression({
1103
+ node: unwrapped.whenTrue,
1104
+ context,
1105
+ targetPath,
1106
+ });
1107
+ } else {
1108
+ processExpression({ node: unwrapped.whenTrue, context });
1109
+ }
1110
+
1111
+ if (ts.isObjectLiteralExpression(unwrapped.whenFalse)) {
1112
+ processExpression({
1113
+ node: unwrapped.whenFalse,
1114
+ context,
1115
+ targetPath,
1116
+ });
1117
+ } else {
1118
+ processExpression({ node: unwrapped.whenFalse, context });
1119
+ }
1120
+ } else {
1121
+ // Other parenthesized expression - just process normally
1122
+ processExpression({ node: property.expression, context });
1123
+ }
1124
+ }
1038
1125
  // Handle other expression types
1039
1126
  else {
1127
+ // Process the spread expression
1128
+ processExpression({ node: property.expression, context });
1129
+
1040
1130
  // For complex expressions, use their source representation
1041
1131
  spreadSourcePath = nodeToSource(
1042
1132
  property.expression,
@@ -1960,6 +2050,25 @@ export function processExpression({
1960
2050
  return result;
1961
2051
  }
1962
2052
 
2053
+ // Handle yield expressions in generator functions
2054
+ if (ts.isYieldExpression(unwrappedNode)) {
2055
+ // yield returns whatever is yielded, or undefined if no expression
2056
+ if (unwrappedNode.expression) {
2057
+ // Process the yielded expression
2058
+ const result = processExpression({
2059
+ node: unwrappedNode.expression,
2060
+ context,
2061
+ targetPath,
2062
+ });
2063
+ return result;
2064
+ }
2065
+ // yield with no expression returns undefined
2066
+ if (targetPath) {
2067
+ context.addType(targetPath, 'undefined');
2068
+ }
2069
+ return true;
2070
+ }
2071
+
1963
2072
  if (ts.isRegularExpressionLiteral(unwrappedNode)) {
1964
2073
  // Regular expressions are treated as string literals
1965
2074
  const regexPath = StructuredPath.createLiteralPath(
@@ -1,7 +1,5 @@
1
1
  export default function checkAllAttributes(data: { [key: string]: unknown }) {
2
- if (data === null) return data;
3
-
4
- for (const key of Object.keys(data)) {
2
+ for (const key of Object.keys(data || {})) {
5
3
  try {
6
4
  if (data[key] === undefined) {
7
5
  delete data[key];