@codeyam/codeyam-cli 0.1.0-staging.dbc742d → 0.1.0-staging.df25827
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 +8 -8
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +6 -6
- package/analyzer-template/packages/ai/package.json +1 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +36 -9
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
- package/analyzer-template/packages/analyze/index.ts +4 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
- package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +10 -6
- package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +9 -12
- package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +4 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +4 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +239 -58
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1684 -1462
- package/analyzer-template/packages/aws/package.json +7 -7
- package/analyzer-template/packages/database/package.json +3 -3
- package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +77 -6
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +25 -15
- package/analyzer-template/packages/database/src/lib/loadEntity.ts +19 -8
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +5 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +79 -6
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts +4 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js +5 -5
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts +3 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +22 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +27 -0
- package/analyzer-template/project/analyzeFileEntities.ts +26 -0
- package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
- package/background/src/lib/virtualized/project/analyzeFileEntities.js +22 -0
- package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/codeyam-cli/src/cli.js +24 -0
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +71 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js +51 -0
- package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js +55 -0
- package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +56 -0
- package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +39 -3
- package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
- package/codeyam-cli/src/commands/editor.js +3819 -624
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
- package/codeyam-cli/src/commands/editorIsolateArgs.js +25 -0
- package/codeyam-cli/src/commands/editorIsolateArgs.js.map +1 -0
- package/codeyam-cli/src/commands/init.js +22 -0
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/commands/telemetry.js +37 -0
- package/codeyam-cli/src/commands/telemetry.js.map +1 -0
- package/codeyam-cli/src/data/designSystems.js +27 -0
- package/codeyam-cli/src/data/designSystems.js.map +1 -0
- package/codeyam-cli/src/data/techStacks.js +1 -1
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +173 -0
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/devServerState.test.js +93 -1
- package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js +62 -8
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +3526 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js +76 -0
- package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
- package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js +100 -0
- package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +76 -3
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +381 -0
- package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js +67 -0
- package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js +75 -1
- package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorMigration.test.js +435 -0
- package/codeyam-cli/src/utils/__tests__/editorMigration.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +73 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +98 -1
- package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js +1108 -0
- package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +190 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +936 -9
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +201 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js +143 -0
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js +66 -0
- package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js +53 -0
- package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +390 -11
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/envFile.test.js +125 -0
- package/codeyam-cli/src/utils/__tests__/envFile.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
- package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/handoffContext.test.js +500 -0
- package/codeyam-cli/src/utils/__tests__/handoffContext.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +16 -1
- package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js +30 -2
- package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js +127 -0
- package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js +118 -0
- package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +57 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +373 -1
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js +84 -0
- package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/telemetry.test.js +159 -0
- package/codeyam-cli/src/utils/__tests__/telemetry.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js +216 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +6 -0
- package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -1
- package/codeyam-cli/src/utils/analysisRunner.js +39 -8
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/analyzer.js +11 -1
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/analyzerFinalization.js +100 -0
- package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
- package/codeyam-cli/src/utils/backgroundServer.js +1 -1
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/designSystemShowcase.js +810 -0
- package/codeyam-cli/src/utils/designSystemShowcase.js.map +1 -0
- package/codeyam-cli/src/utils/devServerState.js +32 -0
- package/codeyam-cli/src/utils/devServerState.js.map +1 -1
- package/codeyam-cli/src/utils/editorApi.js +27 -5
- package/codeyam-cli/src/utils/editorApi.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +700 -10
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorBroadcastViewport.js +26 -0
- package/codeyam-cli/src/utils/editorBroadcastViewport.js.map +1 -0
- package/codeyam-cli/src/utils/editorDeleteScenario.js +67 -0
- package/codeyam-cli/src/utils/editorDeleteScenario.js.map +1 -0
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js +13 -7
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -1
- package/codeyam-cli/src/utils/editorEntityHelpers.js +144 -0
- package/codeyam-cli/src/utils/editorEntityHelpers.js.map +1 -0
- package/codeyam-cli/src/utils/editorGuard.js +36 -0
- package/codeyam-cli/src/utils/editorGuard.js.map +1 -0
- package/codeyam-cli/src/utils/editorLoaderHelpers.js +40 -1
- package/codeyam-cli/src/utils/editorLoaderHelpers.js.map +1 -1
- package/codeyam-cli/src/utils/editorMigration.js +224 -0
- package/codeyam-cli/src/utils/editorMigration.js.map +1 -0
- package/codeyam-cli/src/utils/editorPreview.js +33 -0
- package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
- package/codeyam-cli/src/utils/editorRecapture.js +109 -0
- package/codeyam-cli/src/utils/editorRecapture.js.map +1 -0
- package/codeyam-cli/src/utils/editorRoadmap.js +574 -0
- package/codeyam-cli/src/utils/editorRoadmap.js.map +1 -0
- package/codeyam-cli/src/utils/editorScenarioSwitch.js +39 -2
- package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +375 -16
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/editorSeedAdapter.js +308 -6
- package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
- package/codeyam-cli/src/utils/editorShouldRevalidate.js +21 -0
- package/codeyam-cli/src/utils/editorShouldRevalidate.js.map +1 -0
- package/codeyam-cli/src/utils/entityChangeStatus.js +50 -5
- package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.server.js +72 -3
- package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -1
- package/codeyam-cli/src/utils/envFile.js +90 -0
- package/codeyam-cli/src/utils/envFile.js.map +1 -0
- package/codeyam-cli/src/utils/fileWatcher.js +38 -0
- package/codeyam-cli/src/utils/fileWatcher.js.map +1 -1
- package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
- package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
- package/codeyam-cli/src/utils/handoffContext.js +257 -0
- package/codeyam-cli/src/utils/handoffContext.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +50 -6
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
- package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
- package/codeyam-cli/src/utils/parseRegisterArg.js.map +1 -1
- package/codeyam-cli/src/utils/progress.js +2 -2
- package/codeyam-cli/src/utils/progress.js.map +1 -1
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
- package/codeyam-cli/src/utils/queue/job.js +35 -6
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/registerScenarioResult.js +52 -0
- package/codeyam-cli/src/utils/registerScenarioResult.js.map +1 -0
- package/codeyam-cli/src/utils/routePatternMatching.js +129 -0
- package/codeyam-cli/src/utils/routePatternMatching.js.map +1 -0
- package/codeyam-cli/src/utils/scenarioCoverage.js +12 -10
- package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -1
- package/codeyam-cli/src/utils/scenariosManifest.js +154 -0
- package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
- package/codeyam-cli/src/utils/screenshotHash.js +26 -0
- package/codeyam-cli/src/utils/screenshotHash.js.map +1 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +1 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js +9 -0
- package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
- package/codeyam-cli/src/utils/techStackConfig.js +38 -0
- package/codeyam-cli/src/utils/techStackConfig.js.map +1 -0
- package/codeyam-cli/src/utils/techStackConfig.test.js +85 -0
- package/codeyam-cli/src/utils/techStackConfig.test.js.map +1 -0
- package/codeyam-cli/src/utils/telemetry.js +106 -0
- package/codeyam-cli/src/utils/telemetry.js.map +1 -0
- package/codeyam-cli/src/utils/telemetryMiddleware.js +22 -0
- package/codeyam-cli/src/utils/telemetryMiddleware.js.map +1 -0
- package/codeyam-cli/src/utils/testResultCache.js +53 -0
- package/codeyam-cli/src/utils/testResultCache.js.map +1 -0
- package/codeyam-cli/src/utils/testResultCache.server.js +81 -0
- package/codeyam-cli/src/utils/testResultCache.server.js.map +1 -0
- package/codeyam-cli/src/utils/testResultCache.server.test.js +187 -0
- package/codeyam-cli/src/utils/testResultCache.server.test.js.map +1 -0
- package/codeyam-cli/src/utils/testResultCache.test.js +230 -0
- package/codeyam-cli/src/utils/testResultCache.test.js.map +1 -0
- package/codeyam-cli/src/utils/testRunner.js +193 -1
- package/codeyam-cli/src/utils/testRunner.js.map +1 -1
- package/codeyam-cli/src/utils/webappDetection.js +4 -2
- package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +99 -0
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js +153 -0
- package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +68 -1
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +454 -4
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +315 -0
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js +135 -0
- package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js.map +1 -0
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js +22 -1
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/git.js +3 -2
- package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -1
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
- package/codeyam-cli/src/webserver/app/types/editor.js +8 -0
- package/codeyam-cli/src/webserver/app/types/editor.js.map +1 -0
- package/codeyam-cli/src/webserver/backgroundServer.js +60 -61
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-DTBZZfSk.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-BcgbViKV.js → EntityItem-BxclONWq.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-CQgyEGV-.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CQIG2qda.js → EntityTypeIcon-BsnEOJZ_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-ByaELMbv.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-6WjVfhxX.js +25 -0
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-ChX-Hp7W.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-BU_OAEMP.js → LoadingDots-By5zI316.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-ceAyBX-H.js → LogViewer-C-9zQdXg.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-Bs2_Oua4.js +36 -0
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-BzHcG7SE.js → ReportIssueModal-DQsceHVv.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DThcm_9M.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-0DY_NKil.js → ScenarioViewer-Cl4oOA3A.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-CIil5-gb.js +34 -0
- package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-CK7-NaPZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-BqkA9zyZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{_index-DLxKhri3.js → _index-DnOgyseQ.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BcY3q6nt.js → activity.(_tab)-DqM9hbNE.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-Duc5hnl7.js → addon-web-links-C58dYPwR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-Bni3iiUj.js → agent-transcripts-B8NCeOrm.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-database-verify-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-github-verify-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-handoff-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-hosting-verify-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-recapture-stale-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-rename-scenario-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-roadmap-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-scenario-data-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-seed-state-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-prompt-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-schema-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-session-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-BYOypzCa.js → book-open-BFSIqZgO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-C_Pmso5S.js → chevron-down-B9fDzFVh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-UVKPFVEO-Bmq2apuh.js +43 -0
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BVMi9VA5.js → circle-check-DLPObLUx.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-n2FB0_Sw.js → copy-DXEmO0TD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-CC6AbExI.js → createLucideIcon-BwyFiRot.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CCKUIm0S.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-iRhRIFlp.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/editor._tab-BZPBzV73.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DhtVC4aI.js +161 -0
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-C6fEYHrh.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BF4oLwaE.js → entity._sha._-pc-vc6wO.js} +13 -12
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-C8AyYgYT.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DziaVQX1.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-BTcpgIpC.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMvVHNXU.js → entity._sha_.edit._scenarioId-D_O_ajfZ.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-DTvKq3TY.js → entry.client-j1Vi0bco.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-Daa96Fr1.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/files-kuny2Q_s.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/git-DgCZPMie.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-L-aUIeux.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-BcvgDzbZ.js → index-BliGSSpl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-yHOVb4rc.js → index-SqjQKTdH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-10oVnAAH.js → index-vyrZD2g4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/jsx-runtime-D_zvdyIk.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/labs-c3yLxSEp.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-DaAZ_H2w.js → loader-circle-D-q28GLF.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-b0d69c06.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{memory-9gnxSZlb.js → memory-CEWIUC4t.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{pause-f5-1lKBt.js → pause-BP6fitdh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-CLedrjXQ.js +80 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-Di64LWVb.js → search-BooqacKS.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-BM0nbryO.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/simulations-ovy6FjRY.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-Br7MOqts.js → terminal-DHemCJIs.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BLdiCuG-.js → triangle-alert-D87ekDl8.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-Dk0Tciqg.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C8QvIe05.js +2 -0
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-jkCytuYz.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/useToast-BgqkixU9.js +1 -0
- package/codeyam-cli/src/webserver/build/client/sound-test.html +98 -0
- package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-DPUEhrWo.js +16 -0
- package/codeyam-cli/src/webserver/build/server/assets/{index-BWoRb5RY.js → index-oF2amaGI.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/init-C42BvUGp.js +14 -0
- package/codeyam-cli/src/webserver/build/server/assets/progress-CHTtrxFG.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DiCdDL5d.js +853 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/editorProxy.js +443 -35
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/idleDetector.js +130 -0
- package/codeyam-cli/src/webserver/idleDetector.js.map +1 -0
- package/codeyam-cli/src/webserver/mockStateEvents.js +28 -0
- package/codeyam-cli/src/webserver/mockStateEvents.js.map +1 -0
- package/codeyam-cli/src/webserver/public/sound-test.html +98 -0
- package/codeyam-cli/src/webserver/scripts/journalCapture.ts +53 -0
- package/codeyam-cli/src/webserver/server.js +192 -4
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +369 -52
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/__tests__/editor-step-hook.prompt-capture.test.ts +118 -0
- package/codeyam-cli/templates/codeyam-editor-claude.md +3 -1
- package/codeyam-cli/templates/codeyam-editor-codex.md +61 -0
- package/codeyam-cli/templates/codeyam-editor-gemini.md +59 -0
- package/codeyam-cli/templates/codeyam-editor-reference.md +216 -0
- package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
- package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
- package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
- package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
- package/codeyam-cli/templates/editor-step-hook.py +193 -56
- package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +204 -5
- package/codeyam-cli/templates/expo-react-native/__tests__/.gitkeep +0 -0
- package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +6 -3
- package/codeyam-cli/templates/expo-react-native/app/index.tsx +36 -0
- package/codeyam-cli/templates/expo-react-native/app.json +11 -0
- package/codeyam-cli/templates/expo-react-native/babel.config.js +1 -0
- package/codeyam-cli/templates/expo-react-native/gitignore +2 -0
- package/codeyam-cli/templates/expo-react-native/global.css +7 -0
- package/codeyam-cli/templates/expo-react-native/lib/theme.ts +73 -0
- package/codeyam-cli/templates/expo-react-native/package.json +32 -16
- package/codeyam-cli/templates/expo-react-native/patches/expo-modules-autolinking+3.0.24.patch +29 -0
- package/codeyam-cli/templates/isolation-route/expo-router.tsx.template +54 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +1 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +1 -1
- package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +88 -40
- package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +1 -1
- package/codeyam-cli/templates/seed-adapters/supabase.ts +475 -0
- package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +106 -10
- package/package.json +2 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
- package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
- package/packages/ai/src/lib/astScopes/paths.js +12 -3
- package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +27 -10
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/analyze/index.js +1 -1
- package/packages/analyze/index.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +3 -2
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +9 -7
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeChange.js +1 -0
- package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeInitial.js +1 -0
- package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +120 -28
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1368 -1193
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +79 -6
- package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +7 -1
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/packages/database/src/lib/loadEntity.js +5 -5
- package/packages/database/src/lib/loadEntity.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +22 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-BPXZwM4t.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-g3saevPb.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-Bu6c6aDe.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-DYFW3lDD.js +0 -25
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DLeucoVX.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BED4B6sP.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bb5uFQ5V.js +0 -34
- package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-C8OKAR5x.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-oAf2Kqsf.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-C4pqxYJB.js +0 -51
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Csi0_PMl.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor-BBAGP_mE.js +0 -10
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-BLQMSKZa.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-C7YX6r3H.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-CF164ouH.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-p9hhkjJM.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-cPo8LiG3.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-BZrlFE1F.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-DdZcvjGh.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-COUSHTyZ.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-Zk7ryIM1.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-9c70d1f3.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-CHOdrM6Y.js +0 -67
- package/codeyam-cli/src/webserver/build/client/assets/settings-0OrEMU6J.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/simulations-DWT-CvLy.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-CrAK28Bc.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C14nCb1q.js +0 -2
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-O-jkvSPx.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useToast-9FIWuYfK.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/init-DbChSUQP.js +0 -10
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BtbLQkKd.js +0 -433
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +0 -33
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +0 -12
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +0 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseClientErrors } from "../app/lib/clientErrors.js";
|
|
1
|
+
import { parseClientErrors, parseVisibleText } from "../app/lib/clientErrors.js";
|
|
2
2
|
describe('parseClientErrors', () => {
|
|
3
3
|
it('extracts console.error lines', () => {
|
|
4
4
|
const output = `[JournalCapture] Page console.error: Uncaught TypeError: x is not a function`;
|
|
@@ -36,5 +36,72 @@ describe('parseClientErrors', () => {
|
|
|
36
36
|
const output = `[JournalCapture] Screenshot saved\n[JournalCapture] Done`;
|
|
37
37
|
expect(parseClientErrors(output)).toEqual([]);
|
|
38
38
|
});
|
|
39
|
+
it('extracts HTTP error status lines (e.g. 404)', () => {
|
|
40
|
+
const output = `[JournalCapture] HTTP error: status=404, url=http://localhost:3112/library/collections/col-1`;
|
|
41
|
+
expect(parseClientErrors(output)).toEqual([
|
|
42
|
+
'HTTP error: status=404, url=http://localhost:3112/library/collections/col-1',
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
it('extracts HTTP 500 error status lines', () => {
|
|
46
|
+
const output = `[JournalCapture] HTTP error: status=500, url=http://localhost:3112/api/crash`;
|
|
47
|
+
expect(parseClientErrors(output)).toEqual([
|
|
48
|
+
'HTTP error: status=500, url=http://localhost:3112/api/crash',
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
it('collects HTTP errors alongside console errors', () => {
|
|
52
|
+
const output = [
|
|
53
|
+
`[JournalCapture] HTTP error: status=404, url=http://localhost:3112/missing`,
|
|
54
|
+
`[JournalCapture] Page console.error: Cannot read properties of null`,
|
|
55
|
+
].join('\n');
|
|
56
|
+
expect(parseClientErrors(output)).toEqual([
|
|
57
|
+
'HTTP error: status=404, url=http://localhost:3112/missing',
|
|
58
|
+
'Cannot read properties of null',
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
it('extracts API response error lines with response body', () => {
|
|
62
|
+
const output = `[JournalCapture] API response error: GET http://localhost:3112/api/items/abc-123 → 404 — {"error":"not found"}`;
|
|
63
|
+
expect(parseClientErrors(output)).toEqual([
|
|
64
|
+
'API response error: GET http://localhost:3112/api/items/abc-123 → 404 — {"error":"not found"}',
|
|
65
|
+
]);
|
|
66
|
+
});
|
|
67
|
+
it('collects API response errors alongside HTTP errors and console errors', () => {
|
|
68
|
+
const output = [
|
|
69
|
+
`[JournalCapture] HTTP error: status=404, url=http://localhost:3112/page/abc`,
|
|
70
|
+
`[JournalCapture] API response error: GET http://localhost:3112/api/items/abc-123 → 404 — {"error":"Item not found"}`,
|
|
71
|
+
`[JournalCapture] Page console.error: Unhandled error in component`,
|
|
72
|
+
].join('\n');
|
|
73
|
+
expect(parseClientErrors(output)).toEqual([
|
|
74
|
+
'HTTP error: status=404, url=http://localhost:3112/page/abc',
|
|
75
|
+
'API response error: GET http://localhost:3112/api/items/abc-123 → 404 — {"error":"Item not found"}',
|
|
76
|
+
'Unhandled error in component',
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('parseVisibleText', () => {
|
|
81
|
+
it('extracts visible text from capture output', () => {
|
|
82
|
+
const output = '[JournalCapture] Visible text: Save to Library | Tech Chronicle';
|
|
83
|
+
expect(parseVisibleText(output)).toBe('Save to Library | Tech Chronicle');
|
|
84
|
+
});
|
|
85
|
+
it('returns null when no visible text line exists', () => {
|
|
86
|
+
const output = '[JournalCapture] Page loaded: status=200';
|
|
87
|
+
expect(parseVisibleText(output)).toBeNull();
|
|
88
|
+
});
|
|
89
|
+
it('extracts empty page marker', () => {
|
|
90
|
+
const output = '[JournalCapture] Visible text: (empty page)';
|
|
91
|
+
expect(parseVisibleText(output)).toBe('(empty page)');
|
|
92
|
+
});
|
|
93
|
+
it('extracts from multi-line output with other log lines', () => {
|
|
94
|
+
const output = [
|
|
95
|
+
'[JournalCapture] Page loaded: status=200, url=http://localhost:3113/',
|
|
96
|
+
'[JournalCapture] Page title: Margo',
|
|
97
|
+
'[JournalCapture] Visible text: Save to Library | Tech Chronicle | The Future of Web Dev',
|
|
98
|
+
'[JournalCapture] RESULT:{"success":true,"path":"/tmp/screenshot.png"}',
|
|
99
|
+
].join('\n');
|
|
100
|
+
expect(parseVisibleText(output)).toBe('Save to Library | Tech Chronicle | The Future of Web Dev');
|
|
101
|
+
});
|
|
102
|
+
it('extracts extraction failure marker', () => {
|
|
103
|
+
const output = '[JournalCapture] Visible text: (extraction failed)';
|
|
104
|
+
expect(parseVisibleText(output)).toBe('(extraction failed)');
|
|
105
|
+
});
|
|
39
106
|
});
|
|
40
107
|
//# sourceMappingURL=clientErrors.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientErrors.test.js","sourceRoot":"","sources":["../../../../../src/webserver/__tests__/clientErrors.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"clientErrors.test.js","sourceRoot":"","sources":["../../../../../src/webserver/__tests__/clientErrors.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
import zlib from 'zlib';
|
|
3
|
-
import { injectHealthScript, PREVIEW_HEALTH_SCRIPT, getPreviewHealthReport, resetPreviewHealth, } from "../editorProxy.js";
|
|
3
|
+
import { injectHealthScript, PREVIEW_HEALTH_SCRIPT, getPreviewHealthReport, resetPreviewHealth, buildErrorPage, escapeHtml, } from "../editorProxy.js";
|
|
4
4
|
describe('editorProxy', () => {
|
|
5
5
|
describe('normalizeTargetUrl', () => {
|
|
6
6
|
it('should leave localhost as-is (no longer normalizes to 127.0.0.1)', () => {
|
|
@@ -198,6 +198,14 @@ describe('editorProxy', () => {
|
|
|
198
198
|
const result = injectHealthScript(html);
|
|
199
199
|
expect(result).toContain('data-codeyam-health');
|
|
200
200
|
});
|
|
201
|
+
it('should use 100ms settle delay for network-idle detection', () => {
|
|
202
|
+
// The settle delay determines how long after all fetch() calls complete
|
|
203
|
+
// before the preview is shown. 100ms is enough for React to re-render.
|
|
204
|
+
expect(PREVIEW_HEALTH_SCRIPT).toContain('}, 100)');
|
|
205
|
+
});
|
|
206
|
+
it('should use 200ms fallback for static pages with no fetches', () => {
|
|
207
|
+
expect(PREVIEW_HEALTH_SCRIPT).toContain('}, 200)');
|
|
208
|
+
});
|
|
201
209
|
});
|
|
202
210
|
describe('preview health endpoint', () => {
|
|
203
211
|
let targetServer;
|
|
@@ -352,10 +360,20 @@ describe('editorProxy', () => {
|
|
|
352
360
|
});
|
|
353
361
|
});
|
|
354
362
|
describe('buildLocalStorageScript', () => {
|
|
355
|
-
it('should
|
|
363
|
+
it('should clean up previous keys when no localStorage config but scenarioId is present', () => {
|
|
364
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
365
|
+
// When switching to a scenario WITHOUT localStorage from one that HAD it,
|
|
366
|
+
// the script must clean up the previous scenario's keys so stale filters
|
|
367
|
+
// don't persist and hide data.
|
|
368
|
+
const script = buildLocalStorageScript(null, 'scenario-123');
|
|
369
|
+
expect(script).toContain('__codeyam_ls_keys__');
|
|
370
|
+
expect(script).toContain('removeItem');
|
|
371
|
+
expect(script).toContain('clear:scenario-123');
|
|
372
|
+
});
|
|
373
|
+
it('should return empty string when no localStorage config and no scenarioId', () => {
|
|
356
374
|
const { buildLocalStorageScript } = require('../editorProxy');
|
|
357
|
-
expect(buildLocalStorageScript(null, '
|
|
358
|
-
expect(buildLocalStorageScript(undefined, '
|
|
375
|
+
expect(buildLocalStorageScript(null, '')).toBe('');
|
|
376
|
+
expect(buildLocalStorageScript(undefined, '')).toBe('');
|
|
359
377
|
});
|
|
360
378
|
it('should emit cleanup script when localStorage config is empty object', () => {
|
|
361
379
|
// BUG FIX: When switching from a scenario with localStorage data to one
|
|
@@ -391,6 +409,24 @@ describe('editorProxy', () => {
|
|
|
391
409
|
// Should track which keys were set for cleanup
|
|
392
410
|
expect(script).toContain('__codeyam_ls_keys__');
|
|
393
411
|
});
|
|
412
|
+
it('should emit gated localStorage.clear() when prototypeId is provided and config is null', () => {
|
|
413
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
414
|
+
const script = buildLocalStorageScript(null, 'scenario-123', 'proto-abc');
|
|
415
|
+
// Should not be empty — prototypeId triggers a clear script
|
|
416
|
+
expect(script).not.toBe('');
|
|
417
|
+
expect(script).toContain('localStorage.clear()');
|
|
418
|
+
// Should be gated by the __codeyam_proto__ marker
|
|
419
|
+
expect(script).toContain('__codeyam_proto__');
|
|
420
|
+
expect(script).toContain('proto-abc');
|
|
421
|
+
});
|
|
422
|
+
it('should clean up previous keys when prototypeId is absent but scenarioId is present', () => {
|
|
423
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
424
|
+
// No prototypeId but scenarioId — cleanup previous scenario's keys
|
|
425
|
+
const script1 = buildLocalStorageScript(null, 'scenario-123');
|
|
426
|
+
expect(script1).toContain('removeItem');
|
|
427
|
+
const script2 = buildLocalStorageScript(null, 'scenario-123', null);
|
|
428
|
+
expect(script2).toContain('removeItem');
|
|
429
|
+
});
|
|
394
430
|
it('should clean up keys from previous scenario before setting new ones', () => {
|
|
395
431
|
const { buildLocalStorageScript } = require('../editorProxy');
|
|
396
432
|
const config = { my_key: 'my_value' };
|
|
@@ -415,6 +451,67 @@ describe('editorProxy', () => {
|
|
|
415
451
|
expect(script).toContain('array_key');
|
|
416
452
|
expect(script).toContain('[1,2,3]');
|
|
417
453
|
});
|
|
454
|
+
it('should include localStorage mutation watcher that sends postMessage on changes', () => {
|
|
455
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
456
|
+
const config = { my_key: 'my_value' };
|
|
457
|
+
const script = buildLocalStorageScript(config, 'scenario-1');
|
|
458
|
+
// Should hook setItem, removeItem, and clear
|
|
459
|
+
expect(script).toContain('__codeyam_orig_setItem__');
|
|
460
|
+
expect(script).toContain('__codeyam_orig_removeItem__');
|
|
461
|
+
expect(script).toContain('__codeyam_orig_clear__');
|
|
462
|
+
// Should send postMessage to parent
|
|
463
|
+
expect(script).toContain('codeyam-localstorage-changed');
|
|
464
|
+
expect(script).toContain('postMessage');
|
|
465
|
+
// Should filter out internal codeyam keys
|
|
466
|
+
expect(script).toContain('__codeyam_');
|
|
467
|
+
});
|
|
468
|
+
it('should include localStorage mutation watcher even for empty localStorage config', () => {
|
|
469
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
470
|
+
const script = buildLocalStorageScript({}, 'scenario-1');
|
|
471
|
+
// Empty config still needs the watcher since the app may write to localStorage
|
|
472
|
+
expect(script).toContain('codeyam-localstorage-changed');
|
|
473
|
+
});
|
|
474
|
+
it('should include a listener for codeyam-get-localstorage requests', () => {
|
|
475
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
476
|
+
const config = { my_key: 'my_value' };
|
|
477
|
+
const script = buildLocalStorageScript(config, 'scenario-1');
|
|
478
|
+
// Should listen for get-localstorage requests from parent
|
|
479
|
+
expect(script).toContain('codeyam-get-localstorage');
|
|
480
|
+
expect(script).toContain('codeyam-localstorage-state');
|
|
481
|
+
});
|
|
482
|
+
it('should not include mutation watcher when no localStorage config and no scenarioId', () => {
|
|
483
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
484
|
+
// No config AND no scenarioId — returns empty string
|
|
485
|
+
expect(buildLocalStorageScript(null, '')).toBe('');
|
|
486
|
+
});
|
|
487
|
+
it('should re-seed localStorage when scenario data changes even if ID is the same', () => {
|
|
488
|
+
// BUG: When a scenario is re-registered with updated data (e.g., adding
|
|
489
|
+
// collections to articles), the scenario ID stays the same. The guard
|
|
490
|
+
// checked only the ID, so the browser skipped re-seeding and showed stale
|
|
491
|
+
// data. The screenshot (captured by Playwright with a fresh browser)
|
|
492
|
+
// showed the new data, but the live preview didn't.
|
|
493
|
+
const { buildLocalStorageScript } = require('../editorProxy');
|
|
494
|
+
const originalData = {
|
|
495
|
+
articles: '[{"id":"a1","title":"Test"}]',
|
|
496
|
+
};
|
|
497
|
+
const updatedData = {
|
|
498
|
+
articles: '[{"id":"a1","title":"Test","collectionIds":["c1"]}]',
|
|
499
|
+
collections: '[{"id":"c1","name":"Dev"}]',
|
|
500
|
+
};
|
|
501
|
+
const script1 = buildLocalStorageScript(originalData, 'scenario-abc');
|
|
502
|
+
const script2 = buildLocalStorageScript(updatedData, 'scenario-abc');
|
|
503
|
+
// Both scripts use the same scenario ID
|
|
504
|
+
expect(script1).toContain('scenario-abc');
|
|
505
|
+
expect(script2).toContain('scenario-abc');
|
|
506
|
+
// The guard values must be DIFFERENT so the browser re-seeds
|
|
507
|
+
// Extract the guard comparison value from each script
|
|
508
|
+
const guardPattern = /__codeyam_ls_sid__.*?===\s*([^\)]+)\)/;
|
|
509
|
+
const guard1 = script1.match(guardPattern)?.[1];
|
|
510
|
+
const guard2 = script2.match(guardPattern)?.[1];
|
|
511
|
+
expect(guard1).toBeDefined();
|
|
512
|
+
expect(guard2).toBeDefined();
|
|
513
|
+
expect(guard1).not.toEqual(guard2);
|
|
514
|
+
});
|
|
418
515
|
});
|
|
419
516
|
describe('localStorage injection in HTML responses', () => {
|
|
420
517
|
it('should inject localStorage script before health script in HTML', () => {
|
|
@@ -493,6 +590,121 @@ describe('editorProxy', () => {
|
|
|
493
590
|
expect(response.headers.get('content-encoding')).toBeNull();
|
|
494
591
|
});
|
|
495
592
|
});
|
|
593
|
+
describe('session cookie injection into requests', () => {
|
|
594
|
+
let targetServer;
|
|
595
|
+
let targetPort;
|
|
596
|
+
let tempDir;
|
|
597
|
+
let receivedCookies;
|
|
598
|
+
let originalProjectRoot;
|
|
599
|
+
beforeEach(() => {
|
|
600
|
+
const fs = require('fs');
|
|
601
|
+
const path = require('path');
|
|
602
|
+
const os = require('os');
|
|
603
|
+
const { getProjectRoot } = require('../../state');
|
|
604
|
+
const { setProjectRoot } = require('../../state');
|
|
605
|
+
originalProjectRoot = getProjectRoot();
|
|
606
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'proxy-req-cookie-'));
|
|
607
|
+
setProjectRoot(tempDir);
|
|
608
|
+
receivedCookies = undefined;
|
|
609
|
+
});
|
|
610
|
+
afterEach(async () => {
|
|
611
|
+
const { stopEditorProxy, invalidateScenarioCache, } = require('../editorProxy');
|
|
612
|
+
const { setProjectRoot } = require('../../state');
|
|
613
|
+
invalidateScenarioCache();
|
|
614
|
+
await stopEditorProxy();
|
|
615
|
+
if (targetServer?.listening) {
|
|
616
|
+
await new Promise((resolve) => targetServer.close(() => resolve()));
|
|
617
|
+
}
|
|
618
|
+
if (originalProjectRoot) {
|
|
619
|
+
setProjectRoot(originalProjectRoot);
|
|
620
|
+
}
|
|
621
|
+
const fs = require('fs');
|
|
622
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
623
|
+
resetPreviewHealth();
|
|
624
|
+
});
|
|
625
|
+
it('should forward seed adapter session cookies in the request Cookie header', async () => {
|
|
626
|
+
const fs = require('fs');
|
|
627
|
+
const path = require('path');
|
|
628
|
+
const { startEditorProxy, invalidateScenarioCache, } = require('../editorProxy');
|
|
629
|
+
// Set up scenario files
|
|
630
|
+
const scenarioId = 'integration-auth-test';
|
|
631
|
+
const codeyamDir = path.join(tempDir, '.codeyam');
|
|
632
|
+
const scenariosDir = path.join(codeyamDir, 'editor-scenarios');
|
|
633
|
+
fs.mkdirSync(scenariosDir, { recursive: true });
|
|
634
|
+
fs.writeFileSync(path.join(codeyamDir, 'active-scenario.json'), JSON.stringify({ scenarioId, type: 'application' }));
|
|
635
|
+
fs.writeFileSync(path.join(scenariosDir, `${scenarioId}.json`), JSON.stringify({
|
|
636
|
+
type: 'application',
|
|
637
|
+
seed: { user: [{ id: '1' }] },
|
|
638
|
+
sessionCookies: [
|
|
639
|
+
{
|
|
640
|
+
name: 'sb-test-auth-token',
|
|
641
|
+
value: '{"access_token":"test-jwt","refresh_token":"test-ref"}',
|
|
642
|
+
path: '/',
|
|
643
|
+
sameSite: 'Lax',
|
|
644
|
+
},
|
|
645
|
+
],
|
|
646
|
+
}));
|
|
647
|
+
// Target server that captures the request Cookie header
|
|
648
|
+
targetServer = http.createServer((req, res) => {
|
|
649
|
+
receivedCookies = req.headers.cookie;
|
|
650
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
651
|
+
res.end('OK');
|
|
652
|
+
});
|
|
653
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
654
|
+
targetPort = targetServer.address().port;
|
|
655
|
+
// Invalidate to force re-read of scenario data
|
|
656
|
+
invalidateScenarioCache();
|
|
657
|
+
const result = await startEditorProxy({
|
|
658
|
+
port: 0,
|
|
659
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
660
|
+
});
|
|
661
|
+
expect(result).not.toBeNull();
|
|
662
|
+
// Make request WITHOUT any cookies (simulates first iframe load after scenario switch)
|
|
663
|
+
await fetch(`http://127.0.0.1:${result.port}/library`);
|
|
664
|
+
// The target server should have received the injected auth cookie
|
|
665
|
+
expect(receivedCookies).toBeDefined();
|
|
666
|
+
expect(receivedCookies).toContain('sb-test-auth-token=');
|
|
667
|
+
expect(receivedCookies).toContain('test-jwt');
|
|
668
|
+
});
|
|
669
|
+
it('should merge injected cookies with existing browser cookies', async () => {
|
|
670
|
+
const fs = require('fs');
|
|
671
|
+
const path = require('path');
|
|
672
|
+
const { startEditorProxy, invalidateScenarioCache, } = require('../editorProxy');
|
|
673
|
+
const scenarioId = 'integration-merge-test';
|
|
674
|
+
const codeyamDir = path.join(tempDir, '.codeyam');
|
|
675
|
+
const scenariosDir = path.join(codeyamDir, 'editor-scenarios');
|
|
676
|
+
fs.mkdirSync(scenariosDir, { recursive: true });
|
|
677
|
+
fs.writeFileSync(path.join(codeyamDir, 'active-scenario.json'), JSON.stringify({ scenarioId, type: 'application' }));
|
|
678
|
+
fs.writeFileSync(path.join(scenariosDir, `${scenarioId}.json`), JSON.stringify({
|
|
679
|
+
type: 'application',
|
|
680
|
+
seed: {},
|
|
681
|
+
session: { cookieValue: 'sess_alice' },
|
|
682
|
+
sessionCookies: [
|
|
683
|
+
{ name: 'sb-auth', value: 'supabase-jwt', path: '/' },
|
|
684
|
+
],
|
|
685
|
+
}));
|
|
686
|
+
targetServer = http.createServer((req, res) => {
|
|
687
|
+
receivedCookies = req.headers.cookie;
|
|
688
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
689
|
+
res.end('OK');
|
|
690
|
+
});
|
|
691
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
692
|
+
targetPort = targetServer.address().port;
|
|
693
|
+
invalidateScenarioCache();
|
|
694
|
+
const result = await startEditorProxy({
|
|
695
|
+
port: 0,
|
|
696
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
697
|
+
});
|
|
698
|
+
// Make request WITH an existing cookie (simulates browser that already has cookies)
|
|
699
|
+
await fetch(`http://127.0.0.1:${result.port}/library`, {
|
|
700
|
+
headers: { Cookie: 'other-cookie=existing-value' },
|
|
701
|
+
});
|
|
702
|
+
// Should have both the existing cookie and the injected ones
|
|
703
|
+
expect(receivedCookies).toContain('other-cookie=existing-value');
|
|
704
|
+
expect(receivedCookies).toContain('session-token=sess_alice');
|
|
705
|
+
expect(receivedCookies).toContain('sb-auth=supabase-jwt');
|
|
706
|
+
});
|
|
707
|
+
});
|
|
496
708
|
describe('Cache-Control on HTML responses', () => {
|
|
497
709
|
let targetServer;
|
|
498
710
|
let targetPort;
|
|
@@ -546,5 +758,243 @@ describe('editorProxy', () => {
|
|
|
546
758
|
expect(response.headers.get('cache-control')).toBeNull();
|
|
547
759
|
});
|
|
548
760
|
});
|
|
761
|
+
describe('escapeHtml', () => {
|
|
762
|
+
it('should escape ampersands, angle brackets, and quotes', () => {
|
|
763
|
+
expect(escapeHtml('<script>alert("xss")</script>')).toBe('<script>alert("xss")</script>');
|
|
764
|
+
});
|
|
765
|
+
it('should escape single quotes', () => {
|
|
766
|
+
expect(escapeHtml("it's")).toBe('it's');
|
|
767
|
+
});
|
|
768
|
+
it('should return empty string for empty input', () => {
|
|
769
|
+
expect(escapeHtml('')).toBe('');
|
|
770
|
+
});
|
|
771
|
+
it('should leave safe text unchanged', () => {
|
|
772
|
+
expect(escapeHtml('Hello world 123')).toBe('Hello world 123');
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
describe('buildErrorPage', () => {
|
|
776
|
+
it('should generate a complete HTML document', () => {
|
|
777
|
+
const page = buildErrorPage(500, 'Internal Server Error', 'something broke');
|
|
778
|
+
expect(page).toContain('<!DOCTYPE html>');
|
|
779
|
+
expect(page).toContain('<html');
|
|
780
|
+
expect(page).toContain('</html>');
|
|
781
|
+
});
|
|
782
|
+
it('should include the status code and title', () => {
|
|
783
|
+
const page = buildErrorPage(502, 'Dev Server Unreachable', 'details here');
|
|
784
|
+
expect(page).toContain('502');
|
|
785
|
+
expect(page).toContain('Dev Server Unreachable');
|
|
786
|
+
});
|
|
787
|
+
it('should include the error detail text', () => {
|
|
788
|
+
const page = buildErrorPage(500, 'Error', 'Connection refused on port 3000');
|
|
789
|
+
expect(page).toContain('Connection refused on port 3000');
|
|
790
|
+
});
|
|
791
|
+
it('should escape HTML in the detail to prevent XSS', () => {
|
|
792
|
+
const page = buildErrorPage(500, 'Error', '<script>alert("xss")</script>');
|
|
793
|
+
expect(page).not.toContain('<script>alert("xss")</script>');
|
|
794
|
+
expect(page).toContain('<script>alert("xss")</script>');
|
|
795
|
+
});
|
|
796
|
+
it('should include codeyam-server-error postMessage', () => {
|
|
797
|
+
const page = buildErrorPage(500, 'Error', 'detail');
|
|
798
|
+
expect(page).toContain('codeyam-server-error');
|
|
799
|
+
expect(page).toContain('postMessage');
|
|
800
|
+
});
|
|
801
|
+
it('should NOT include codeyam-preview-ready postMessage', () => {
|
|
802
|
+
const page = buildErrorPage(500, 'Error', 'detail');
|
|
803
|
+
expect(page).not.toContain('codeyam-preview-ready');
|
|
804
|
+
});
|
|
805
|
+
it('should include a retry button that sends codeyam-server-error-retry', () => {
|
|
806
|
+
const page = buildErrorPage(500, 'Error', 'detail');
|
|
807
|
+
expect(page).toContain('codeyam-server-error-retry');
|
|
808
|
+
// Should have a button element
|
|
809
|
+
expect(page).toMatch(/<button[^>]*>/i);
|
|
810
|
+
});
|
|
811
|
+
it('should include the status code in the postMessage data', () => {
|
|
812
|
+
const page = buildErrorPage(502, 'Unreachable', 'detail');
|
|
813
|
+
// The postMessage should include statusCode: 502
|
|
814
|
+
expect(page).toContain('502');
|
|
815
|
+
});
|
|
816
|
+
it('should escape HTML in the title to prevent XSS', () => {
|
|
817
|
+
const page = buildErrorPage(500, '<img onerror=alert(1)>', 'detail');
|
|
818
|
+
expect(page).not.toContain('<img onerror=alert(1)>');
|
|
819
|
+
expect(page).toContain('<img onerror=alert(1)>');
|
|
820
|
+
});
|
|
821
|
+
it('should handle multiline error detail', () => {
|
|
822
|
+
const detail = 'Error on line 1\nStack trace line 2\nStack trace line 3';
|
|
823
|
+
const page = buildErrorPage(500, 'Error', detail);
|
|
824
|
+
expect(page).toContain('Error on line 1');
|
|
825
|
+
expect(page).toContain('Stack trace line 3');
|
|
826
|
+
});
|
|
827
|
+
it('should handle empty detail', () => {
|
|
828
|
+
const page = buildErrorPage(500, 'Error', '');
|
|
829
|
+
expect(page).toContain('<!DOCTYPE html>');
|
|
830
|
+
expect(page).toContain('codeyam-server-error');
|
|
831
|
+
});
|
|
832
|
+
});
|
|
833
|
+
describe('5xx error page serving', () => {
|
|
834
|
+
let targetServer;
|
|
835
|
+
let targetPort;
|
|
836
|
+
afterEach(async () => {
|
|
837
|
+
const { stopEditorProxy } = require('../editorProxy');
|
|
838
|
+
await stopEditorProxy();
|
|
839
|
+
if (targetServer?.listening) {
|
|
840
|
+
await new Promise((resolve) => targetServer.close(() => resolve()));
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
it('should serve an error page instead of raw HTML for 500 responses', async () => {
|
|
844
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
845
|
+
targetServer = http.createServer((_req, res) => {
|
|
846
|
+
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
847
|
+
res.end('<html><body>Internal Server Error</body></html>');
|
|
848
|
+
});
|
|
849
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
850
|
+
targetPort = targetServer.address().port;
|
|
851
|
+
const result = await startEditorProxy({
|
|
852
|
+
port: 0,
|
|
853
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
854
|
+
});
|
|
855
|
+
expect(result).not.toBeNull();
|
|
856
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/`);
|
|
857
|
+
expect(response.status).toBe(500);
|
|
858
|
+
const body = await response.text();
|
|
859
|
+
// Should contain the friendly error page, not the raw error
|
|
860
|
+
expect(body).toContain('codeyam-server-error');
|
|
861
|
+
expect(body).toContain('Internal Server Error');
|
|
862
|
+
});
|
|
863
|
+
it('should NOT replace non-HTML 500 responses', async () => {
|
|
864
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
865
|
+
targetServer = http.createServer((_req, res) => {
|
|
866
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
867
|
+
res.end(JSON.stringify({ error: 'server error' }));
|
|
868
|
+
});
|
|
869
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
870
|
+
targetPort = targetServer.address().port;
|
|
871
|
+
const result = await startEditorProxy({
|
|
872
|
+
port: 0,
|
|
873
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
874
|
+
});
|
|
875
|
+
expect(result).not.toBeNull();
|
|
876
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/api/data`);
|
|
877
|
+
expect(response.status).toBe(500);
|
|
878
|
+
const body = await response.text();
|
|
879
|
+
// JSON responses should pass through unchanged
|
|
880
|
+
expect(body).toContain('"error":"server error"');
|
|
881
|
+
expect(body).not.toContain('codeyam-server-error');
|
|
882
|
+
});
|
|
883
|
+
it('should serve an error page for 500 responses with no content type', async () => {
|
|
884
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
885
|
+
// Simulates Next.js returning bare "Internal Server Error" with no Content-Type
|
|
886
|
+
targetServer = http.createServer((_req, res) => {
|
|
887
|
+
res.writeHead(500);
|
|
888
|
+
res.end('Internal Server Error');
|
|
889
|
+
});
|
|
890
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
891
|
+
targetPort = targetServer.address().port;
|
|
892
|
+
const result = await startEditorProxy({
|
|
893
|
+
port: 0,
|
|
894
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
895
|
+
});
|
|
896
|
+
expect(result).not.toBeNull();
|
|
897
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/`);
|
|
898
|
+
expect(response.status).toBe(500);
|
|
899
|
+
const body = await response.text();
|
|
900
|
+
expect(body).toContain('codeyam-server-error');
|
|
901
|
+
expect(body).toContain('<!DOCTYPE html>');
|
|
902
|
+
expect(body).toContain('Internal Server Error');
|
|
903
|
+
});
|
|
904
|
+
it('should serve an error page for 500 text/plain responses', async () => {
|
|
905
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
906
|
+
targetServer = http.createServer((_req, res) => {
|
|
907
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
908
|
+
res.end('Something went wrong');
|
|
909
|
+
});
|
|
910
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
911
|
+
targetPort = targetServer.address().port;
|
|
912
|
+
const result = await startEditorProxy({
|
|
913
|
+
port: 0,
|
|
914
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
915
|
+
});
|
|
916
|
+
expect(result).not.toBeNull();
|
|
917
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/`);
|
|
918
|
+
expect(response.status).toBe(500);
|
|
919
|
+
const body = await response.text();
|
|
920
|
+
expect(body).toContain('codeyam-server-error');
|
|
921
|
+
expect(body).toContain('Something went wrong');
|
|
922
|
+
});
|
|
923
|
+
it('should serve an error page for 503 responses', async () => {
|
|
924
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
925
|
+
targetServer = http.createServer((_req, res) => {
|
|
926
|
+
res.writeHead(503, { 'Content-Type': 'text/html' });
|
|
927
|
+
res.end('<html><body>Service Unavailable</body></html>');
|
|
928
|
+
});
|
|
929
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
930
|
+
targetPort = targetServer.address().port;
|
|
931
|
+
const result = await startEditorProxy({
|
|
932
|
+
port: 0,
|
|
933
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
934
|
+
});
|
|
935
|
+
expect(result).not.toBeNull();
|
|
936
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/`);
|
|
937
|
+
expect(response.status).toBe(503);
|
|
938
|
+
const body = await response.text();
|
|
939
|
+
expect(body).toContain('codeyam-server-error');
|
|
940
|
+
});
|
|
941
|
+
it('should serve an error page for POST requests returning 500', async () => {
|
|
942
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
943
|
+
targetServer = http.createServer((_req, res) => {
|
|
944
|
+
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
945
|
+
res.end('<html><body>POST Error</body></html>');
|
|
946
|
+
});
|
|
947
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
948
|
+
targetPort = targetServer.address().port;
|
|
949
|
+
const result = await startEditorProxy({
|
|
950
|
+
port: 0,
|
|
951
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
952
|
+
});
|
|
953
|
+
expect(result).not.toBeNull();
|
|
954
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/api/action`, {
|
|
955
|
+
method: 'POST',
|
|
956
|
+
headers: { 'Content-Type': 'application/json' },
|
|
957
|
+
body: JSON.stringify({ test: true }),
|
|
958
|
+
});
|
|
959
|
+
expect(response.status).toBe(500);
|
|
960
|
+
const body = await response.text();
|
|
961
|
+
expect(body).toContain('codeyam-server-error');
|
|
962
|
+
expect(body).toContain('POST Error');
|
|
963
|
+
});
|
|
964
|
+
it('should NOT serve an error page for 4xx responses', async () => {
|
|
965
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
966
|
+
targetServer = http.createServer((_req, res) => {
|
|
967
|
+
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
968
|
+
res.end('<html><body>Not Found</body></html>');
|
|
969
|
+
});
|
|
970
|
+
await new Promise((resolve) => targetServer.listen(0, '127.0.0.1', () => resolve()));
|
|
971
|
+
targetPort = targetServer.address().port;
|
|
972
|
+
const result = await startEditorProxy({
|
|
973
|
+
port: 0,
|
|
974
|
+
targetUrl: `http://localhost:${targetPort}`,
|
|
975
|
+
});
|
|
976
|
+
expect(result).not.toBeNull();
|
|
977
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/missing`);
|
|
978
|
+
expect(response.status).toBe(404);
|
|
979
|
+
const body = await response.text();
|
|
980
|
+
// 4xx should pass through normally (with health script injected, not error page)
|
|
981
|
+
expect(body).not.toContain('codeyam-server-error');
|
|
982
|
+
expect(body).toContain('Not Found');
|
|
983
|
+
});
|
|
984
|
+
it('should serve an HTML error page for 502 connection failures', async () => {
|
|
985
|
+
const { startEditorProxy } = require('../editorProxy');
|
|
986
|
+
// No target server — connection will fail
|
|
987
|
+
const result = await startEditorProxy({
|
|
988
|
+
port: 0,
|
|
989
|
+
targetUrl: 'http://127.0.0.1:19999',
|
|
990
|
+
});
|
|
991
|
+
expect(result).not.toBeNull();
|
|
992
|
+
const response = await fetch(`http://127.0.0.1:${result.port}/`);
|
|
993
|
+
expect(response.status).toBe(502);
|
|
994
|
+
const body = await response.text();
|
|
995
|
+
expect(body).toContain('codeyam-server-error');
|
|
996
|
+
expect(body).toContain('<!DOCTYPE html>');
|
|
997
|
+
});
|
|
998
|
+
});
|
|
549
999
|
});
|
|
550
1000
|
//# sourceMappingURL=editorProxy.test.js.map
|