@lowdefy/server-dev 6.0.0 → 7.0.0
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/client/App.jsx +52 -24
- package/client/Inspector.jsx +73 -30
- package/client/JourneyObserver.jsx +47 -0
- package/client/Page.jsx +54 -22
- package/client/Recorder.jsx +73 -0
- package/client/Routing.jsx +37 -13
- package/client/clientBuildImports.test.mjs +63 -0
- package/client/devStreamConnections.test.mjs +40 -0
- package/client/feedback/FeedbackMount.jsx +2 -2
- package/client/feedback/FeedbackOverlay.jsx +7 -4
- package/client/feedback/feedbackStyles.js +3 -0
- package/client/journeyObserver/startJourneyObserver.js +101 -0
- package/client/journeyObserver/startJourneyObserver.test.mjs +149 -0
- package/client/openInEditor/OpenInEditorListener.jsx +2 -0
- package/client/recorder/buildEngineRecord.js +37 -0
- package/client/recorder/buildInteractionRecord.js +64 -0
- package/client/recorder/buildTraceEvent.js +57 -0
- package/client/recorder/buildTraceEvent.test.mjs +81 -0
- package/client/recorder/chunkRecords.js +69 -0
- package/client/recorder/chunkRecords.test.mjs +59 -0
- package/client/recorder/collectEventActions.js +30 -0
- package/client/recorder/collectEventEndpoints.js +40 -0
- package/client/recorder/collectEventRequests.js +39 -0
- package/client/recorder/createPairingBuffer.js +187 -0
- package/client/recorder/createPairingBuffer.test.mjs +405 -0
- package/client/recorder/createPasswordRedactor.js +84 -0
- package/client/recorder/createRecordBatcher.js +54 -0
- package/client/recorder/createRecordBatcher.test.mjs +76 -0
- package/client/recorder/createRecorder.js +216 -0
- package/client/recorder/createRecorder.test.mjs +318 -0
- package/client/recorder/createRecordingSession.js +61 -0
- package/client/recorder/createRecordingSession.test.mjs +72 -0
- package/client/recorder/diffStateWrites.js +77 -0
- package/client/recorder/diffStateWrites.test.mjs +66 -0
- package/client/recorder/isEventCall.js +30 -0
- package/client/recorder/jsonType.js +39 -0
- package/client/recorder/keyChord.js +47 -0
- package/client/recorder/keyChord.test.mjs +50 -0
- package/client/recorder/sendRecords.js +40 -0
- package/client/recorder/toJsonSafe.js +29 -0
- package/lib/client/BuildingPage.jsx +3 -1
- package/lib/client/ErrorBar.jsx +17 -13
- package/lib/client/RedirectingPage.jsx +56 -0
- package/lib/client/auth/Auth.jsx +11 -6
- package/lib/client/auth/AuthConfigured.jsx +224 -39
- package/lib/client/auth/AuthNotConfigured.js +45 -4
- package/lib/client/auth/authNotConfiguredParity.test.mjs +61 -0
- package/lib/client/auth/authTemplateSync.test.mjs +40 -0
- package/lib/client/auth/betterAuthSessionContract.test.mjs +181 -0
- package/lib/client/auth/createFetchCheckingBuild.js +45 -0
- package/lib/client/bundleBuildId.js +25 -0
- package/lib/client/collectVisibleBlockIds.js +51 -0
- package/lib/client/getCspNonce.js +25 -0
- package/lib/client/getPagePath.js +36 -0
- package/lib/client/getPagePath.test.mjs +51 -0
- package/lib/client/utils/formatErrorsForCopy.js +30 -0
- package/lib/client/utils/formatErrorsForCopy.test.mjs +39 -0
- package/lib/client/utils/getErrorBarColor.js +25 -0
- package/lib/client/utils/getErrorBarColor.test.mjs +34 -0
- package/lib/client/utils/request.js +8 -1
- package/lib/client/utils/usePageConfig.js +89 -25
- package/lib/client/utils/usePageConfig.test.mjs +198 -13
- package/lib/configTree/buildConfigTree.mjs +58 -0
- package/lib/configTree/buildConfigTree.test.mjs +77 -0
- package/lib/configTree/collectConfigText.mjs +101 -0
- package/lib/configTree/collectConfigText.test.mjs +116 -0
- package/lib/configTree/prepareScratchServer.mjs +46 -0
- package/lib/configTree/runConfigTreeBuild.mjs +88 -0
- package/lib/configTree/runConfigTreeBuild.skipPluginChecks.test.mjs +74 -0
- package/lib/configTree/runConfigTreeBuild.test.mjs +202 -0
- package/lib/docs/JourneyStepError.js +30 -0
- package/lib/docs/acquireBrowserSlot.js +30 -0
- package/lib/docs/addNestedEndpoints.js +54 -0
- package/lib/docs/addNestedEndpoints.test.mjs +185 -0
- package/lib/docs/addWriteFlags.js +77 -0
- package/lib/docs/buildEditedPages.js +50 -0
- package/lib/docs/buildWaitHeader.js +21 -0
- package/lib/docs/captureAnnotatedScreenshot.js +23 -12
- package/lib/docs/checkAgentFiles.js +148 -0
- package/lib/docs/checkAgentFiles.test.mjs +225 -0
- package/lib/docs/checkStepReferences.js +239 -0
- package/lib/docs/checkStepReferences.test.mjs +173 -0
- package/lib/docs/checkpointStore.js +3 -0
- package/lib/docs/clientErrorStore.js +18 -1
- package/lib/docs/clientErrorStore.test.mjs +46 -0
- package/lib/docs/collectExercised.js +52 -0
- package/lib/docs/createBrowserLifecycle.js +102 -0
- package/lib/docs/createBrowserLifecycle.test.mjs +212 -0
- package/lib/docs/createDocsMcpServer.js +345 -388
- package/lib/docs/createDocsMcpServer.test.mjs +644 -4
- package/lib/docs/createDocsMcpServerRunJourney.test.mjs +148 -0
- package/lib/docs/createJourneyActors.chromium.test.mjs +227 -0
- package/lib/docs/createJourneyActors.js +213 -0
- package/lib/docs/createJourneyActors.test.mjs +79 -0
- package/lib/docs/createJourneyObservations.js +80 -0
- package/lib/docs/createLeftOriginError.js +26 -0
- package/lib/docs/createNetworkCounter.js +101 -0
- package/lib/docs/dataSets/checkSharedCollectionIds.js +67 -0
- package/lib/docs/dataSets/dataSessionRegistry.js +25 -0
- package/lib/docs/dataSets/dataSetJourneys.chromium.mongodb.test.mjs +679 -0
- package/lib/docs/dataSets/describeDataSetResult.js +25 -0
- package/lib/docs/dataSets/describeDatabaseTarget.js +46 -0
- package/lib/docs/dataSets/deserializeFixture.js +34 -0
- package/lib/docs/dataSets/drainSessionWork.js +37 -0
- package/lib/docs/dataSets/drainSessionWork.test.mjs +64 -0
- package/lib/docs/dataSets/duplicateIndexName.js +24 -0
- package/lib/docs/dataSets/findCollectionCollisions.js +52 -0
- package/lib/docs/dataSets/getDataStore.js +106 -0
- package/lib/docs/dataSets/getDataStore.mongodb.test.mjs +63 -0
- package/lib/docs/dataSets/getDataStore.test.mjs +195 -0
- package/lib/docs/dataSets/groupDataSetByCollection.js +44 -0
- package/lib/docs/dataSets/insertFixture.js +57 -0
- package/lib/docs/dataSets/insertGeneratedDocuments.js +41 -0
- package/lib/docs/dataSets/isDataStoreGone.js +29 -0
- package/lib/docs/dataSets/loadDataSetCollection.js +42 -0
- package/lib/docs/dataSets/mergeCollectionIndexes.js +52 -0
- package/lib/docs/dataSets/mergeCollectionIndexes.test.mjs +59 -0
- package/lib/docs/dataSets/openDataSession.js +119 -0
- package/lib/docs/dataSets/openDataSession.mongodb.test.mjs +343 -0
- package/lib/docs/dataSets/pickDataStorePort.js +58 -0
- package/lib/docs/dataSets/pickDataStorePort.test.mjs +63 -0
- package/lib/docs/dataSets/readConnectionArtifacts.js +46 -0
- package/lib/docs/dataSets/readDataSession.js +41 -0
- package/lib/docs/dataSets/readDataSession.test.mjs +57 -0
- package/lib/docs/dataSets/readDataSet.js +68 -0
- package/lib/docs/dataSets/readDataSet.test.mjs +220 -0
- package/lib/docs/dataSets/registerDataStoreShutdown.js +47 -0
- package/lib/docs/dataSets/removeDataStoreFiles.js +32 -0
- package/lib/docs/dataSets/resolveDataSetCollection.js +46 -0
- package/lib/docs/dataSets/resolveJourneyDataSet.js +106 -0
- package/lib/docs/dataSets/resolveJourneyDataSet.test.mjs +130 -0
- package/lib/docs/dataSets/sweepOrphanDatabases.js +33 -0
- package/lib/docs/dataSets/test/app/lowdefy.yaml +203 -0
- package/lib/docs/dataSets/test/app/modules/archive/module.lowdefy.yaml +30 -0
- package/lib/docs/dataSets/test/app/tests/data/shop.yaml +8 -0
- package/lib/docs/dataSets/test/buildTestApp.mjs +43 -0
- package/lib/docs/devEventBus.js +136 -0
- package/lib/docs/devEventBus.test.mjs +269 -0
- package/lib/docs/devToolDefinitions.js +529 -0
- package/lib/docs/docSources.js +21 -0
- package/lib/docs/docs.test.mjs +171 -15
- package/lib/docs/docsIndex.test.mjs +377 -0
- package/lib/docs/evalOperator.js +5 -3
- package/lib/docs/evalOperatorHeadless.js +84 -12
- package/lib/docs/evalOperatorHeadless.test.mjs +7 -1
- package/lib/docs/evalOperatorInTab.js +2 -1
- package/lib/docs/findConfig.js +95 -49
- package/lib/docs/fitResponse.js +81 -0
- package/lib/docs/fitResponse.test.mjs +128 -0
- package/lib/docs/formatFeedback.js +26 -5
- package/lib/docs/formatFeedback.test.mjs +48 -0
- package/lib/docs/getAppMap.js +7 -1
- package/lib/docs/getBrowser.js +150 -80
- package/lib/docs/getBrowser.test.mjs +407 -16
- package/lib/docs/getBuildId.js +61 -0
- package/lib/docs/getBuildId.test.mjs +84 -0
- package/lib/docs/getBuildStatus.js +54 -6
- package/lib/docs/getBuildStatus.test.mjs +133 -0
- package/lib/docs/getBuildStatusAfterEdits.js +35 -0
- package/lib/docs/getBuildStatusAfterEdits.test.mjs +76 -0
- package/lib/docs/getCoreDoc.js +9 -1
- package/lib/docs/getDoc.js +100 -0
- package/lib/docs/getDocsIndex.js +152 -0
- package/lib/docs/getHazards.js +115 -0
- package/lib/docs/getHazards.test.mjs +175 -0
- package/lib/docs/getMailOutboxDirectory.js +26 -0
- package/lib/docs/getOverview.js +79 -13
- package/lib/docs/getOverviewBasePath.test.mjs +37 -0
- package/lib/docs/getPageBuildStatus.js +46 -0
- package/lib/docs/getPluginDoc.js +21 -23
- package/lib/docs/getSchema.js +33 -1
- package/lib/docs/getStaleStatus.js +36 -0
- package/lib/docs/getStaleStatus.test.mjs +74 -0
- package/lib/docs/guardJourneyOrigin.js +39 -0
- package/lib/docs/inspectState.js +5 -3
- package/lib/docs/inspectStateFromTab.js +2 -2
- package/lib/docs/inspectStateHeadless.js +89 -27
- package/lib/docs/inspectStateHeadless.test.mjs +20 -1
- package/lib/docs/installHeadlessShell.failure.test.mjs +45 -0
- package/lib/docs/installHeadlessShell.js +123 -0
- package/lib/docs/installHeadlessShell.test.mjs +70 -0
- package/lib/docs/installHeadlessShell.timeout.test.mjs +72 -0
- package/lib/docs/isHeadlessShellIncomplete.js +34 -0
- package/lib/docs/isHeadlessShellIncomplete.test.mjs +63 -0
- package/lib/docs/isPageReady.js +77 -0
- package/lib/docs/isPageReady.test.mjs +235 -0
- package/lib/docs/isRunErrorEntry.js +25 -0
- package/lib/docs/journeyMutantCookie.chromium.test.mjs +150 -0
- package/lib/docs/journeyRunRecording.js +35 -0
- package/lib/docs/journeyRunRecording.test.mjs +39 -0
- package/lib/docs/keepEventStreamAlive.js +68 -0
- package/lib/docs/keepEventStreamAlive.test.mjs +77 -0
- package/lib/docs/launchBrowser.js +83 -0
- package/lib/docs/launchBrowser.test.mjs +175 -0
- package/lib/docs/listModuleDocEntries.js +69 -0
- package/lib/docs/listPackageDocFiles.js +67 -0
- package/lib/docs/listPluginDocEntries.js +111 -0
- package/lib/docs/listPlugins.js +9 -58
- package/lib/docs/listTypes.js +14 -6
- package/lib/docs/loadFrameworkHazards.js +40 -0
- package/lib/docs/loadFrameworkHazards.test.mjs +43 -0
- package/lib/docs/loadState.js +103 -35
- package/lib/docs/makeModuleManifestDoc.js +174 -0
- package/lib/docs/matchExercisedPages.js +35 -0
- package/lib/docs/matchJourneyRoute.js +69 -0
- package/lib/docs/matchJourneyRoute.test.mjs +178 -0
- package/lib/docs/mergeNetworkSnapshots.js +49 -0
- package/lib/docs/nextJourneySequence.js +30 -0
- package/lib/docs/noBrowserError.js +22 -0
- package/lib/docs/observe/TRANSIENT_SELECTOR.js +21 -0
- package/lib/docs/observe/claimExpectedErrors.js +67 -0
- package/lib/docs/observe/createJourneyAppErrors.js +236 -0
- package/lib/docs/observe/createJourneyAppErrors.test.mjs +385 -0
- package/lib/docs/observe/evaluateInvariants.js +183 -0
- package/lib/docs/observe/evaluateInvariants.test.mjs +299 -0
- package/lib/docs/observe/findingKey.js +29 -0
- package/lib/docs/observe/hasNoEffect.js +31 -0
- package/lib/docs/observe/hasNoEffect.test.mjs +37 -0
- package/lib/docs/observe/installStepObserver.js +72 -0
- package/lib/docs/observe/isAppApiUrl.js +33 -0
- package/lib/docs/observe/parseAppApiUrl.js +37 -0
- package/lib/docs/observe/readStepObserver.js +42 -0
- package/lib/docs/observe/relativeSource.js +29 -0
- package/lib/docs/observe/resolveConfigKeySource.js +33 -0
- package/lib/docs/observe/takeJourneyEvents.js +36 -0
- package/lib/docs/observe/toAppErrorFailure.js +61 -0
- package/lib/docs/observe/usesSearchStage.js +45 -0
- package/lib/docs/observe/waitForClientErrorReports.js +31 -0
- package/lib/docs/observe/watchJourneyContext.js +75 -0
- package/lib/docs/observe/withAppErrors.js +31 -0
- package/lib/docs/observe/withAppErrors.test.mjs +101 -0
- package/lib/docs/openJourney.js +94 -0
- package/lib/docs/openJourneyEmail.js +41 -0
- package/lib/docs/openJourneyEmail.test.mjs +187 -0
- package/lib/docs/pageBlocks.js +47 -0
- package/lib/docs/pageBuildStatus.test.mjs +103 -0
- package/lib/{client/setPageId.js → docs/parseModuleSource.js} +11 -12
- package/lib/docs/rails/authEngineActions.js +53 -0
- package/lib/docs/rails/authEngineActions.test.mjs +69 -0
- package/lib/docs/rails/authEngineMethods.js +52 -0
- package/lib/docs/rails/authEngineMethods.test.mjs +36 -0
- package/lib/docs/rails/checkAuthActionsRan.js +66 -0
- package/lib/docs/rails/checkAuthActionsRan.test.mjs +149 -0
- package/lib/docs/rails/checkClickRails.js +56 -0
- package/lib/docs/rails/createDataSetRails.js +82 -0
- package/lib/docs/rails/createDataSetRails.test.mjs +172 -0
- package/lib/docs/rails/findExternalBlocks.js +147 -0
- package/lib/docs/rails/findExternalBlocks.test.mjs +254 -0
- package/lib/docs/rails/installAuthActionRecorder.js +56 -0
- package/lib/docs/rails/readAuthActionRecorder.js +32 -0
- package/lib/docs/rails/readBuiltArtifact.js +30 -0
- package/lib/docs/readConnectionPlugins.js +26 -0
- package/lib/docs/readDevAuthMode.js +32 -0
- package/lib/docs/readDocEntry.js +40 -0
- package/lib/docs/readDocTitle.js +26 -0
- package/lib/docs/readJourneyEmailMatch.js +57 -0
- package/lib/docs/readJourneyEmailMatch.test.mjs +110 -0
- package/lib/docs/readJourneySession.js +56 -0
- package/lib/docs/readMailOutbox.js +37 -0
- package/lib/docs/readPagePath.js +27 -0
- package/lib/docs/readPluginPackages.js +99 -0
- package/lib/docs/readProxyBuildWait.js +38 -0
- package/lib/docs/readRoutineSteps.js +45 -0
- package/lib/docs/registerShownTextEngine.js +118 -0
- package/lib/docs/requestRestart.js +30 -0
- package/lib/docs/requestRestart.test.mjs +49 -0
- package/lib/docs/resolvePageInstance.js +46 -0
- package/lib/docs/resolvePageInstance.test.mjs +81 -0
- package/lib/docs/resolveSource.js +11 -7
- package/lib/docs/resolveSource.test.mjs +1 -1
- package/lib/docs/resolveToolCaller.js +62 -0
- package/lib/docs/reviewPage.js +51 -0
- package/lib/docs/reviewPageBuilds.js +56 -0
- package/lib/docs/reviewPageBuilds.test.mjs +207 -0
- package/lib/docs/runCheck.js +75 -0
- package/lib/docs/runCheck.test.mjs +91 -0
- package/lib/docs/runCheckChild.js +49 -0
- package/lib/docs/runEndpoint.js +185 -0
- package/lib/docs/runEndpoint.test.mjs +509 -0
- package/lib/docs/runErrorBuffers.js +99 -0
- package/lib/docs/runErrorBuffers.test.mjs +95 -0
- package/lib/docs/runJourney.js +347 -0
- package/lib/docs/runJourney.test.mjs +2383 -0
- package/lib/docs/runJourneyAsUsers.js +44 -0
- package/lib/docs/runJourneyDataSet.test.mjs +274 -0
- package/lib/docs/runJourneySteps.js +1320 -0
- package/lib/docs/runRequest.js +100 -59
- package/lib/docs/runRequest.test.mjs +190 -0
- package/lib/docs/saveAnnotatedScreenshot.js +1 -1
- package/lib/docs/scaffoldPage.js +3 -1
- package/lib/docs/screenshotPage.js +163 -11
- package/lib/docs/screenshotPage.test.mjs +263 -1
- package/lib/docs/screenshotPageClip.test.mjs +4 -0
- package/lib/docs/searchDocs.js +82 -30
- package/lib/docs/searchDocs.test.mjs +100 -0
- package/lib/docs/searchIcons.js +90 -0
- package/lib/docs/searchIcons.test.mjs +127 -0
- package/lib/docs/selectExercised.js +39 -0
- package/lib/docs/selectFinalState.js +66 -0
- package/lib/docs/selectFinalState.test.mjs +51 -0
- package/lib/docs/serverErrorStore.js +54 -0
- package/lib/docs/serverErrorStore.test.mjs +50 -0
- package/lib/docs/setupTestFixtures.mjs +133 -39
- package/lib/docs/shownTextSelector.js +28 -0
- package/lib/docs/snapshotState.js +13 -5
- package/lib/docs/splitSearchTerms.js +62 -0
- package/lib/docs/splitSearchTerms.test.mjs +50 -0
- package/lib/docs/stateCheckpoints.test.mjs +77 -0
- package/lib/docs/tabAvailable.js +6 -5
- package/lib/docs/tabChannel.js +127 -21
- package/lib/docs/tabChannel.test.mjs +187 -29
- package/lib/docs/unsettledPageNote.js +24 -0
- package/lib/docs/validateJourneyMail.js +36 -0
- package/lib/docs/validateJourneyTimeout.js +38 -0
- package/lib/docs/validateJourneyTimeout.test.mjs +29 -0
- package/lib/docs/validateRecordingParam.js +42 -0
- package/lib/docs/validateStateSelection.js +33 -0
- package/lib/docs/validateStateSelection.test.mjs +33 -0
- package/lib/docs/validateViewport.js +51 -0
- package/lib/docs/validateViewport.test.mjs +54 -0
- package/lib/docs/waitForBuild.js +50 -0
- package/lib/docs/waitForBuild.test.mjs +75 -0
- package/lib/docs/waitForJourneyEmail.js +77 -0
- package/lib/docs/withBrowserSlot.js +45 -0
- package/lib/docs/withBrowserSlot.test.mjs +75 -0
- package/lib/docs/withDataSession.js +53 -0
- package/lib/server/applyDataSetRedirect.js +83 -0
- package/lib/server/applyDataSetRedirect.test.mjs +340 -0
- package/lib/server/applyDataSetRedirectTenantReach.test.mjs +204 -0
- package/lib/server/applyDataSetRedirectWalled.test.mjs +131 -0
- package/lib/server/auth/createSystemContext.js +73 -0
- package/lib/server/auth/getAuth.js +46 -0
- package/lib/server/auth/getHeadlessUser.js +9 -8
- package/lib/server/auth/getHeadlessUser.test.mjs +41 -0
- package/lib/server/auth/getMockUser.js +18 -14
- package/lib/server/auth/{getAuthConfig.js → getStrategies.js} +12 -10
- package/lib/server/auth/headlessUser.js +3 -2
- package/lib/server/auth/journeyActor.js +35 -0
- package/lib/server/auth/resolveHeadlessUser.test.mjs +0 -4
- package/lib/server/checkPageRecord.js +44 -0
- package/lib/server/contextMapBudget.js +24 -0
- package/lib/server/contextMapBudget.test.mjs +98 -0
- package/lib/server/continueJitKeys.js +28 -0
- package/lib/server/continueJitKeys.test.mjs +43 -0
- package/lib/server/createDataSessionEndedError.js +33 -0
- package/lib/server/createDataSetRefusal.js +26 -0
- package/lib/server/createLowdefyContext.js +174 -41
- package/lib/server/createLowdefyContext.test.mjs +437 -0
- package/lib/server/getClientAddress.js +51 -0
- package/lib/server/getClientAddress.test.mjs +56 -0
- package/lib/server/getPageJitEnrichment.test.mjs +29 -11
- package/lib/server/hashConfigContent.js +26 -0
- package/lib/server/importAppCode.test.mjs +57 -0
- package/lib/server/isRoutineStep.js +27 -0
- package/lib/server/jitPageBuilder.js +309 -126
- package/lib/server/jitPageBuilder.skipPluginChecks.test.mjs +78 -0
- package/lib/server/jitPageBuilder.test.mjs +218 -0
- package/lib/server/journeyCookies/JOURNEY_COOKIES.js +37 -0
- package/lib/server/journeyCookies/forwardJourneyCookies.js +46 -0
- package/lib/server/journeyCookies/readJourneyCookie.js +52 -0
- package/lib/server/journeyCookies/writeJourneyCookie.js +46 -0
- package/lib/server/journeyCookies.js +22 -0
- package/lib/server/journeyCookies.test.mjs +145 -0
- package/lib/server/loadDynamicJsMap.js +47 -0
- package/lib/server/log/createHandleError.js +38 -2
- package/lib/server/log/createHandleError.test.mjs +125 -2
- package/lib/server/log/createLogger.js +3 -0
- package/lib/server/log/createLogger.test.mjs +77 -0
- package/lib/server/log/logRequest.js +2 -3
- package/lib/server/mutantDataSetWrappers.test.mjs +112 -0
- package/lib/server/mutants/applyMutant.js +39 -0
- package/lib/server/mutants/artifactPatterns.js +25 -0
- package/lib/server/mutants/buildAnchor.js +45 -0
- package/lib/server/mutants/collectSharedIds.js +41 -0
- package/lib/server/mutants/configPathSegments.js +38 -0
- package/lib/server/mutants/createMutantReadConfigFile.js +42 -0
- package/lib/server/mutants/describeEvent.js +22 -0
- package/lib/server/mutants/enumerateArtifact.js +56 -0
- package/lib/server/mutants/findNodeByKey.js +45 -0
- package/lib/server/mutants/findNodeByPointer.js +49 -0
- package/lib/server/mutants/getArtifactKind.js +32 -0
- package/lib/server/mutants/groupMutantCopies.js +56 -0
- package/lib/server/mutants/hashArtifact.js +25 -0
- package/lib/server/mutants/hashMutantTarget.js +34 -0
- package/lib/server/mutants/listMutants.js +122 -0
- package/lib/server/mutants/listMutants.test.mjs +502 -0
- package/lib/server/mutants/mutantId.js +30 -0
- package/lib/server/mutants/mutantRuns.js +57 -0
- package/lib/server/mutants/mutantRuns.test.mjs +136 -0
- package/lib/server/mutants/operators/dropAction.js +47 -0
- package/lib/server/mutants/operators/dropBlock.js +44 -0
- package/lib/server/mutants/operators/dropPayload.js +52 -0
- package/lib/server/mutants/operators/dropStep.js +44 -0
- package/lib/server/mutants/operators/flipVisible.js +53 -0
- package/lib/server/mutants/operators/index.js +37 -0
- package/lib/server/mutants/operators/retargetLink.js +72 -0
- package/lib/server/mutants/operators/skipValidate.js +77 -0
- package/lib/server/mutants/operators/swapIf.js +112 -0
- package/lib/server/mutants/operators.test.mjs +396 -0
- package/lib/server/mutants/positionFreePath.js +38 -0
- package/lib/server/mutants/removeFromParent.js +28 -0
- package/lib/server/mutants/test/fixtures.mjs +173 -0
- package/lib/server/mutants/test/keyArtifact.mjs +63 -0
- package/lib/server/mutants/validateMutantParam.js +69 -0
- package/lib/server/mutants/validateMutantsBody.js +88 -0
- package/lib/server/mutants/walkArtifact.js +179 -0
- package/lib/server/pageBuildRecords.js +131 -0
- package/lib/server/pageBuildRecords.test.mjs +258 -0
- package/lib/server/pageCache.mjs +22 -7
- package/lib/server/pageCache.test.mjs +22 -7
- package/lib/server/pageRebuilds.test.mjs +543 -0
- package/lib/server/pruneJitMaps.js +36 -0
- package/lib/server/pruneJitMaps.test.mjs +55 -0
- package/lib/server/readInstanceRecord.js +33 -0
- package/lib/server/readInstanceRecord.test.mjs +99 -0
- package/lib/server/readMergedMaps.js +86 -0
- package/lib/server/readMergedMaps.test.mjs +79 -0
- package/lib/server/recording/appendRecords.js +33 -0
- package/lib/server/recording/errorRecordingStamp.js +34 -0
- package/lib/server/recording/errorRecordingStamp.test.mjs +31 -0
- package/lib/server/recording/isRecordingEnabled.js +31 -0
- package/lib/server/recording/readRecordingCookie.js +71 -0
- package/lib/server/recording/readRecordingCookie.test.mjs +73 -0
- package/lib/server/recording/recordingCookiePayload.js +33 -0
- package/lib/server/recording/servedBuilds.js +46 -0
- package/lib/server/recording/servedBuilds.test.mjs +42 -0
- package/lib/server/scrubSecrets.js +23 -0
- package/lib/server/sinkExternalConnections.js +95 -0
- package/lib/server/sinkExternalConnections.test.mjs +135 -0
- package/lib/server/skipStaleMapWrites.js +62 -0
- package/lib/server/skipStaleMapWrites.test.mjs +113 -0
- package/lib/server/startIdleGc.js +67 -0
- package/lib/server/startIdleGc.test.mjs +138 -0
- package/lib/server/testFixtures/importAppCodeTwice.mjs +70 -0
- package/lib/server/trackSessionWork.js +30 -0
- package/lib/vite/createDevServerExclude.js +40 -0
- package/lib/vite/createDevServerExclude.test.mjs +79 -0
- package/manager/getContext.mjs +24 -2
- package/manager/processes/initialBuild.mjs +14 -0
- package/manager/processes/initialBuild.test.mjs +101 -0
- package/manager/processes/lowdefyBuild.mjs +30 -7
- package/manager/processes/lowdefyBuild.skipPluginChecks.test.mjs +62 -0
- package/manager/processes/lowdefyBuild.test.mjs +136 -1
- package/manager/processes/optimizeDependencies.mjs +59 -0
- package/manager/processes/restartServer.mjs +34 -6
- package/manager/processes/restartServer.test.mjs +162 -0
- package/manager/processes/shutdownServer.mjs +11 -0
- package/manager/processes/shutdownServer.test.mjs +45 -0
- package/manager/processes/startFirstServer.mjs +46 -0
- package/manager/processes/startFirstServer.test.mjs +326 -0
- package/manager/processes/startMailSink.mjs +135 -0
- package/manager/processes/startMailSink.test.mjs +146 -0
- package/manager/processes/startProxy.mjs +129 -12
- package/manager/processes/startProxy.test.mjs +366 -0
- package/manager/processes/startServer.mjs +47 -6
- package/manager/processes/startServer.test.mjs +155 -0
- package/manager/processes/startWatchers.mjs +6 -4
- package/manager/processes/syncServer.mjs +69 -0
- package/manager/processes/syncServer.test.mjs +141 -0
- package/manager/processes/waitForDevServer.mjs +48 -0
- package/manager/processes/waitForDevServer.test.mjs +112 -0
- package/manager/run.mjs +128 -43
- package/manager/utils/BatchChanges.mjs +21 -5
- package/manager/utils/BatchChanges.test.mjs +77 -0
- package/manager/utils/acquireDevInstance.mjs +99 -0
- package/manager/utils/acquireDevInstance.test.mjs +160 -0
- package/manager/utils/createBuildActivity.mjs +67 -0
- package/manager/utils/createBuildActivity.test.mjs +58 -0
- package/manager/utils/createChangeSignal.mjs +39 -0
- package/manager/utils/createChangeSignal.test.mjs +62 -0
- package/manager/utils/createCustomPluginMessagesMap.mjs +23 -33
- package/manager/utils/createCustomPluginTypesMap.mjs +24 -30
- package/manager/utils/createCustomPluginTypesMap.test.mjs +94 -0
- package/manager/utils/createDotPathIgnore.mjs +44 -0
- package/manager/utils/createDotPathIgnore.test.mjs +65 -0
- package/manager/utils/createIdleGc.mjs +51 -0
- package/manager/utils/createIdleGc.test.mjs +77 -0
- package/manager/utils/createRequestActivity.mjs +100 -0
- package/manager/utils/createRequestActivity.test.mjs +121 -0
- package/manager/utils/createServerArtifactTracker.mjs +83 -0
- package/manager/utils/createServerArtifactTracker.test.mjs +78 -0
- package/manager/utils/createServerEnv.mjs +39 -0
- package/manager/utils/filesHaveSameBytes.mjs +41 -0
- package/manager/utils/findBuildFilesOutsideWatch.mjs +59 -0
- package/manager/utils/findBuildFilesOutsideWatch.test.mjs +111 -0
- package/manager/utils/importFresh.mjs +46 -0
- package/manager/utils/importFresh.test.mjs +72 -0
- package/manager/utils/importFreshWorker.mjs +20 -0
- package/manager/utils/killTaggedBrowser.mjs +35 -0
- package/manager/utils/pagePathChanged.mjs +56 -0
- package/manager/utils/pruneRecordings.mjs +85 -0
- package/manager/utils/pruneRecordings.test.mjs +117 -0
- package/manager/utils/publishBuildDirectory.mjs +121 -0
- package/manager/utils/publishBuildDirectory.order.test.mjs +74 -0
- package/manager/utils/publishBuildDirectory.test.mjs +262 -0
- package/manager/utils/readBasePath.mjs +27 -0
- package/manager/utils/readBasePath.test.mjs +43 -0
- package/manager/utils/readBuildStatusWait.mjs +67 -0
- package/manager/utils/readManagerVersion.mjs +30 -0
- package/manager/utils/readManagerVersion.test.mjs +35 -0
- package/manager/utils/readPluginDefinitions.mjs +36 -0
- package/manager/utils/resolveDevAuthUrl.mjs +58 -0
- package/manager/utils/resolveDevAuthUrl.test.mjs +107 -0
- package/manager/utils/resolvePorts.mjs +49 -0
- package/manager/utils/setupWatcher.mjs +19 -11
- package/manager/utils/startRecordingPruner.mjs +45 -0
- package/manager/utils/startRecordingPruner.test.mjs +66 -0
- package/manager/utils/waitForChildExit.mjs +53 -0
- package/manager/utils/waitForChildExit.test.mjs +70 -0
- package/manager/utils/waitForServer.mjs +44 -0
- package/manager/utils/writeBuildStatus.mjs +1 -1
- package/manager/watchers/createPluginSourceIgnore.mjs +77 -0
- package/manager/watchers/envWatcher.mjs +9 -2
- package/manager/watchers/envWatcher.test.mjs +87 -0
- package/manager/watchers/listServerSidePackages.mjs +47 -0
- package/manager/watchers/listServerSidePackages.test.mjs +38 -0
- package/manager/watchers/lowdefyBuildWatcher.mjs +106 -22
- package/manager/watchers/lowdefyBuildWatcher.test.mjs +309 -0
- package/manager/watchers/pluginSourceWatcher.mjs +79 -0
- package/manager/watchers/pluginSourceWatcher.test.mjs +222 -0
- package/manager/watchers/restartRequestWatcher.mjs +71 -0
- package/manager/watchers/restartRequestWatcher.test.mjs +111 -0
- package/manager/watchers/selectLocalPluginPackages.mjs +48 -0
- package/manager/watchers/selectLocalPluginPackages.test.mjs +73 -0
- package/manager/watchers/serverPackageWatcher.mjs +38 -0
- package/package.json +61 -49
- package/package.original.json +61 -49
- package/src/app.js +131 -20
- package/src/html/renderDevPage.js +63 -11
- package/src/html/renderDevPage.test.mjs +138 -0
- package/src/lib/getRequestPath.js +29 -0
- package/src/middleware/createSameOriginGuard.js +37 -0
- package/src/middleware/createSameOriginGuard.test.mjs +102 -0
- package/src/middleware/errorHandler.js +51 -1
- package/src/middleware/errorHandler.test.mjs +196 -14
- package/src/middleware/isRebindingSafeHost.js +44 -0
- package/src/middleware/isRebindingSafeHost.test.mjs +32 -0
- package/src/middleware/localDevToolsOnly.js +38 -0
- package/src/middleware/localDevToolsOnly.test.mjs +61 -0
- package/src/middleware/noStore.js +27 -0
- package/src/middleware/noStore.test.mjs +48 -0
- package/src/middleware/requestTimeout.js +38 -0
- package/src/middleware/staleFlag.js +76 -0
- package/src/middleware/staleFlag.test.mjs +127 -0
- package/src/middleware/stampCaller.js +38 -0
- package/src/middleware/stampCaller.test.mjs +64 -0
- package/src/routes/agent.js +15 -3
- package/src/routes/auth.js +29 -20
- package/src/routes/auth.test.mjs +30 -56
- package/src/routes/clientError.js +13 -13
- package/src/routes/cron.js +3 -1
- package/src/routes/cronForward.js +4 -2
- package/src/routes/detached.js +22 -9
- package/src/routes/devInspect.js +17 -8
- package/src/routes/devInspect.test.mjs +44 -7
- package/src/routes/devRecording.js +113 -0
- package/src/routes/devRecording.test.mjs +253 -0
- package/src/routes/docs/buildStatus.js +10 -2
- package/src/routes/docs/buildStatus.test.mjs +46 -0
- package/src/routes/docs/content.js +5 -3
- package/src/routes/docs/evalOperator.js +15 -1
- package/src/routes/docs/events.js +50 -0
- package/src/routes/docs/events.test.mjs +117 -0
- package/src/routes/docs/find.js +9 -1
- package/src/routes/docs/icons.js +30 -0
- package/src/routes/docs/inspectState.js +16 -1
- package/src/routes/docs/journey.js +194 -0
- package/src/routes/docs/journey.test.mjs +401 -0
- package/src/routes/docs/journeyRefusals.test.mjs +71 -0
- package/src/routes/docs/loadState.js +4 -2
- package/src/routes/docs/mcp.js +34 -3
- package/src/routes/docs/mcp.test.mjs +130 -0
- package/src/routes/docs/mutants.js +78 -0
- package/src/routes/docs/mutants.test.mjs +180 -0
- package/src/routes/docs/parsePathParamsParam.js +41 -0
- package/src/routes/docs/parsePathParamsParam.test.mjs +42 -0
- package/src/routes/docs/parseUserParam.js +27 -21
- package/src/routes/docs/parseUserParam.test.mjs +17 -5
- package/src/routes/docs/restart.js +35 -0
- package/src/routes/docs/restart.test.mjs +64 -0
- package/src/routes/docs/runEndpoint.js +54 -0
- package/src/routes/docs/runEndpoint.test.mjs +165 -0
- package/src/routes/docs/runRequest.js +25 -8
- package/src/routes/docs/runRequest.test.mjs +92 -0
- package/src/routes/docs/screenshot.js +50 -2
- package/src/routes/docs/screenshot.test.mjs +117 -0
- package/src/routes/docs/search.js +15 -2
- package/src/routes/docs/snapshotState.js +17 -3
- package/src/routes/endpoints.js +27 -26
- package/src/routes/endpointsTextAnswer.test.mjs +77 -0
- package/src/routes/feedback.js +10 -13
- package/src/routes/jitPage.js +99 -35
- package/src/routes/jitPage.test.mjs +248 -0
- package/src/routes/mcp.js +82 -5
- package/src/routes/mcp.test.mjs +215 -0
- package/src/routes/mcpMemberToken.test.mjs +125 -0
- package/src/routes/mcpProtectedResourceMetadata.js +34 -0
- package/src/routes/mcpProtectedResourceMetadata.test.mjs +65 -0
- package/src/routes/mountDevPageRoutes.js +25 -0
- package/src/routes/mountDevPageRoutes.test.mjs +30 -0
- package/src/routes/mountOauthDiscovery.js +44 -0
- package/src/routes/mountOauthDiscovery.test.mjs +79 -0
- package/src/routes/normalizeMcpProtocolVersionHeader.js +46 -0
- package/src/routes/normalizeMcpProtocolVersionHeader.test.mjs +62 -0
- package/src/routes/reload.js +16 -0
- package/src/routes/request.js +6 -4
- package/src/routes/request.test.mjs +9 -5
- package/src/routes/requestBody.test.mjs +159 -0
- package/src/routes/usage.js +6 -2
- package/src/routes/user.js +27 -0
- package/src/routes/websocket.js +29 -8
- package/src/routes/websocket.test.mjs +65 -0
- package/src/routes/wellKnownFallback.js +30 -0
- package/src/routes/wellKnownFallback.test.mjs +32 -0
- package/src/websocket/devWebSocket.js +41 -26
- package/src/websocket/devWebSocket.test.mjs +157 -0
- package/vite.config.js +53 -23
- package/lib/server/auth/getDevSession.js +0 -70
- package/lib/server/auth/getDevSession.test.mjs +0 -138
- package/lib/server/auth/session.js +0 -39
- package/manager/processes/warnAuthUrlPortMismatch.mjs +0 -47
- package/manager/processes/warnAuthUrlPortMismatch.test.mjs +0 -93
- package/manager/watchers/moduleBuildWatcher.mjs +0 -79
- package/manager/watchers/serverArtifactWatcher.mjs +0 -120
- package/src/routes/apiPage.js +0 -37
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { type } from '@lowdefy/helpers';
|
|
18
|
+
|
|
19
|
+
import operators from './operators/index.js';
|
|
20
|
+
|
|
21
|
+
const ARTIFACT_PATTERN = /^(pages\/.+\.json|api\/.+\.json|events\.json)$/;
|
|
22
|
+
|
|
23
|
+
// The `mutant` of a journey POST: one mutant from POST /lowdefy-docs/mutants,
|
|
24
|
+
// with the build it was listed against. Returns an error message, or
|
|
25
|
+
// undefined when it is valid.
|
|
26
|
+
function validateMutantParam(mutant) {
|
|
27
|
+
if (!type.isObject(mutant)) {
|
|
28
|
+
return `The "mutant" param must be an object { buildId, artifact, key, arg, operator }. Received ${JSON.stringify(
|
|
29
|
+
mutant
|
|
30
|
+
)}.`;
|
|
31
|
+
}
|
|
32
|
+
if (
|
|
33
|
+
!type.isString(mutant.artifact) ||
|
|
34
|
+
!ARTIFACT_PATTERN.test(mutant.artifact) ||
|
|
35
|
+
mutant.artifact.includes('..')
|
|
36
|
+
) {
|
|
37
|
+
return `"mutant.artifact" must be a page, endpoint or app events artifact path, such as "pages/tickets.json". Received ${JSON.stringify(
|
|
38
|
+
mutant.artifact
|
|
39
|
+
)}.`;
|
|
40
|
+
}
|
|
41
|
+
if (type.isUndefined(operators[mutant.operator])) {
|
|
42
|
+
return `"mutant.operator" must be one of ${Object.keys(operators).join(
|
|
43
|
+
', '
|
|
44
|
+
)}. Received ${JSON.stringify(mutant.operator)}.`;
|
|
45
|
+
}
|
|
46
|
+
if (!type.isString(mutant.key)) {
|
|
47
|
+
return `"mutant.key" must be a string. Received ${JSON.stringify(mutant.key)}.`;
|
|
48
|
+
}
|
|
49
|
+
if (
|
|
50
|
+
!type.isNone(mutant.pointer) &&
|
|
51
|
+
!(
|
|
52
|
+
type.isArray(mutant.pointer) &&
|
|
53
|
+
mutant.pointer.every((step) => type.isString(step) || type.isInt(step))
|
|
54
|
+
)
|
|
55
|
+
) {
|
|
56
|
+
return `"mutant.pointer" must be an array of keys and indexes. Received ${JSON.stringify(
|
|
57
|
+
mutant.pointer
|
|
58
|
+
)}.`;
|
|
59
|
+
}
|
|
60
|
+
if (!type.isNone(mutant.nodeHash) && !type.isString(mutant.nodeHash)) {
|
|
61
|
+
return `"mutant.nodeHash" must be a string. Received ${JSON.stringify(mutant.nodeHash)}.`;
|
|
62
|
+
}
|
|
63
|
+
if (!type.isNone(mutant.arg) && !type.isString(mutant.arg)) {
|
|
64
|
+
return `"mutant.arg" must be a string. Received ${JSON.stringify(mutant.arg)}.`;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default validateMutantParam;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { type } from '@lowdefy/helpers';
|
|
18
|
+
|
|
19
|
+
import operators from './operators/index.js';
|
|
20
|
+
|
|
21
|
+
function isStringArray(value) {
|
|
22
|
+
return type.isArray(value) && value.every((item) => type.isString(item));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Ids name build artifacts (`pages/<id>.json`), so one that climbs out of
|
|
26
|
+
// the build directory is refused, as readConfigFile refuses it.
|
|
27
|
+
function isId(value) {
|
|
28
|
+
return type.isString(value) && !value.includes('..');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isIdArray(value) {
|
|
32
|
+
return type.isArray(value) && value.every((item) => isId(item));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// The body of POST /lowdefy-docs/mutants: what a set of journey runs
|
|
36
|
+
// exercised. Returns { body } with defaults, or { error } naming the field.
|
|
37
|
+
function validateMutantsBody(body) {
|
|
38
|
+
if (!type.isObject(body)) {
|
|
39
|
+
return { error: `The body must be a JSON object. Received ${JSON.stringify(body)}.` };
|
|
40
|
+
}
|
|
41
|
+
const { pages = [], requests = [], endpoints = [], appEvents = false } = body;
|
|
42
|
+
if (!isIdArray(pages)) {
|
|
43
|
+
return { error: `"pages" must be an array of page ids. Received ${JSON.stringify(pages)}.` };
|
|
44
|
+
}
|
|
45
|
+
if (
|
|
46
|
+
!type.isArray(requests) ||
|
|
47
|
+
!requests.every(
|
|
48
|
+
(request) => type.isObject(request) && isId(request.pageId) && isId(request.requestId)
|
|
49
|
+
)
|
|
50
|
+
) {
|
|
51
|
+
return {
|
|
52
|
+
error: `"requests" must be an array of { pageId, requestId }. Received ${JSON.stringify(
|
|
53
|
+
requests
|
|
54
|
+
)}.`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (!isIdArray(endpoints)) {
|
|
58
|
+
return {
|
|
59
|
+
error: `"endpoints" must be an array of endpoint ids. Received ${JSON.stringify(endpoints)}.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!type.isBoolean(appEvents)) {
|
|
63
|
+
return { error: `"appEvents" must be a boolean. Received ${JSON.stringify(appEvents)}.` };
|
|
64
|
+
}
|
|
65
|
+
if (!type.isNone(body.operators)) {
|
|
66
|
+
const unknown = isStringArray(body.operators)
|
|
67
|
+
? body.operators.filter((name) => type.isUndefined(operators[name]))
|
|
68
|
+
: [body.operators];
|
|
69
|
+
if (unknown.length > 0) {
|
|
70
|
+
return {
|
|
71
|
+
error: `"operators" must be an array of operator names (${Object.keys(operators).join(
|
|
72
|
+
', '
|
|
73
|
+
)}). Received ${JSON.stringify(body.operators)}.`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
body: {
|
|
79
|
+
pages,
|
|
80
|
+
requests: requests.map(({ pageId, requestId }) => ({ pageId, requestId })),
|
|
81
|
+
endpoints,
|
|
82
|
+
appEvents,
|
|
83
|
+
operators: body.operators ?? null,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default validateMutantsBody;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { type } from '@lowdefy/helpers';
|
|
18
|
+
|
|
19
|
+
import getArtifactKind from './getArtifactKind.js';
|
|
20
|
+
import isRoutineStep from '../isRoutineStep.js';
|
|
21
|
+
|
|
22
|
+
function rootScope({ artifact, root }) {
|
|
23
|
+
const kind = getArtifactKind(artifact);
|
|
24
|
+
switch (kind) {
|
|
25
|
+
case 'page':
|
|
26
|
+
return {
|
|
27
|
+
kind,
|
|
28
|
+
pageId: root.pageId,
|
|
29
|
+
role: 'block',
|
|
30
|
+
region: 'block',
|
|
31
|
+
blockId: root.blockId ?? root.pageId,
|
|
32
|
+
blockType: root.type,
|
|
33
|
+
parentBlockId: null,
|
|
34
|
+
};
|
|
35
|
+
case 'app':
|
|
36
|
+
return { kind, pageId: 'app', role: 'events', region: 'events', blockId: null };
|
|
37
|
+
case 'request':
|
|
38
|
+
return { kind, pageId: root.pageId, requestId: root.requestId, role: 'requestRoot' };
|
|
39
|
+
case 'endpoint':
|
|
40
|
+
return { kind, endpointId: root.endpointId, role: 'endpointRoot' };
|
|
41
|
+
default:
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function blockChildScope({ scope, key }) {
|
|
47
|
+
switch (key) {
|
|
48
|
+
case 'slots':
|
|
49
|
+
return { ...scope, role: 'slots', region: 'slots' };
|
|
50
|
+
case 'events':
|
|
51
|
+
return { ...scope, role: 'events', region: 'events' };
|
|
52
|
+
case 'properties':
|
|
53
|
+
return { ...scope, role: 'value', region: 'blockProperties' };
|
|
54
|
+
case 'validate':
|
|
55
|
+
return { ...scope, role: 'validate', region: 'validate' };
|
|
56
|
+
case 'requests':
|
|
57
|
+
// Only the page itself holds requests; the server never runs this copy
|
|
58
|
+
// of their config (it reads the request artifact), so only the payload
|
|
59
|
+
// the browser evaluates is walked.
|
|
60
|
+
return scope.parentBlockId === null
|
|
61
|
+
? { ...scope, role: 'requests', region: 'requests' }
|
|
62
|
+
: null;
|
|
63
|
+
default:
|
|
64
|
+
return { ...scope, role: 'value', region: 'blockOther' };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The scope of `child`, found at `key` in `node` (scope `scope`), or null to
|
|
69
|
+
// leave the subtree out. A scope names the node's role in the artifact
|
|
70
|
+
// (block, action, payload, step, ...) and where it sits (page, block,
|
|
71
|
+
// event), which is what operators enumerate by and anchors are built from.
|
|
72
|
+
function childScope({ scope, key, child }) {
|
|
73
|
+
switch (scope.role) {
|
|
74
|
+
case 'block':
|
|
75
|
+
return blockChildScope({ scope, key });
|
|
76
|
+
case 'slots':
|
|
77
|
+
return { ...scope, role: 'slot' };
|
|
78
|
+
case 'slot':
|
|
79
|
+
return key === 'blocks' ? { ...scope, role: 'slotBlocks' } : null;
|
|
80
|
+
case 'slotBlocks':
|
|
81
|
+
return {
|
|
82
|
+
...scope,
|
|
83
|
+
role: 'block',
|
|
84
|
+
region: 'block',
|
|
85
|
+
parentBlockId: scope.blockId,
|
|
86
|
+
blockId: child?.blockId,
|
|
87
|
+
blockType: child?.type,
|
|
88
|
+
};
|
|
89
|
+
case 'events':
|
|
90
|
+
return { ...scope, role: 'event', eventName: key };
|
|
91
|
+
case 'event':
|
|
92
|
+
return key === 'try' || key === 'catch' ? { ...scope, role: 'actions', branch: key } : null;
|
|
93
|
+
case 'actions':
|
|
94
|
+
return { ...scope, role: 'action', actionId: child?.id, actionType: child?.type };
|
|
95
|
+
case 'action':
|
|
96
|
+
return {
|
|
97
|
+
...scope,
|
|
98
|
+
role: 'value',
|
|
99
|
+
region: key === 'params' ? 'actionParams' : 'actionOther',
|
|
100
|
+
};
|
|
101
|
+
case 'validate':
|
|
102
|
+
return { ...scope, role: 'validateEntry' };
|
|
103
|
+
case 'requests':
|
|
104
|
+
return { ...scope, role: 'request', requestId: child?.requestId };
|
|
105
|
+
case 'request':
|
|
106
|
+
return key === 'payload' ? { ...scope, role: 'payload', region: 'requestPayload' } : null;
|
|
107
|
+
case 'requestRoot':
|
|
108
|
+
return key === 'properties' ? { ...scope, role: 'value', region: 'requestProperties' } : null;
|
|
109
|
+
case 'endpointRoot':
|
|
110
|
+
return key === 'routine' ? { ...scope, role: 'routine', region: 'routine' } : null;
|
|
111
|
+
case 'routine':
|
|
112
|
+
// An array of routine items: steps, controls, or nested arrays.
|
|
113
|
+
if (isRoutineStep(child)) {
|
|
114
|
+
return { ...scope, role: 'step', stepId: child.stepId, stepType: child.type };
|
|
115
|
+
}
|
|
116
|
+
if (type.isArray(child)) {
|
|
117
|
+
return { ...scope, role: 'routine' };
|
|
118
|
+
}
|
|
119
|
+
if (type.isObject(child) && Object.keys(child).some((childKey) => childKey.startsWith(':'))) {
|
|
120
|
+
return { ...scope, role: 'control' };
|
|
121
|
+
}
|
|
122
|
+
return { ...scope, role: 'routineValue' };
|
|
123
|
+
case 'control':
|
|
124
|
+
// `:then`, `:else`, `:try`, `:parallel`, ... hold more steps; `:if`,
|
|
125
|
+
// `:set_state`, `:return`, ... hold values.
|
|
126
|
+
return { ...scope, role: type.isArray(child) ? 'routine' : 'routineValue' };
|
|
127
|
+
case 'step':
|
|
128
|
+
case 'routineValue':
|
|
129
|
+
return { ...scope, role: 'routineValue' };
|
|
130
|
+
default:
|
|
131
|
+
return { ...scope, role: 'value' };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Depth-first walk of one deserialised build artifact, calling visit for every
|
|
136
|
+
// object with its parent, its key in the parent, its scope and its pointer:
|
|
137
|
+
// the keys and array indexes that lead from the root to it.
|
|
138
|
+
function walkArtifact({ artifact, root, visit }) {
|
|
139
|
+
function walk({ node, parent, keyInParent, scope, pointer }) {
|
|
140
|
+
if (type.isArray(node)) {
|
|
141
|
+
node.forEach((child, index) => {
|
|
142
|
+
const next = childScope({ scope, key: index, child });
|
|
143
|
+
if (next !== null) {
|
|
144
|
+
walk({
|
|
145
|
+
node: child,
|
|
146
|
+
parent: node,
|
|
147
|
+
keyInParent: index,
|
|
148
|
+
scope: next,
|
|
149
|
+
pointer: [...pointer, index],
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!type.isObject(node)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
visit({ node, parent, keyInParent, artifact, scope, pointer });
|
|
159
|
+
Object.keys(node).forEach((key) => {
|
|
160
|
+
const next = childScope({ scope, key, child: node[key] });
|
|
161
|
+
if (next !== null) {
|
|
162
|
+
walk({
|
|
163
|
+
node: node[key],
|
|
164
|
+
parent: node,
|
|
165
|
+
keyInParent: key,
|
|
166
|
+
scope: next,
|
|
167
|
+
pointer: [...pointer, key],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const scope = rootScope({ artifact, root });
|
|
173
|
+
if (scope === null) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
walk({ node: root, parent: null, keyInParent: null, scope, pointer: [] });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default walkArtifact;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
|
|
20
|
+
import { resolveErrorLocation } from '@lowdefy/errors';
|
|
21
|
+
|
|
22
|
+
import mapPageBuildErrors from '../docs/mapPageBuildErrors.js';
|
|
23
|
+
import hashConfigContent from './hashConfigContent.js';
|
|
24
|
+
|
|
25
|
+
// What each page's latest JIT build read and how it ended, kept for the life of
|
|
26
|
+
// the server process. The dev server uses it to tell which built pages an edit
|
|
27
|
+
// touched and which pages currently fail to build, without the page being
|
|
28
|
+
// requested. Pages build concurrently on one shared build context, so the files
|
|
29
|
+
// a build reads are attributed through async context rather than the context.
|
|
30
|
+
const buildReads = new AsyncLocalStorage();
|
|
31
|
+
const records = new Map();
|
|
32
|
+
|
|
33
|
+
// Recorded for a file a build read twice with different content, or could not
|
|
34
|
+
// read: no content on disk matches it, so the page is always rebuilt.
|
|
35
|
+
const NEVER_MATCHES = 'conflict';
|
|
36
|
+
|
|
37
|
+
function recordRead({ reads, filePath, hash }) {
|
|
38
|
+
const previous = reads.files.get(filePath);
|
|
39
|
+
if (previous !== undefined && previous !== hash) {
|
|
40
|
+
reads.files.set(filePath, NEVER_MATCHES);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
reads.files.set(filePath, hash);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Every config file a page build reads comes through readConfigFile, and all
|
|
47
|
+
// app code it runs through importAppCode. App code can read anything, so a
|
|
48
|
+
// build that ran it is only marked, not traced.
|
|
49
|
+
function trackReadConfigFile({ readConfigFile, configDirectory }) {
|
|
50
|
+
return async function trackedReadConfigFile(filePath) {
|
|
51
|
+
const reads = buildReads.getStore();
|
|
52
|
+
const absolutePath = path.resolve(configDirectory, filePath);
|
|
53
|
+
let content;
|
|
54
|
+
try {
|
|
55
|
+
content = await readConfigFile(filePath);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (reads) recordRead({ reads, filePath: absolutePath, hash: NEVER_MATCHES });
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
if (reads) recordRead({ reads, filePath: absolutePath, hash: hashConfigContent(content) });
|
|
61
|
+
return content;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function trackFileReads({ context, configDirectory }) {
|
|
66
|
+
context.readConfigFile = trackReadConfigFile({
|
|
67
|
+
readConfigFile: context.readConfigFile,
|
|
68
|
+
configDirectory,
|
|
69
|
+
});
|
|
70
|
+
const importAppCode = context.importAppCode;
|
|
71
|
+
context.importAppCode = (filePath) => {
|
|
72
|
+
const reads = buildReads.getStore();
|
|
73
|
+
if (reads) reads.ranAppCode = true;
|
|
74
|
+
return importAppCode(filePath);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// The page route resolves a build error's source when it logs the error; a
|
|
79
|
+
// build nobody requested is never logged, so its errors are located here, from
|
|
80
|
+
// the keys the build added to its context.
|
|
81
|
+
function locateErrors({ error, context, configDirectory }) {
|
|
82
|
+
for (const buildError of error.buildErrors ?? [error]) {
|
|
83
|
+
if (buildError.source) continue;
|
|
84
|
+
try {
|
|
85
|
+
buildError.source =
|
|
86
|
+
resolveErrorLocation(buildError, {
|
|
87
|
+
keyMap: context.keyMap,
|
|
88
|
+
refMap: context.refMap,
|
|
89
|
+
configDirectory,
|
|
90
|
+
})?.source ?? null;
|
|
91
|
+
} catch {
|
|
92
|
+
// A malformed keyMap or refMap entry leaves the error unlocated.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// generation names the build context the page was built on, and checkedAt the
|
|
98
|
+
// change event counter when its build started: what it read is current as of
|
|
99
|
+
// that event.
|
|
100
|
+
async function record({ pageId, context, configDirectory, generation, checkedAt, build }) {
|
|
101
|
+
const reads = { files: new Map(), ranAppCode: false };
|
|
102
|
+
const builtAt = Date.now();
|
|
103
|
+
const describe = (errors) => ({
|
|
104
|
+
builtAt,
|
|
105
|
+
checkedAt,
|
|
106
|
+
errors,
|
|
107
|
+
files: reads.files,
|
|
108
|
+
generation,
|
|
109
|
+
ranAppCode: reads.ranAppCode,
|
|
110
|
+
});
|
|
111
|
+
let result;
|
|
112
|
+
try {
|
|
113
|
+
result = await buildReads.run(reads, build);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
locateErrors({ error, context, configDirectory });
|
|
116
|
+
records.set(pageId, describe(mapPageBuildErrors(error)));
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
// A plugin install ends the build before the page is built, so the page's
|
|
120
|
+
// previous record still describes it.
|
|
121
|
+
if (!result?.installing) {
|
|
122
|
+
records.set(pageId, describe(null));
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function get(pageId) {
|
|
128
|
+
return records.get(pageId) ?? null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export default { get, record, trackFileReads, trackReadConfigFile };
|