@codeyam/codeyam-cli 0.1.0-staging.596f0eb → 0.1.0-staging.76566f9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +2 -1
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +2 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +22 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.ts +23 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +401 -106
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +60 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +734 -45
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +2 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +715 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +233 -75
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +19 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +34 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +23 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.ts +98 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +34 -1
- package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +236 -24
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityKeyAttributes.ts +18 -1
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +41 -0
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +37 -4
- package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +213 -12
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +36 -25
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +114 -11
- package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +143 -31
- package/analyzer-template/packages/ai/src/lib/guessScenarioDataFromDescription.ts +8 -2
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +7 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +42 -2
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +38 -2
- package/analyzer-template/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.ts +28 -2
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +8 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +127 -43
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +158 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +405 -45
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.ts +1 -1
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +260 -133
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +10 -5
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +77 -83
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +2 -5
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +196 -86
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts +15 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts.map +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js +31 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js.map +1 -0
- package/analyzer-template/packages/aws/package.json +1 -1
- package/analyzer-template/packages/aws/s3/index.ts +1 -0
- package/analyzer-template/packages/aws/src/lib/s3/checkS3ObjectExists.ts +47 -0
- package/analyzer-template/packages/database/src/lib/kysely/db.ts +4 -4
- package/analyzer-template/packages/database/src/lib/kysely/tableRelations.ts +2 -2
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +20 -9
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +9 -4
- package/analyzer-template/packages/generate/src/lib/deepMerge.ts +26 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tableRelations.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts +8 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +14 -7
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js +27 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts +4 -3
- package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.js +1 -0
- package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +31 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts +51 -1
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.js +21 -1
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +48 -0
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/analyzer-template/packages/types/index.ts +8 -0
- package/analyzer-template/packages/types/src/types/Analysis.ts +32 -1
- package/analyzer-template/packages/types/src/types/Scenario.ts +75 -6
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +49 -0
- package/analyzer-template/packages/ui-components/src/components/ScenarioDetailInteractiveView.tsx +23 -7
- package/analyzer-template/packages/utils/dist/types/index.d.ts +4 -3
- package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/index.js +1 -0
- package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +31 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts +51 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.js +21 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.js.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +48 -0
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +27 -0
- package/analyzer-template/playwright/takeElementScreenshot.ts +26 -11
- package/analyzer-template/playwright/takeScreenshot.ts +9 -7
- package/analyzer-template/project/constructMockCode.ts +286 -84
- package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +77 -37
- package/analyzer-template/project/reconcileMockDataKeys.ts +5 -2
- package/analyzer-template/project/runMultiScenarioServer.ts +11 -10
- package/analyzer-template/project/serverOnlyModules.ts +71 -23
- package/analyzer-template/project/start.ts +10 -0
- package/analyzer-template/project/startScenarioCapture.ts +73 -41
- package/analyzer-template/project/writeMockDataTsx.ts +115 -54
- package/analyzer-template/project/writeScenarioComponents.ts +571 -162
- package/analyzer-template/project/writeSimpleRoot.ts +11 -13
- package/background/src/lib/virtualized/project/constructMockCode.js +265 -75
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +67 -32
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +5 -2
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +11 -9
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/background/src/lib/virtualized/project/serverOnlyModules.js +62 -25
- package/background/src/lib/virtualized/project/serverOnlyModules.js.map +1 -1
- package/background/src/lib/virtualized/project/start.js +6 -0
- package/background/src/lib/virtualized/project/start.js.map +1 -1
- package/background/src/lib/virtualized/project/startScenarioCapture.js +54 -31
- package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +106 -46
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +399 -106
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/background/src/lib/virtualized/project/writeSimpleRoot.js +11 -11
- package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
- package/codeyam-cli/src/cli.js +2 -0
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/commands/debug.js +14 -2
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/recapture.js +215 -0
- package/codeyam-cli/src/commands/recapture.js.map +1 -0
- package/codeyam-cli/src/commands/report.js +26 -23
- package/codeyam-cli/src/commands/report.js.map +1 -1
- package/codeyam-cli/src/utils/backgroundServer.js +2 -2
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +252 -106
- package/codeyam-cli/src/utils/generateReport.js.map +1 -1
- package/codeyam-cli/src/utils/install-skills.js +2 -2
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/queue/__tests__/manager.test.js +38 -0
- package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +140 -16
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/queue/manager.js +19 -7
- package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
- package/codeyam-cli/src/utils/queue/persistence.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/database.js +47 -0
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
- package/codeyam-cli/src/webserver/backgroundServer.js +5 -10
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +9 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-wXL1Z2Aq.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-efWKDYMr.js → EntityTypeBadge-CzGX-miz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-CXFKsCOD.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-D-9pXIaY.js +25 -0
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-CBQPrpT0.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/LoadingDots-D1CdlbrV.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-wDPcZNKx.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-4lcOlid-.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BfmDgXxG.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-CUxUNEEC.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-COPstp9J.js → TruncatedFilePath-6J7zDUD5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-DHImXdXq.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CVP_WGQ3.js +32 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.link-scenario-value-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.update-key-attributes-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.update-valid-values-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-BYimnrHg.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/chunk-JMJ3UQ3L-BambyYE_.js +51 -0
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-CaVsIRxt.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CgUsG7ib.js +21 -0
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-CKnwPCDr.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-DW_hdGUc.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-Dt-SjPsw.js +23 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DyB90fWk.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-D_3ero5o.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-CfLCUi9S.js +5 -0
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-DKJyZfAY.js +29 -0
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-DAtOlaWE.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/files-ClR0d32A.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/git-D62Lxxmv.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-C9s7Lhdl.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-fmIEn3Bc.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-BosqDOlH.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-CzNNiTkw.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/keyAttributeCoverage-CTlFMihX.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-CNp9QFCX.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-0d27da29.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/preload-helper-ckwbz45p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-B_wIKCIf.js +56 -0
- package/codeyam-cli/src/webserver/build/client/assets/scenarioStatus-B_8jpV3e.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/search-DDGjYAMJ.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/settings-DgTyB-Wg.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/simulations-CoNWGt0K.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-CBc5dE1s.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BMIGFP-m.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/useInteractiveMode-Dk_FQqWJ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-3pmpUQB-.js → useLastLogLine-BqPPNjAl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-DsJbgMY9.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-DEyawJ8r.js → useToast-DWHcCcl1.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-CU58-Ttc.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-D35o2uae.js +175 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/devServer.js +1 -3
- package/codeyam-cli/src/webserver/devServer.js.map +1 -1
- package/codeyam-cli/templates/codeyam-setup-skill.md +138 -3
- package/codeyam-cli/templates/debug-codeyam.md +625 -0
- package/package.json +14 -14
- package/packages/ai/src/lib/analyzeScope.js +2 -0
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +16 -0
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js +16 -0
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +305 -88
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +582 -41
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +2 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +454 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +173 -55
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +16 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +30 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +20 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js +86 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +28 -2
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +179 -17
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js +6 -0
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js +41 -0
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarios.js +37 -4
- package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js +4 -0
- package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
- package/packages/ai/src/lib/generateEntityKeyAttributes.js +176 -9
- package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +29 -25
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +105 -9
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js +84 -14
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js +2 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +6 -0
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +38 -2
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +38 -2
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js +16 -3
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js +4 -0
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +100 -23
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +125 -0
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +298 -45
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +201 -80
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +10 -5
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +55 -69
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +2 -5
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +171 -81
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/database/src/lib/kysely/db.js +2 -2
- package/packages/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
- package/packages/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/packages/generate/src/lib/deepMerge.js +27 -1
- package/packages/generate/src/lib/deepMerge.js.map +1 -1
- package/packages/types/index.js +1 -0
- package/packages/types/index.js.map +1 -1
- package/packages/types/src/types/Scenario.js +21 -1
- package/packages/types/src/types/Scenario.js.map +1 -1
- package/packages/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/packages/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +3 -1
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js +0 -238
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js.map +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-CVbSvOjo.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-DcwcHyl5.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-WgwC1GfJ.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-IEKom9O2.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-BYnfxbUG.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-_lBPJCzG.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-lHVhvsu_.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-d_TBk4GQ.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/_index-kGT7VUqj.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-DDGmhu7P.js +0 -7
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-n_HPRfM_.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-CbVoyx1U.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-D1VOYveA.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-YR8jjAlu.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-B8vP3V_s.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-CN6aLCT1.js +0 -16
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DA5Jeu2P.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-BTeitalf.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-du6UEYD-.js +0 -13
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-BpjkhMoi.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-BQGvk4lJ.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-DVdYRT-I.js +0 -12
- package/codeyam-cli/src/webserver/build/client/assets/globals-CO-U8Bpo.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/index-DCG-vks0.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-GazdNeLl.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-0b694d28.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-D3tQP7hx.js +0 -16
- package/codeyam-cli/src/webserver/build/client/assets/search-CIY6XmtE.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/server-build-CMKNK2uU.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-CoMDgElu.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/simulations-agkniXp2.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-B2VUcygF.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-EvdK-zXP.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-DGVHQEXD.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-CghkTkIL.js +0 -166
- package/codeyam-cli/templates/debug-command.md +0 -303
- /package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CMKNK2uU.css → styles-CMKNK2uU.css} +0 -0
|
@@ -8,6 +8,51 @@ import * as fs from 'fs';
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import ts from 'typescript';
|
|
10
10
|
import { applyServerOnlyMocks } from "./serverOnlyModules.js";
|
|
11
|
+
// Debug timing helper for tracking where time is spent
|
|
12
|
+
const DEBUG_TIMING = process.env.DEBUG_WRITE_SCENARIO === 'true';
|
|
13
|
+
let debugStartTime;
|
|
14
|
+
let debugLastTime;
|
|
15
|
+
// Timeout protection to prevent infinite hangs
|
|
16
|
+
const WRITE_SCENARIO_TIMEOUT_MS = parseInt(process.env.WRITE_SCENARIO_TIMEOUT_MS || '300000', // Default 5 minutes
|
|
17
|
+
10);
|
|
18
|
+
class WriteScenarioTimeoutError extends Error {
|
|
19
|
+
constructor(operation, timeoutMs) {
|
|
20
|
+
super(`WriteScenarioComponents timed out after ${timeoutMs}ms during: ${operation}`);
|
|
21
|
+
this.name = 'WriteScenarioTimeoutError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function withTimeout(operation, promise, timeoutMs = WRITE_SCENARIO_TIMEOUT_MS) {
|
|
25
|
+
let timeoutId;
|
|
26
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
27
|
+
timeoutId = setTimeout(() => {
|
|
28
|
+
reject(new WriteScenarioTimeoutError(operation, timeoutMs));
|
|
29
|
+
}, timeoutMs);
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
if (timeoutId)
|
|
36
|
+
clearTimeout(timeoutId);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function debugLog(message, extra) {
|
|
40
|
+
if (!DEBUG_TIMING)
|
|
41
|
+
return;
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
if (!debugStartTime) {
|
|
44
|
+
debugStartTime = now;
|
|
45
|
+
debugLastTime = now;
|
|
46
|
+
}
|
|
47
|
+
const elapsed = now - debugStartTime;
|
|
48
|
+
const delta = now - debugLastTime;
|
|
49
|
+
debugLastTime = now;
|
|
50
|
+
console.log(`[WriteScenario +${elapsed}ms Δ${delta}ms] ${message}`, extra ? JSON.stringify(extra, null, 2) : '');
|
|
51
|
+
}
|
|
52
|
+
function resetDebugTiming() {
|
|
53
|
+
debugStartTime = 0;
|
|
54
|
+
debugLastTime = 0;
|
|
55
|
+
}
|
|
11
56
|
/**
|
|
12
57
|
* Find the end position of the last import/export-from statement using TypeScript AST.
|
|
13
58
|
* This is more reliable than regex for handling multiline imports, comments, etc.
|
|
@@ -17,7 +62,10 @@ import { applyServerOnlyMocks } from "./serverOnlyModules.js";
|
|
|
17
62
|
*/
|
|
18
63
|
function findEndOfImports(content) {
|
|
19
64
|
try {
|
|
20
|
-
|
|
65
|
+
// Use temp.tsx to enable JSX parsing - otherwise TypeScript may misparse
|
|
66
|
+
// JSX content containing the word "import" (e.g., "Entities that import this")
|
|
67
|
+
// as an import statement, causing mock code to be inserted in the wrong location.
|
|
68
|
+
const sourceFile = ts.createSourceFile('temp.tsx', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
21
69
|
let lastImportEnd = 0;
|
|
22
70
|
// Visit all top-level statements to find import/export declarations
|
|
23
71
|
for (const statement of sourceFile.statements) {
|
|
@@ -46,6 +94,106 @@ function findEndOfImports(content) {
|
|
|
46
94
|
function escapeRegExp(str) {
|
|
47
95
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
48
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove a named import from file content using TypeScript AST.
|
|
99
|
+
* Handles both regular imports (`EntityName`) and type-only imports (`type EntityName`).
|
|
100
|
+
*
|
|
101
|
+
* @param fileContent - The file content to modify
|
|
102
|
+
* @param entityName - The name of the entity to remove from imports
|
|
103
|
+
* @returns The modified file content with the entity removed from imports
|
|
104
|
+
*/
|
|
105
|
+
function removeNamedImportAst(fileContent, entityName) {
|
|
106
|
+
try {
|
|
107
|
+
const sourceFile = ts.createSourceFile('temp.tsx', fileContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
108
|
+
const replacements = [];
|
|
109
|
+
for (const statement of sourceFile.statements) {
|
|
110
|
+
if (!ts.isImportDeclaration(statement))
|
|
111
|
+
continue;
|
|
112
|
+
if (!statement.importClause?.namedBindings)
|
|
113
|
+
continue;
|
|
114
|
+
if (!ts.isNamedImports(statement.importClause.namedBindings))
|
|
115
|
+
continue;
|
|
116
|
+
const namedImports = statement.importClause.namedBindings;
|
|
117
|
+
const elements = namedImports.elements;
|
|
118
|
+
// Find the element that matches our entity name
|
|
119
|
+
const matchingIndex = elements.findIndex((el) => el.name.text === entityName);
|
|
120
|
+
if (matchingIndex === -1)
|
|
121
|
+
continue;
|
|
122
|
+
// Check if there's a default import (e.g., `import DefaultName, { NamedImport } from '...'`)
|
|
123
|
+
const hasDefaultImport = !!statement.importClause.name;
|
|
124
|
+
// If this is the only named import AND there's no default import, remove the entire statement
|
|
125
|
+
if (elements.length === 1 && !hasDefaultImport) {
|
|
126
|
+
// Find the end including any trailing newline
|
|
127
|
+
let end = statement.getEnd();
|
|
128
|
+
const afterStatement = fileContent.slice(end);
|
|
129
|
+
const trailingNewline = afterStatement.match(/^\r?\n/);
|
|
130
|
+
if (trailingNewline) {
|
|
131
|
+
end += trailingNewline[0].length;
|
|
132
|
+
}
|
|
133
|
+
replacements.push({
|
|
134
|
+
start: statement.getStart(sourceFile),
|
|
135
|
+
end,
|
|
136
|
+
replacement: '',
|
|
137
|
+
});
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Otherwise, rebuild the import without this element
|
|
141
|
+
const remainingElements = elements.filter((_, i) => i !== matchingIndex);
|
|
142
|
+
// Get the module specifier
|
|
143
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
144
|
+
if (!ts.isStringLiteral(moduleSpecifier))
|
|
145
|
+
continue;
|
|
146
|
+
// Preserve import type modifier if present
|
|
147
|
+
const importTypePrefix = statement.importClause.isTypeOnly ? 'type ' : '';
|
|
148
|
+
// Get the default import name if present
|
|
149
|
+
const defaultImportName = statement.importClause.name?.text;
|
|
150
|
+
let newImport;
|
|
151
|
+
if (remainingElements.length === 0) {
|
|
152
|
+
// All named imports were removed, but there's a default import to preserve
|
|
153
|
+
// (we only get here when hasDefaultImport is true, because otherwise we'd have
|
|
154
|
+
// removed the whole statement at the elements.length === 1 check above)
|
|
155
|
+
newImport = `import ${defaultImportName} from ${moduleSpecifier.getText(sourceFile)};`;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// Build the new named imports string
|
|
159
|
+
const newNamedImports = remainingElements
|
|
160
|
+
.map((el) => {
|
|
161
|
+
const isTypeOnly = el.isTypeOnly;
|
|
162
|
+
const name = el.name.text;
|
|
163
|
+
const propertyName = el.propertyName?.text;
|
|
164
|
+
if (propertyName) {
|
|
165
|
+
return isTypeOnly
|
|
166
|
+
? `type ${propertyName} as ${name}`
|
|
167
|
+
: `${propertyName} as ${name}`;
|
|
168
|
+
}
|
|
169
|
+
return isTypeOnly ? `type ${name}` : name;
|
|
170
|
+
})
|
|
171
|
+
.join(', ');
|
|
172
|
+
// Build the new import statement, preserving default import if present
|
|
173
|
+
const defaultImportPrefix = defaultImportName
|
|
174
|
+
? `${defaultImportName}, `
|
|
175
|
+
: '';
|
|
176
|
+
newImport = `import ${importTypePrefix}${defaultImportPrefix}{ ${newNamedImports} } from ${moduleSpecifier.getText(sourceFile)};`;
|
|
177
|
+
}
|
|
178
|
+
replacements.push({
|
|
179
|
+
start: statement.getStart(sourceFile),
|
|
180
|
+
end: statement.getEnd(),
|
|
181
|
+
replacement: newImport,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// Apply replacements in reverse order to preserve positions
|
|
185
|
+
let result = fileContent;
|
|
186
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
187
|
+
for (const { start, end, replacement } of replacements) {
|
|
188
|
+
result = result.slice(0, start) + replacement + result.slice(end);
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
console.warn('[removeNamedImportAst] Failed to parse file:', error);
|
|
194
|
+
return fileContent; // Return original content on error
|
|
195
|
+
}
|
|
196
|
+
}
|
|
49
197
|
/**
|
|
50
198
|
* Map nested dist paths to src paths.
|
|
51
199
|
* Some build tools create nested structures like:
|
|
@@ -321,22 +469,37 @@ function stripServerOnlyImport(fileContent) {
|
|
|
321
469
|
* Excludes node_modules imports (bare specifiers like 'react', '@prisma/client').
|
|
322
470
|
*/
|
|
323
471
|
function extractInternalImportPaths(fileContent) {
|
|
472
|
+
// Always use AST parsing - regex with nested quantifiers can cause catastrophic
|
|
473
|
+
// backtracking that hangs on a single .exec() call (before iteration limits kick in)
|
|
474
|
+
return extractInternalImportPathsAst(fileContent);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Extract internal import paths using TypeScript AST - more reliable for large files
|
|
478
|
+
*/
|
|
479
|
+
function extractInternalImportPathsAst(fileContent) {
|
|
324
480
|
const importPaths = [];
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
481
|
+
try {
|
|
482
|
+
// Use temp.tsx to enable JSX parsing for consistent handling of JSX files
|
|
483
|
+
const sourceFile = ts.createSourceFile('temp.tsx', fileContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
484
|
+
for (const statement of sourceFile.statements) {
|
|
485
|
+
if (ts.isImportDeclaration(statement) && statement.moduleSpecifier) {
|
|
486
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
487
|
+
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
488
|
+
const importPath = moduleSpecifier.text;
|
|
489
|
+
// Skip node_modules imports (bare specifiers)
|
|
490
|
+
if (importPath.startsWith('.') ||
|
|
491
|
+
importPath.startsWith('@/') ||
|
|
492
|
+
importPath.startsWith('~/') ||
|
|
493
|
+
importPath.startsWith('#')) {
|
|
494
|
+
importPaths.push(importPath);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
338
498
|
}
|
|
339
499
|
}
|
|
500
|
+
catch (error) {
|
|
501
|
+
console.warn('[extractInternalImportPathsAst] Failed to parse file:', error);
|
|
502
|
+
}
|
|
340
503
|
return importPaths;
|
|
341
504
|
}
|
|
342
505
|
/**
|
|
@@ -441,8 +604,18 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
|
|
|
441
604
|
const variableMockCodes = [];
|
|
442
605
|
if (hasMultipleCallsWithVariables) {
|
|
443
606
|
// Generate separate mock functions for each variable-qualified call
|
|
444
|
-
//
|
|
445
|
-
//
|
|
607
|
+
// Look up canonical keys from dataForMocks and track variable names for function naming
|
|
608
|
+
// Get all call signature keys for this hook from dataForMocks
|
|
609
|
+
const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
|
|
610
|
+
// Match keys that start with the hook name (e.g., "useFetcher" matches "useFetcher<User>()")
|
|
611
|
+
const callSignatureKeysForHook = dataForMocks
|
|
612
|
+
? Object.keys(dataForMocks).filter((key) => {
|
|
613
|
+
const hookBaseName = importedExport.name.split(/[<(]/)[0];
|
|
614
|
+
const keyBaseName = key.split(/[<(]/)[0];
|
|
615
|
+
return keyBaseName === hookBaseName;
|
|
616
|
+
})
|
|
617
|
+
: [];
|
|
618
|
+
// Track variable name occurrences for unique function naming
|
|
446
619
|
const variableNameCounts = {};
|
|
447
620
|
for (let i = 0; i < importedExport.calls.length; i++) {
|
|
448
621
|
const variableName = importedExport.callVariableNames[i];
|
|
@@ -451,28 +624,31 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
|
|
|
451
624
|
// Calculate the occurrence index for this variable name
|
|
452
625
|
const occurrence = variableNameCounts[variableName] ?? 0;
|
|
453
626
|
variableNameCounts[variableName] = occurrence + 1;
|
|
454
|
-
//
|
|
455
|
-
// e.g., "fetcher[1] <- useFetcher" for the second usage of "fetcher"
|
|
627
|
+
// Build indexed variable name for function naming
|
|
456
628
|
const indexedVariableName = occurrence > 0 ? `${variableName}[${occurrence}]` : variableName;
|
|
457
|
-
//
|
|
458
|
-
//
|
|
459
|
-
const
|
|
460
|
-
|
|
629
|
+
// Use safe function name with underscores instead of brackets
|
|
630
|
+
// e.g., fetcher[1] -> fetcher_1
|
|
631
|
+
const safeFunctionName = indexedVariableName.replace(/\[(\d+)\]/g, '_$1');
|
|
632
|
+
// Compute unique mock function name for call site replacement
|
|
633
|
+
// e.g., useFetcher_entityDiffFetcher, useFetcher_reportFetcher
|
|
634
|
+
const mockFunctionName = `${importedExport.name}_${safeFunctionName}`;
|
|
635
|
+
// Use the call signature from importedExport.calls[i] as the data key
|
|
636
|
+
// This matches what's stored in dataForMocks
|
|
637
|
+
const callSignature = importedExport.calls[i];
|
|
638
|
+
// Generate mock code using the call signature directly
|
|
639
|
+
// This prevents "symbol already declared" errors when multiple calls exist
|
|
640
|
+
const variableMockCode = constructMockCode(callSignature, // Use call signature format for data lookup
|
|
641
|
+
dependencySchemas, importedExport.entityType, undefined, // No need for separate canonical key
|
|
642
|
+
{ uniqueFunctionSuffix: safeFunctionName });
|
|
461
643
|
if (variableMockCode) {
|
|
462
644
|
variableMockCodes.push(variableMockCode);
|
|
463
645
|
// Replace the call site with the variable-specific mock function
|
|
464
646
|
// e.g., useFetcher<BranchEntityDiffResult>() -> useFetcher_entityDiffFetcher()
|
|
465
647
|
// e.g., useFetcher() -> useFetcher_reportFetcher()
|
|
466
|
-
// For indexed variables: useFetcher() -> useFetcher_fetcher_1()
|
|
467
|
-
const callSignature = importedExport.calls[i];
|
|
468
648
|
// Escape special regex characters in the call signature
|
|
469
649
|
const escapedCallSignature = callSignature.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
470
650
|
// Create regex that matches the call (with optional whitespace variations)
|
|
471
651
|
const callRegex = new RegExp(escapedCallSignature.replace(/\s+/g, '\\s*'), 'g');
|
|
472
|
-
// Use safe function name with underscores instead of brackets
|
|
473
|
-
// e.g., fetcher[1] -> fetcher_1
|
|
474
|
-
const safeFunctionName = indexedVariableName.replace(/\[(\d+)\]/g, '_$1');
|
|
475
|
-
const mockFunctionName = `${importedExport.name}_${safeFunctionName}`;
|
|
476
652
|
fileContent = fileContent.replace(callRegex, `${mockFunctionName}()`);
|
|
477
653
|
}
|
|
478
654
|
}
|
|
@@ -487,15 +663,26 @@ function addMockToContent(fileContent, importedExport, fileAnalyses, rootAnalysi
|
|
|
487
663
|
? importedExport.callVariableNames[0]
|
|
488
664
|
: undefined;
|
|
489
665
|
if (singleCallVariableName) {
|
|
490
|
-
// For single variable assignments, use the
|
|
491
|
-
|
|
492
|
-
//
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
|
|
666
|
+
// For single variable assignments, use the call signature directly from dataForMocks
|
|
667
|
+
const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
|
|
668
|
+
// Find matching call signature key in dataForMocks
|
|
669
|
+
const hookBaseName = importedExport.name.split(/[<(]/)[0];
|
|
670
|
+
const callSignatureKey = dataForMocks
|
|
671
|
+
? Object.keys(dataForMocks).find((key) => {
|
|
672
|
+
const keyBaseName = key.split(/[<(]/)[0];
|
|
673
|
+
return keyBaseName === hookBaseName;
|
|
674
|
+
})
|
|
675
|
+
: undefined;
|
|
676
|
+
// Use the call signature if found, otherwise construct it
|
|
677
|
+
const dataKey = callSignatureKey ??
|
|
678
|
+
importedExport.calls?.[0] ??
|
|
679
|
+
`${importedExport.name}()`;
|
|
680
|
+
// Keep the original function name since there's only one call
|
|
681
|
+
mockCode = constructMockCode(dataKey, // Use call signature format
|
|
682
|
+
dependencySchemas, importedExport.entityType, undefined, { keepOriginalFunctionName: true });
|
|
496
683
|
// If constructMockCode didn't generate code, fall back to simple return
|
|
497
684
|
if (!mockCode) {
|
|
498
|
-
mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${
|
|
685
|
+
mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${dataKey}"];
|
|
499
686
|
|
|
500
687
|
function ${importedExport.name}() {
|
|
501
688
|
return ${importedExport.name}ReturnValue;
|
|
@@ -503,50 +690,38 @@ function ${importedExport.name}() {
|
|
|
503
690
|
}
|
|
504
691
|
}
|
|
505
692
|
else {
|
|
506
|
-
//
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
693
|
+
// Helper to find matching call signature key from dataForMocks
|
|
694
|
+
const hookBaseName = importedExport.name.split(/[<(]/)[0];
|
|
695
|
+
const findMatchingKey = (dataForMocks) => {
|
|
696
|
+
if (!dataForMocks)
|
|
697
|
+
return undefined;
|
|
698
|
+
return Object.keys(dataForMocks).find((key) => {
|
|
699
|
+
const keyBaseName = key.split(/[<(]/)[0];
|
|
700
|
+
return keyBaseName === hookBaseName;
|
|
701
|
+
});
|
|
702
|
+
};
|
|
703
|
+
// Check rootAnalysis FIRST for matching keys.
|
|
704
|
+
// The mock DATA is generated from rootAnalysis, so the mock CODE must
|
|
705
|
+
// also use rootAnalysis keys to ensure the lookup succeeds.
|
|
706
|
+
let dataKey = findMatchingKey(rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks);
|
|
707
|
+
// If not found in rootAnalysis, fall back to fileAnalyses
|
|
708
|
+
if (!dataKey) {
|
|
709
|
+
for (const analysis of fileAnalyses) {
|
|
710
|
+
dataKey = findMatchingKey(analysis.metadata?.scenariosDataStructure?.dataForMocks);
|
|
711
|
+
if (dataKey)
|
|
519
712
|
break;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
// If not found in fileAnalyses, fall back to rootAnalysis
|
|
524
|
-
if (!variableQualifiedKey) {
|
|
525
|
-
const dataForMocks = rootAnalysis.metadata?.scenariosDataStructure?.dataForMocks;
|
|
526
|
-
if (dataForMocks) {
|
|
527
|
-
variableQualifiedKey = Object.keys(dataForMocks).find((key) => {
|
|
528
|
-
const match = key.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*<-\s*(.+)$/);
|
|
529
|
-
return match && match[2] === importedExport.name;
|
|
530
|
-
});
|
|
531
713
|
}
|
|
532
714
|
}
|
|
533
|
-
if
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (!mockCode) {
|
|
540
|
-
mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${variableQualifiedKey}"];
|
|
715
|
+
// Use the data key if found, otherwise use call signature or function name
|
|
716
|
+
const mockNameToUse = dataKey ?? importedExport.calls?.[0] ?? `${importedExport.name}()`;
|
|
717
|
+
mockCode = constructMockCode(mockNameToUse, dependencySchemas, importedExport.entityType, undefined, { keepOriginalFunctionName: true });
|
|
718
|
+
// If constructMockCode didn't generate code, fall back to simple return
|
|
719
|
+
if (!mockCode && dataKey) {
|
|
720
|
+
mockCode = `const ${importedExport.name}ReturnValue = scenarios().data()?.["${dataKey}"];
|
|
541
721
|
|
|
542
722
|
function ${importedExport.name}() {
|
|
543
723
|
return ${importedExport.name}ReturnValue;
|
|
544
724
|
}`;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
// Original behavior for calls without variable names
|
|
549
|
-
mockCode = constructMockCode(importedExport.name, dependencySchemas, importedExport.entityType);
|
|
550
725
|
}
|
|
551
726
|
}
|
|
552
727
|
}
|
|
@@ -764,6 +939,14 @@ function captureArgumentsForTesting(args) {
|
|
|
764
939
|
}
|
|
765
940
|
export default async function writeScenarioComponents({ project, file, entity, rootAnalysis, scenario, context, projectAnalyzer, framework, mocksDir, rootFile, namespaceMocks, writtenScenarioComponents = {}, fileStore, exportAsNamed, }) {
|
|
766
941
|
var _a;
|
|
942
|
+
// Reset debug timing for this invocation
|
|
943
|
+
resetDebugTiming();
|
|
944
|
+
debugLog('START writeScenarioComponents', {
|
|
945
|
+
filePath: file.path,
|
|
946
|
+
entityName: entity.name,
|
|
947
|
+
scenarioName: scenario.name,
|
|
948
|
+
isRootFile: !rootFile || rootFile === file,
|
|
949
|
+
});
|
|
767
950
|
// Capture arguments for testing if debug mode is enabled
|
|
768
951
|
captureArgumentsForTesting({
|
|
769
952
|
project,
|
|
@@ -907,7 +1090,20 @@ export default async function writeScenarioComponents({ project, file, entity, r
|
|
|
907
1090
|
return 1;
|
|
908
1091
|
return 0;
|
|
909
1092
|
});
|
|
1093
|
+
debugLog('Starting main importedExports loop', {
|
|
1094
|
+
count: sortedImportedExports.length,
|
|
1095
|
+
fileContentLength: fileContent.length,
|
|
1096
|
+
});
|
|
1097
|
+
let importedExportIndex = 0;
|
|
910
1098
|
for (const importedExport of sortedImportedExports) {
|
|
1099
|
+
importedExportIndex++;
|
|
1100
|
+
if (importedExportIndex % 5 === 0 || importedExportIndex === 1) {
|
|
1101
|
+
debugLog(`Processing importedExport ${importedExportIndex}/${sortedImportedExports.length}`, {
|
|
1102
|
+
name: importedExport.name,
|
|
1103
|
+
filePath: importedExport.filePath,
|
|
1104
|
+
isMocked: importedExport.isMocked,
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
911
1107
|
// IMPORTANT: The import mapping keys may be either absolute or relative paths
|
|
912
1108
|
// depending on how they were created by the file analyzer. We try multiple formats.
|
|
913
1109
|
// Also need to normalize paths to handle /tmp vs /private/tmp on macOS
|
|
@@ -1034,7 +1230,11 @@ export default async function writeScenarioComponents({ project, file, entity, r
|
|
|
1034
1230
|
// e.g., if file has `export default X` but parent does `import { X } from '...'`
|
|
1035
1231
|
const needsNamedReExport = importedExport.resolvedIsDefault === true &&
|
|
1036
1232
|
importedExport.isDefault === false;
|
|
1037
|
-
|
|
1233
|
+
debugLog(`Recursing into writeScenarioComponents for ${importedExportEntity.name}`, {
|
|
1234
|
+
entityName: importedExportEntity.name,
|
|
1235
|
+
filePath: fileNotMocked.path,
|
|
1236
|
+
});
|
|
1237
|
+
const { scenarioComponentPaths: newScenarioComponentPaths, writtenScenarioComponents: updatedWrittenScenarioComponents, } = await withTimeout(`recursive writeScenarioComponents for ${importedExportEntity.name}`, writeScenarioComponents({
|
|
1038
1238
|
project,
|
|
1039
1239
|
file: fileNotMocked,
|
|
1040
1240
|
entity: importedExportEntity,
|
|
@@ -1052,7 +1252,8 @@ export default async function writeScenarioComponents({ project, file, entity, r
|
|
|
1052
1252
|
exportAsNamed: needsNamedReExport
|
|
1053
1253
|
? importedExport.name
|
|
1054
1254
|
: undefined,
|
|
1055
|
-
});
|
|
1255
|
+
}), 60000);
|
|
1256
|
+
debugLog(`Completed recursive writeScenarioComponents for ${importedExportEntity.name}`);
|
|
1056
1257
|
writtenScenarioComponents = updatedWrittenScenarioComponents;
|
|
1057
1258
|
scenarioComponentPaths.push(...newScenarioComponentPaths);
|
|
1058
1259
|
}
|
|
@@ -1286,9 +1487,7 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1286
1487
|
: `import { ${entityImportName} } from '${path}';`;
|
|
1287
1488
|
// First, try to remove this entity from the already-rewritten grouped import
|
|
1288
1489
|
// This prevents duplicate/conflicting imports
|
|
1289
|
-
//
|
|
1290
|
-
// The global patterns used previously would also match type annotations like:
|
|
1291
|
-
// "param: MyType," in function signatures, corrupting the syntax.
|
|
1490
|
+
// Use AST-based removal to properly handle type-only imports like `type EntityName`
|
|
1292
1491
|
const escapedEntityName = escapeRegExp(entityImportName);
|
|
1293
1492
|
// For default imports: remove "DefaultName, " from "import DefaultName, { ... }"
|
|
1294
1493
|
// This handles the case where a default export is being split out
|
|
@@ -1296,27 +1495,12 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1296
1495
|
const defaultImportPattern = new RegExp(`(import\\s+)${escapedEntityName}\\s*,\\s*(\\{)`, 'gm');
|
|
1297
1496
|
fileContent = fileContent.replace(defaultImportPattern, '$1$2');
|
|
1298
1497
|
}
|
|
1299
|
-
//
|
|
1300
|
-
//
|
|
1301
|
-
//
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
let cleaned = namedImports
|
|
1306
|
-
.replace(new RegExp(`\\b${escapedEntityName}\\s*,\\s*`), '') // "EntityName, "
|
|
1307
|
-
.replace(new RegExp(`\\s*,\\s*${escapedEntityName}\\b`), '') // ", EntityName"
|
|
1308
|
-
.replace(new RegExp(`\\b${escapedEntityName}\\b`), ''); // "EntityName" (only one)
|
|
1309
|
-
// Clean up any double commas or leading/trailing commas
|
|
1310
|
-
cleaned = cleaned
|
|
1311
|
-
.replace(/,\s*,/g, ',')
|
|
1312
|
-
.replace(/^\s*,\s*/, '')
|
|
1313
|
-
.replace(/\s*,\s*$/, '');
|
|
1314
|
-
// If no imports left, remove the entire import statement
|
|
1315
|
-
if (cleaned.trim() === '') {
|
|
1316
|
-
return '';
|
|
1317
|
-
}
|
|
1318
|
-
return prefix + cleaned + suffix;
|
|
1319
|
-
});
|
|
1498
|
+
// Remove the named import using AST parsing
|
|
1499
|
+
// This properly handles:
|
|
1500
|
+
// - Regular imports: `import { EntityName } from '...'`
|
|
1501
|
+
// - Type-only imports: `import { type EntityName } from '...'`
|
|
1502
|
+
// - Mixed imports: `import { type EntityName, OtherName } from '...'`
|
|
1503
|
+
fileContent = removeNamedImportAst(fileContent, entityImportName);
|
|
1320
1504
|
// Add the new import at the beginning of fileContent
|
|
1321
1505
|
// Note: The header comment (// Scenario:) doesn't exist yet - it's prepended at writeFile time
|
|
1322
1506
|
// So prepending here puts the import right after the header in the final output
|
|
@@ -1330,17 +1514,27 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1330
1514
|
}
|
|
1331
1515
|
}
|
|
1332
1516
|
}
|
|
1517
|
+
// Collect universal mocks BEFORE processing nodeModuleImports
|
|
1518
|
+
// This is needed to check if a node module import is handled by a universal mock
|
|
1519
|
+
const universalMocks = project.metadata?.universalMocks ?? [];
|
|
1520
|
+
const nodeModuleUniversalMocks = universalMocks.filter((mock) => mock.nodeModule && mock.content);
|
|
1521
|
+
// Create a set of import paths that have universal mocks for quick lookup
|
|
1522
|
+
const universalMockPaths = new Set(nodeModuleUniversalMocks.map((mock) => mock.filePath));
|
|
1333
1523
|
for (const nodeModuleImport of nodeModuleImports) {
|
|
1334
1524
|
if (!nodeModuleImport.isMocked)
|
|
1335
1525
|
continue;
|
|
1526
|
+
// Skip generating local mock functions for imports that have universal mocks.
|
|
1527
|
+
// Universal mocks provide the exports via rewritten import paths (handled below).
|
|
1528
|
+
// Generating a local mock function would cause "name defined multiple times" errors.
|
|
1529
|
+
if (universalMockPaths.has(nodeModuleImport.filePath)) {
|
|
1530
|
+
continue;
|
|
1531
|
+
}
|
|
1336
1532
|
fileContent = addMockToContent(fileContent, nodeModuleImport, fileAnalyses, rootAnalysis, relativeMocksDir, scenario.name, importMapping[nodeModuleImport.filePath] ?? nodeModuleImport.filePath);
|
|
1337
1533
|
}
|
|
1338
1534
|
// Rewrite node_module imports that have universal mocks
|
|
1339
1535
|
// Universal mocks create mock files at __codeyamMocks__/{safeFileName}.tsx
|
|
1340
1536
|
// We need to rewrite imports like `import { logger } from "@formbricks/logger"`
|
|
1341
1537
|
// to `import { logger } from "../__codeyamMocks__/_formbricks_logger.js"`
|
|
1342
|
-
const universalMocks = project.metadata?.universalMocks ?? [];
|
|
1343
|
-
const nodeModuleUniversalMocks = universalMocks.filter((mock) => mock.nodeModule && mock.content);
|
|
1344
1538
|
for (const universalMock of nodeModuleUniversalMocks) {
|
|
1345
1539
|
const originalPath = universalMock.filePath;
|
|
1346
1540
|
// Create the mock file name using the same safeFileName function as writeUniversalMocks
|
|
@@ -1388,20 +1582,30 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1388
1582
|
scenario,
|
|
1389
1583
|
});
|
|
1390
1584
|
}
|
|
1585
|
+
debugLog('Route path computed', { scenarioComponentPath });
|
|
1391
1586
|
// Strip <html> and <body> tags from root layout files for Next.js
|
|
1392
1587
|
// These tags cause hydration errors when the scenario layout is nested under the real root
|
|
1588
|
+
debugLog('Starting stripHtmlBodyTags');
|
|
1393
1589
|
fileContent = stripHtmlBodyTags(fileContent, file.path, framework);
|
|
1590
|
+
debugLog('Completed stripHtmlBodyTags');
|
|
1394
1591
|
// Strip "server-only" imports for Next.js
|
|
1395
1592
|
// These cause errors when the scenario component is rendered client-side
|
|
1593
|
+
debugLog('Starting stripServerOnlyImport');
|
|
1396
1594
|
fileContent = stripServerOnlyImport(fileContent);
|
|
1595
|
+
debugLog('Starting applyServerOnlyMocks');
|
|
1397
1596
|
fileContent = applyServerOnlyMocks(fileContent);
|
|
1597
|
+
debugLog('Completed server-only processing');
|
|
1398
1598
|
// Rewrite asset imports (CSS, images, fonts, etc.) to correct relative paths
|
|
1399
1599
|
// The original file path is relative to PROJECT_RELATIVE_PATH, the new path is scenarioComponentPath
|
|
1600
|
+
debugLog('Starting rewriteAssetImports');
|
|
1400
1601
|
fileContent = rewriteAssetImports(fileContent, `${PROJECT_RELATIVE_PATH}/${file.path}`, scenarioComponentPath);
|
|
1602
|
+
debugLog('Completed rewriteAssetImports');
|
|
1401
1603
|
// Rewrite relative TypeScript/JavaScript module imports to correct relative paths
|
|
1402
1604
|
// This handles cases where the file is moved (e.g., from [environmentId]/ to _environmentId_/)
|
|
1403
1605
|
// and relative imports like "./lib/organization" need to be rewritten
|
|
1606
|
+
debugLog('Starting rewriteRelativeModuleImports');
|
|
1404
1607
|
fileContent = rewriteRelativeModuleImports(fileContent, `${PROJECT_RELATIVE_PATH}/${file.path}`, scenarioComponentPath);
|
|
1608
|
+
debugLog('Completed rewriteRelativeModuleImports');
|
|
1405
1609
|
/**
|
|
1406
1610
|
* Recursively process a file's imports to create transitive copies with server-only stripped.
|
|
1407
1611
|
* This handles chains of arbitrary depth: A -> B -> C -> D where each needs server-only removed.
|
|
@@ -1413,16 +1617,44 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1413
1617
|
* @param visitedPaths - Set of file paths currently being processed (for cycle detection)
|
|
1414
1618
|
* @returns The modified content with imports rewritten to point to transitive copies
|
|
1415
1619
|
*/
|
|
1416
|
-
async function processTransitiveImportsRecursively(content, sourceFilePath, targetFilePath, visitedPaths = new Set()) {
|
|
1620
|
+
async function processTransitiveImportsRecursively(content, sourceFilePath, targetFilePath, visitedPaths = new Set(), depth = 0, startTime = Date.now()) {
|
|
1621
|
+
// Global timeout for entire transitive processing
|
|
1622
|
+
const GLOBAL_TIMEOUT_MS = 60000; // 1 minute max for all transitive processing
|
|
1623
|
+
const elapsed = Date.now() - startTime;
|
|
1624
|
+
if (elapsed > GLOBAL_TIMEOUT_MS) {
|
|
1625
|
+
throw new Error(`processTransitiveImportsRecursively exceeded ${GLOBAL_TIMEOUT_MS}ms (elapsed: ${elapsed}ms) at depth=${depth} for ${sourceFilePath}`);
|
|
1626
|
+
}
|
|
1417
1627
|
const importPaths = extractInternalImportPaths(content);
|
|
1628
|
+
debugLog(`processTransitiveImportsRecursively depth=${depth}`, {
|
|
1629
|
+
sourceFilePath,
|
|
1630
|
+
importCount: importPaths.length,
|
|
1631
|
+
visitedCount: visitedPaths.size,
|
|
1632
|
+
});
|
|
1418
1633
|
let modifiedContent = content;
|
|
1419
|
-
|
|
1634
|
+
// Safety check: limit iterations to prevent infinite loops
|
|
1635
|
+
const MAX_IMPORTS_PER_FILE = 100;
|
|
1636
|
+
if (importPaths.length > MAX_IMPORTS_PER_FILE) {
|
|
1637
|
+
console.warn(`[WriteScenario] WARNING: File ${sourceFilePath} has ${importPaths.length} imports (> ${MAX_IMPORTS_PER_FILE}), limiting processing`);
|
|
1638
|
+
}
|
|
1639
|
+
let importIndex = 0;
|
|
1640
|
+
debugLog(`Starting import loop at depth=${depth}, ${importPaths.length} imports to process`);
|
|
1641
|
+
const slicedImports = importPaths.slice(0, MAX_IMPORTS_PER_FILE);
|
|
1642
|
+
for (const importPath of slicedImports) {
|
|
1643
|
+
if (!importPath) {
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
importIndex++;
|
|
1647
|
+
debugLog(`[LOOP] depth=${depth} import ${importIndex}/${Math.min(importPaths.length, MAX_IMPORTS_PER_FILE)}: ${importPath}`);
|
|
1648
|
+
debugLog(`[LOOP] Calling resolveImportPath...`);
|
|
1420
1649
|
const resolvedPath = resolveImportPath(importPath, sourceFilePath, project);
|
|
1650
|
+
debugLog(`[LOOP] resolveImportPath returned: ${resolvedPath?.slice(0, 80) ?? 'null'}`);
|
|
1421
1651
|
if (!resolvedPath)
|
|
1422
1652
|
continue;
|
|
1653
|
+
debugLog(`[LOOP] Looking up importFile...`);
|
|
1423
1654
|
let importFile = fileStore
|
|
1424
1655
|
? fileStore.getByPath(resolvedPath)
|
|
1425
1656
|
: project.files?.find((f) => f.path === resolvedPath);
|
|
1657
|
+
debugLog(`[LOOP] importFile lookup result: ${importFile ? 'found' : 'not found'}`);
|
|
1426
1658
|
if (!importFile)
|
|
1427
1659
|
continue;
|
|
1428
1660
|
// Build the transitive file path (needed for import rewriting even if we skip creating)
|
|
@@ -1450,8 +1682,17 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1450
1682
|
// Strip server-only and mock server-only packages, then recursively process imports
|
|
1451
1683
|
let transitiveContent = stripServerOnlyImport(importFile.content);
|
|
1452
1684
|
transitiveContent = applyServerOnlyMocks(transitiveContent);
|
|
1453
|
-
|
|
1685
|
+
debugLog(`processTransitiveImportsRecursively depth=${depth} for ${importFile.path}`);
|
|
1686
|
+
debugLog(`Calling processTransitiveImportsRecursively depth=${depth + 1} for ${importFile.path}`);
|
|
1687
|
+
transitiveContent = await withTimeout(`processTransitiveImportsRecursively depth=${depth} for ${path.basename(importFile.path)}`, processTransitiveImportsRecursively(transitiveContent, importFile.path, transitiveFilePath, visitedPaths, depth + 1, startTime), 30000);
|
|
1688
|
+
debugLog(`withTimeout returned for depth=${depth}, transitiveContent length=${transitiveContent.length}`);
|
|
1689
|
+
debugLog(`Completed processTransitiveImportsRecursively depth=${depth} for ${importFile.path}`);
|
|
1690
|
+
debugLog(`Writing transitive file depth=${depth}`, {
|
|
1691
|
+
transitiveFilePath: path.basename(transitiveFilePath),
|
|
1692
|
+
contentLength: transitiveContent.length,
|
|
1693
|
+
});
|
|
1454
1694
|
await writeFile(transitiveFilePath, transitiveContent);
|
|
1695
|
+
debugLog(`Wrote transitive file depth=${depth}`);
|
|
1455
1696
|
scenarioComponentPaths.push(transitiveFilePath);
|
|
1456
1697
|
if (!writtenScenarioComponents[resolvedPath]) {
|
|
1457
1698
|
writtenScenarioComponents[resolvedPath] = [];
|
|
@@ -1461,22 +1702,63 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1461
1702
|
}
|
|
1462
1703
|
// ALWAYS rewrite the import to point to the transitive copy
|
|
1463
1704
|
// (even for circular imports or already-processed files)
|
|
1705
|
+
debugLog(`Rewriting import path depth=${depth}`, {
|
|
1706
|
+
importPath,
|
|
1707
|
+
resolvedPath,
|
|
1708
|
+
});
|
|
1464
1709
|
const relativePath = getRelativePath(targetFilePath, transitiveFilePath);
|
|
1465
1710
|
const relativePathWithoutExt = relativePath.replace(/\.(ts|tsx|js|jsx)$/, '');
|
|
1466
1711
|
const safeRelativePath = safeFolder(relativePathWithoutExt);
|
|
1467
1712
|
const escapedImportPath = importPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1468
|
-
|
|
1469
|
-
|
|
1713
|
+
debugLog(`Applying regex depth=${depth}`, {
|
|
1714
|
+
escapedImportPath,
|
|
1715
|
+
contentLength: modifiedContent.length,
|
|
1716
|
+
});
|
|
1717
|
+
// Quick check if the import path even exists in content
|
|
1718
|
+
const simpleCheck = modifiedContent.includes(importPath);
|
|
1719
|
+
debugLog(`Simple check: importPath "${importPath}" exists: ${simpleCheck}`);
|
|
1720
|
+
if (!simpleCheck) {
|
|
1721
|
+
debugLog(`Skipping regex - import path not found in content`);
|
|
1722
|
+
}
|
|
1723
|
+
else {
|
|
1724
|
+
const regexPattern = `(from\\s*["'])${escapedImportPath}(["'])`;
|
|
1725
|
+
debugLog(`Regex pattern: ${regexPattern.slice(0, 100)}`);
|
|
1726
|
+
const importRegex = new RegExp(regexPattern, 'g');
|
|
1727
|
+
debugLog(`About to call replace...`);
|
|
1728
|
+
// Timing for regex replace to detect slow operations
|
|
1729
|
+
const replaceStart = Date.now();
|
|
1730
|
+
modifiedContent = modifiedContent.replace(importRegex, `$1${safeRelativePath}$2`);
|
|
1731
|
+
const replaceTime = Date.now() - replaceStart;
|
|
1732
|
+
if (replaceTime > 100) {
|
|
1733
|
+
console.warn(`[WriteScenario] SLOW regex replace: ${replaceTime}ms for pattern ${regexPattern.slice(0, 50)} on ${modifiedContent.length} bytes`);
|
|
1734
|
+
}
|
|
1735
|
+
debugLog(`Regex applied depth=${depth} in ${replaceTime}ms`);
|
|
1736
|
+
}
|
|
1737
|
+
debugLog(`[LOOP END] depth=${depth} import ${importIndex} completed`);
|
|
1470
1738
|
}
|
|
1739
|
+
debugLog(`[LOOP DONE] Exiting import loop at depth=${depth}`);
|
|
1740
|
+
debugLog(`Returning from processTransitiveImportsRecursively depth=${depth}`);
|
|
1471
1741
|
return modifiedContent;
|
|
1472
1742
|
}
|
|
1473
1743
|
// Process remaining internal imports that weren't in importedExports
|
|
1474
1744
|
// This handles transitive dependencies: when the file content includes code (e.g., from
|
|
1475
1745
|
// other functions in the same file) that imports from files with "server-only"
|
|
1746
|
+
debugLog('Extracting remaining import paths');
|
|
1476
1747
|
const remainingImportPaths = extractInternalImportPaths(fileContent);
|
|
1748
|
+
debugLog('Found remaining import paths', {
|
|
1749
|
+
count: remainingImportPaths.length,
|
|
1750
|
+
});
|
|
1477
1751
|
// Get all file paths that are in importedExports - these are handled by main processing
|
|
1478
1752
|
const importedExportFilePaths = new Set(allImportedExports.map((ie) => ie.resolvedFilePath || ie.filePath));
|
|
1753
|
+
debugLog('Starting remaining imports loop', {
|
|
1754
|
+
remainingCount: remainingImportPaths.length,
|
|
1755
|
+
importedExportCount: importedExportFilePaths.size,
|
|
1756
|
+
});
|
|
1757
|
+
let remainingImportIndex = 0;
|
|
1758
|
+
debugLog(`[REMAINING] Starting remaining imports loop, ${remainingImportPaths.length} imports`);
|
|
1479
1759
|
for (const importPath of remainingImportPaths) {
|
|
1760
|
+
remainingImportIndex++;
|
|
1761
|
+
debugLog(`[REMAINING LOOP] import ${remainingImportIndex}/${remainingImportPaths.length}: ${importPath}`);
|
|
1480
1762
|
// Resolve the import path to a project file path
|
|
1481
1763
|
const resolvedFilePath = resolveImportPath(importPath, file.path, project);
|
|
1482
1764
|
if (!resolvedFilePath) {
|
|
@@ -1537,7 +1819,11 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1537
1819
|
// Recursively process this transitive file's imports
|
|
1538
1820
|
// This handles the nested case: service.ts → brevo.ts → constants.ts
|
|
1539
1821
|
const nestedImportPaths = extractInternalImportPaths(transformedContent);
|
|
1822
|
+
debugLog(`[NESTED] Processing ${nestedImportPaths.length} nested imports for ${targetFile.path}`);
|
|
1823
|
+
let nestedIndex = 0;
|
|
1540
1824
|
for (const nestedImportPath of nestedImportPaths) {
|
|
1825
|
+
nestedIndex++;
|
|
1826
|
+
debugLog(`[NESTED LOOP] import ${nestedIndex}/${nestedImportPaths.length}: ${nestedImportPath}`);
|
|
1541
1827
|
const nestedResolvedPath = resolveImportPath(nestedImportPath, targetFile.path, project);
|
|
1542
1828
|
if (!nestedResolvedPath)
|
|
1543
1829
|
continue;
|
|
@@ -1568,7 +1854,9 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1568
1854
|
// This handles chains of any depth: A -> B -> C -> D
|
|
1569
1855
|
let nestedContent = stripServerOnlyImport(nestedFile.content);
|
|
1570
1856
|
nestedContent = applyServerOnlyMocks(nestedContent);
|
|
1571
|
-
|
|
1857
|
+
debugLog(`processTransitiveImportsRecursively (nested) for ${nestedFile.path}`);
|
|
1858
|
+
nestedContent = await withTimeout(`processTransitiveImportsRecursively (nested) for ${path.basename(nestedFile.path)}`, processTransitiveImportsRecursively(nestedContent, nestedFile.path, nestedTransformedPath), 30000);
|
|
1859
|
+
debugLog(`Completed processTransitiveImportsRecursively (nested) for ${nestedFile.path}`);
|
|
1572
1860
|
await writeFile(nestedTransformedPath, nestedContent);
|
|
1573
1861
|
scenarioComponentPaths.push(nestedTransformedPath);
|
|
1574
1862
|
// Mark as written
|
|
@@ -1639,7 +1927,12 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
|
|
|
1639
1927
|
else {
|
|
1640
1928
|
finalContent = `${scenarioComponentComment}\n\n${fileContent}`;
|
|
1641
1929
|
}
|
|
1930
|
+
debugLog('About to write final scenario file', {
|
|
1931
|
+
scenarioComponentPath,
|
|
1932
|
+
contentLength: finalContent.length,
|
|
1933
|
+
});
|
|
1642
1934
|
await writeFile(scenarioComponentPath, finalContent);
|
|
1935
|
+
debugLog('Successfully wrote scenario file');
|
|
1643
1936
|
scenarioComponentPaths.push(scenarioComponentPath);
|
|
1644
1937
|
return { scenarioComponentPaths, writtenScenarioComponents };
|
|
1645
1938
|
}
|