@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
package/client/App.jsx
CHANGED
|
@@ -18,19 +18,30 @@ import React, { Suspense, useCallback, useEffect, useRef, useState } from 'react
|
|
|
18
18
|
import useSWR from 'swr';
|
|
19
19
|
|
|
20
20
|
import { ErrorBoundary } from '@lowdefy/block-utils';
|
|
21
|
-
import { useDarkMode, useLocale } from '@lowdefy/client';
|
|
21
|
+
import { IconProvider, useDarkMode, useLocale } from '@lowdefy/client';
|
|
22
22
|
import { StyleProvider } from '@ant-design/cssinjs';
|
|
23
23
|
import { App as AntdApp, theme as antdTheme } from 'antd';
|
|
24
24
|
import { XProvider } from '@ant-design/x';
|
|
25
|
+
import { appStorageKey, serializer } from '@lowdefy/helpers';
|
|
25
26
|
|
|
26
27
|
import antdLocaleLoaders from '../build/i18n/antdLocales.js';
|
|
27
28
|
import antdXLocaleLoaders from '../build/i18n/antdXLocales.js';
|
|
28
29
|
import dayjsLocaleMap from '../build/i18n/dayjsLocales.js';
|
|
30
|
+
import rawTheme from '../build/theme.json';
|
|
29
31
|
import Auth from '../lib/client/auth/Auth.jsx';
|
|
30
32
|
import ErrorBar from '../lib/client/ErrorBar.jsx';
|
|
33
|
+
import getCspNonce from '../lib/client/getCspNonce.js';
|
|
31
34
|
import request from '../lib/client/utils/request.js';
|
|
32
35
|
import Routing from './Routing.jsx';
|
|
33
36
|
|
|
37
|
+
// rootConfig arrives after the first render; the build-written theme gives
|
|
38
|
+
// the icon provider its settings until then.
|
|
39
|
+
const buildTheme = serializer.deserialize(rawTheme);
|
|
40
|
+
|
|
41
|
+
// antd and antd X put this nonce on the style tags they add, so the page's
|
|
42
|
+
// Content-Security-Policy applies them. Empty (no nonce) when the policy is off.
|
|
43
|
+
const csp = { nonce: getCspNonce() };
|
|
44
|
+
|
|
34
45
|
function ThemeTokenResolver({ lowdefyRef, children }) {
|
|
35
46
|
const { token } = antdTheme.useToken();
|
|
36
47
|
if (!lowdefyRef.current.theme) {
|
|
@@ -40,7 +51,7 @@ function ThemeTokenResolver({ lowdefyRef, children }) {
|
|
|
40
51
|
return children;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
|
-
function App({ router }) {
|
|
54
|
+
function App({ config, router }) {
|
|
44
55
|
const lowdefyRef = useRef({});
|
|
45
56
|
const [runtimeErrors, setRuntimeErrors] = useState([]);
|
|
46
57
|
// Subscribe to rootConfig SWR cache — deduplicates with Routing's fetch.
|
|
@@ -50,9 +61,12 @@ function App({ router }) {
|
|
|
50
61
|
lowdefyRef.current.theme = rootConfig.theme;
|
|
51
62
|
}
|
|
52
63
|
|
|
64
|
+
// Device preferences, kept per app (the same key the HTML template's dark mode script reads).
|
|
65
|
+
const storageScope = { basePath: router.basePath, slug: config.slug };
|
|
53
66
|
const { algorithm, token, components } = useDarkMode({
|
|
54
67
|
antd: lowdefyRef.current.theme?.antd,
|
|
55
68
|
configDarkMode: lowdefyRef.current.theme?.darkMode,
|
|
69
|
+
storageKey: appStorageKey({ ...storageScope, name: 'lowdefy_darkMode' }),
|
|
56
70
|
});
|
|
57
71
|
|
|
58
72
|
const {
|
|
@@ -64,6 +78,7 @@ function App({ router }) {
|
|
|
64
78
|
antdLocaleLoaders,
|
|
65
79
|
antdXLocaleLoaders,
|
|
66
80
|
dayjsLocaleMap,
|
|
81
|
+
storageKey: appStorageKey({ ...storageScope, name: 'lowdefy_locale' }),
|
|
67
82
|
});
|
|
68
83
|
|
|
69
84
|
if (rootConfig?.i18n?.defaultLocale) {
|
|
@@ -88,6 +103,7 @@ function App({ router }) {
|
|
|
88
103
|
message: error.message,
|
|
89
104
|
source: error.source,
|
|
90
105
|
stack: error.stack,
|
|
106
|
+
prodError: error.prodError === true,
|
|
91
107
|
},
|
|
92
108
|
]);
|
|
93
109
|
}, []);
|
|
@@ -115,6 +131,7 @@ function App({ router }) {
|
|
|
115
131
|
return (
|
|
116
132
|
<StyleProvider layer>
|
|
117
133
|
<XProvider
|
|
134
|
+
csp={csp}
|
|
118
135
|
locale={mergedLocale}
|
|
119
136
|
form={
|
|
120
137
|
antdLocale?.Form?.defaultValidateMessages
|
|
@@ -130,29 +147,40 @@ function App({ router }) {
|
|
|
130
147
|
algorithm,
|
|
131
148
|
}}
|
|
132
149
|
>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
{/* Message, Notification and ConfirmModal render in the App.useApp()
|
|
151
|
+
holders here, above the Client's icon provider. */}
|
|
152
|
+
<IconProvider icons={rootConfig?.theme.icons ?? buildTheme.icons}>
|
|
153
|
+
<AntdApp>
|
|
154
|
+
<ThemeTokenResolver lowdefyRef={lowdefyRef}>
|
|
155
|
+
<ErrorBoundary fullPage onError={handleError}>
|
|
156
|
+
<Suspense
|
|
157
|
+
fallback={
|
|
158
|
+
<div
|
|
159
|
+
style={{
|
|
160
|
+
minHeight: '100vh',
|
|
161
|
+
background: 'var(--ant-color-bg-layout)',
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
}
|
|
165
|
+
>
|
|
166
|
+
<Auth user={config?.user}>
|
|
167
|
+
{(auth) => {
|
|
168
|
+
return (
|
|
169
|
+
<Routing
|
|
170
|
+
auth={auth}
|
|
171
|
+
lowdefy={lowdefyRef.current}
|
|
172
|
+
recording={config?.recording}
|
|
173
|
+
router={router}
|
|
174
|
+
/>
|
|
175
|
+
);
|
|
142
176
|
}}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
</Auth>
|
|
151
|
-
</Suspense>
|
|
152
|
-
</ErrorBoundary>
|
|
153
|
-
<ErrorBar errors={runtimeErrors} />
|
|
154
|
-
</ThemeTokenResolver>
|
|
155
|
-
</AntdApp>
|
|
177
|
+
</Auth>
|
|
178
|
+
</Suspense>
|
|
179
|
+
</ErrorBoundary>
|
|
180
|
+
<ErrorBar errors={runtimeErrors} />
|
|
181
|
+
</ThemeTokenResolver>
|
|
182
|
+
</AntdApp>
|
|
183
|
+
</IconProvider>
|
|
156
184
|
</XProvider>
|
|
157
185
|
</StyleProvider>
|
|
158
186
|
);
|
package/client/Inspector.jsx
CHANGED
|
@@ -26,11 +26,13 @@ import DevStreamContext from './DevStreamContext.js';
|
|
|
26
26
|
// stream per tab exhausted the browser's HTTP/1.1 connection pool once a few
|
|
27
27
|
// tabs of the same app were open, and every later fetch queued forever.
|
|
28
28
|
//
|
|
29
|
-
//
|
|
29
|
+
// Page tracking: routes/reload.js registers every connection as an
|
|
30
30
|
// inspectable tab (lib/docs/tabChannel.js) and announces the tab id on the
|
|
31
|
-
// stream. This component then posts { tabId, pageId }
|
|
32
|
-
// /api/dev-inspect/page whenever the
|
|
33
|
-
// view of "what
|
|
31
|
+
// stream. This component then posts { tabId, pageId, pathParams, instanceKey }
|
|
32
|
+
// to /api/dev-inspect/page whenever the page instance on screen changes, so the
|
|
33
|
+
// registry's view of "what instance is this tab on" stays current without
|
|
34
|
+
// reconnecting. A request names the instance to read (the dev server picks
|
|
35
|
+
// it); without one it reads the instance on screen.
|
|
34
36
|
//
|
|
35
37
|
// Never let a bad payload or a plugin's operator error crash the app this is
|
|
36
38
|
// piggybacking on — every handler is wrapped, and the component itself
|
|
@@ -55,23 +57,62 @@ function postResult({ basePath, requestId, result }) {
|
|
|
55
57
|
postJson({ basePath, path: '', body: { requestId, result } });
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
function postTabPage({ basePath, tabId,
|
|
59
|
-
postJson({
|
|
60
|
+
function postTabPage({ basePath, tabId, page }) {
|
|
61
|
+
postJson({
|
|
62
|
+
basePath,
|
|
63
|
+
path: '/page',
|
|
64
|
+
body: {
|
|
65
|
+
tabId,
|
|
66
|
+
pageId: page.pageId,
|
|
67
|
+
pathParams: page.pathParams,
|
|
68
|
+
instanceKey: page.instanceKey,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// `page "ticket"`, or `page "ticket" (tickets/s/1)` for an instance of a page with placeholders,
|
|
74
|
+
// whose instance key ends in the path its values build.
|
|
75
|
+
function describePage({ pageId, instanceKey }) {
|
|
76
|
+
const hashIndex = instanceKey.indexOf('#');
|
|
77
|
+
if (hashIndex === -1) {
|
|
78
|
+
return `page "${pageId}"`;
|
|
79
|
+
}
|
|
80
|
+
return `page "${pageId}" (${instanceKey.slice(hashIndex + 1)})`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function requestedPage({ data, shownPage }) {
|
|
84
|
+
if (type.isString(data.instanceKey)) {
|
|
85
|
+
return { pageId: data.pageId, pathParams: data.pathParams, instanceKey: data.instanceKey };
|
|
86
|
+
}
|
|
87
|
+
return shownPage;
|
|
60
88
|
}
|
|
61
89
|
|
|
62
|
-
function
|
|
63
|
-
|
|
90
|
+
function findContext({ lowdefy, page }) {
|
|
91
|
+
if (type.isNone(page)) {
|
|
92
|
+
return { error: 'No page has rendered in this tab yet.' };
|
|
93
|
+
}
|
|
94
|
+
const context = lowdefy?.contexts?.[page.instanceKey];
|
|
64
95
|
if (type.isNone(context)) {
|
|
65
|
-
return { error: `No live context for
|
|
96
|
+
return { error: `No live context for ${describePage(page)}.` };
|
|
97
|
+
}
|
|
98
|
+
return { context };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function buildSnapshot({ lowdefy, page }) {
|
|
102
|
+
const { context, error } = findContext({ lowdefy, page });
|
|
103
|
+
if (error) {
|
|
104
|
+
return { error };
|
|
66
105
|
}
|
|
67
106
|
return serializer.serializeToString({
|
|
68
|
-
pageId,
|
|
107
|
+
pageId: page.pageId,
|
|
108
|
+
pathParams: context.pathParams,
|
|
109
|
+
instanceKey: page.instanceKey,
|
|
69
110
|
state: context.state,
|
|
70
111
|
requests: context.requests,
|
|
71
112
|
eventLog: (context.eventLog ?? []).slice(-50),
|
|
72
113
|
global: lowdefy.lowdefyGlobal,
|
|
73
114
|
user: lowdefy.user,
|
|
74
|
-
input: lowdefy.inputs?.[
|
|
115
|
+
input: lowdefy.inputs?.[page.instanceKey],
|
|
75
116
|
urlQuery: window.location.search,
|
|
76
117
|
});
|
|
77
118
|
}
|
|
@@ -88,7 +129,7 @@ function buildSnapshot({ lowdefy, pageId }) {
|
|
|
88
129
|
// has finished mounting. Never lets a bad checkpoint or a missing context
|
|
89
130
|
// break the app — every step is try/catch, and failures just leave the app
|
|
90
131
|
// running unmodified.
|
|
91
|
-
async function bootstrapFromCheckpoint({ basePath,
|
|
132
|
+
async function bootstrapFromCheckpoint({ basePath, instanceKey, checkpointName, isCancelled }) {
|
|
92
133
|
try {
|
|
93
134
|
const response = await fetch(
|
|
94
135
|
`${basePath}/api/dev-inspect/checkpoint/${encodeURIComponent(checkpointName)}`
|
|
@@ -106,7 +147,7 @@ async function bootstrapFromCheckpoint({ basePath, pageId, checkpointName, isCan
|
|
|
106
147
|
const deadline = Date.now() + 5000;
|
|
107
148
|
let context;
|
|
108
149
|
while (!isCancelled() && Date.now() < deadline) {
|
|
109
|
-
context = window.lowdefy?.contexts?.[
|
|
150
|
+
context = window.lowdefy?.contexts?.[instanceKey];
|
|
110
151
|
if (context) {
|
|
111
152
|
break;
|
|
112
153
|
}
|
|
@@ -127,10 +168,10 @@ async function bootstrapFromCheckpoint({ basePath, pageId, checkpointName, isCan
|
|
|
127
168
|
}
|
|
128
169
|
}
|
|
129
170
|
|
|
130
|
-
function evalExpression({ lowdefy,
|
|
131
|
-
const context = lowdefy
|
|
132
|
-
if (
|
|
133
|
-
return { error
|
|
171
|
+
function evalExpression({ lowdefy, page, expression }) {
|
|
172
|
+
const { context, error } = findContext({ lowdefy, page });
|
|
173
|
+
if (error) {
|
|
174
|
+
return { error };
|
|
134
175
|
}
|
|
135
176
|
// Callers may pass the operator expression as a JSON-serializable object,
|
|
136
177
|
// or (since it travels as a JSON string end-to-end from an MCP tool
|
|
@@ -143,10 +184,10 @@ function evalExpression({ lowdefy, pageId, expression }) {
|
|
|
143
184
|
};
|
|
144
185
|
}
|
|
145
186
|
|
|
146
|
-
const Inspector = ({ basePath, lowdefy,
|
|
187
|
+
const Inspector = ({ basePath, lowdefy, page }) => {
|
|
147
188
|
const { source, tabId } = useContext(DevStreamContext);
|
|
148
|
-
const
|
|
149
|
-
|
|
189
|
+
const pageRef = useRef(page);
|
|
190
|
+
pageRef.current = page;
|
|
150
191
|
|
|
151
192
|
useEffect(() => {
|
|
152
193
|
if (type.isNone(source)) {
|
|
@@ -158,8 +199,10 @@ const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
|
158
199
|
try {
|
|
159
200
|
const data = JSON.parse(message.data);
|
|
160
201
|
requestId = data.requestId;
|
|
161
|
-
const
|
|
162
|
-
|
|
202
|
+
const result = buildSnapshot({
|
|
203
|
+
lowdefy,
|
|
204
|
+
page: requestedPage({ data, shownPage: pageRef.current }),
|
|
205
|
+
});
|
|
163
206
|
postResult({ basePath, requestId, result });
|
|
164
207
|
} catch (error) {
|
|
165
208
|
postResult({ basePath, requestId, result: { error: error.message } });
|
|
@@ -171,10 +214,9 @@ const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
|
171
214
|
try {
|
|
172
215
|
const data = JSON.parse(message.data);
|
|
173
216
|
requestId = data.requestId;
|
|
174
|
-
const targetPageId = data.pageId ?? pageIdRef.current;
|
|
175
217
|
const result = evalExpression({
|
|
176
218
|
lowdefy,
|
|
177
|
-
|
|
219
|
+
page: requestedPage({ data, shownPage: pageRef.current }),
|
|
178
220
|
expression: data.expression,
|
|
179
221
|
});
|
|
180
222
|
postResult({ basePath, requestId, result });
|
|
@@ -192,14 +234,15 @@ const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
|
192
234
|
}, [basePath, lowdefy, source]);
|
|
193
235
|
|
|
194
236
|
useEffect(() => {
|
|
195
|
-
if (type.isNone(tabId) || type.isNone(
|
|
237
|
+
if (type.isNone(tabId) || type.isNone(page)) {
|
|
196
238
|
return;
|
|
197
239
|
}
|
|
198
|
-
postTabPage({ basePath, tabId,
|
|
199
|
-
}, [basePath, tabId,
|
|
240
|
+
postTabPage({ basePath, tabId, page });
|
|
241
|
+
}, [basePath, tabId, page]);
|
|
200
242
|
|
|
243
|
+
const instanceKey = page?.instanceKey;
|
|
201
244
|
useEffect(() => {
|
|
202
|
-
if (type.isNone(
|
|
245
|
+
if (type.isNone(instanceKey)) {
|
|
203
246
|
return undefined;
|
|
204
247
|
}
|
|
205
248
|
const checkpointName = new URLSearchParams(window.location.search).get('_checkpoint');
|
|
@@ -210,7 +253,7 @@ const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
|
210
253
|
let cancelled = false;
|
|
211
254
|
bootstrapFromCheckpoint({
|
|
212
255
|
basePath,
|
|
213
|
-
|
|
256
|
+
instanceKey,
|
|
214
257
|
checkpointName,
|
|
215
258
|
isCancelled: () => cancelled,
|
|
216
259
|
});
|
|
@@ -218,7 +261,7 @@ const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
|
218
261
|
return () => {
|
|
219
262
|
cancelled = true;
|
|
220
263
|
};
|
|
221
|
-
}, [basePath,
|
|
264
|
+
}, [basePath, instanceKey]);
|
|
222
265
|
|
|
223
266
|
return null;
|
|
224
267
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
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 { useEffect } from 'react';
|
|
18
|
+
import { getTrace } from '@lowdefy/engine';
|
|
19
|
+
|
|
20
|
+
import collectVisibleBlockIds from '../lib/client/collectVisibleBlockIds.js';
|
|
21
|
+
import startJourneyObserver from './journeyObserver/startJourneyObserver.js';
|
|
22
|
+
|
|
23
|
+
// Dev-only: tells the journey runner which events completed and which blocks
|
|
24
|
+
// were visible in a journey's own pages (see journeyObserver/). It renders
|
|
25
|
+
// null, like Inspector, does nothing in a developer's tab, and never lets an
|
|
26
|
+
// error reach the app.
|
|
27
|
+
function JourneyObserver({ lowdefy }) {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
let stop = null;
|
|
30
|
+
try {
|
|
31
|
+
stop = startJourneyObserver({ window, lowdefy, getTrace, collectVisibleBlockIds });
|
|
32
|
+
} catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return () => {
|
|
36
|
+
try {
|
|
37
|
+
stop?.();
|
|
38
|
+
} catch {
|
|
39
|
+
// Best effort.
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}, [lowdefy]);
|
|
43
|
+
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default JourneyObserver;
|
package/client/Page.jsx
CHANGED
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import React, { useEffect, useRef } from 'react';
|
|
18
|
-
import { GenIcon } from 'react-icons/lib';
|
|
19
18
|
import Client from '@lowdefy/client';
|
|
19
|
+
import { pageInstanceKey } from '@lowdefy/helpers';
|
|
20
20
|
|
|
21
21
|
import BuildErrorPage from '../lib/client/BuildErrorPage.jsx';
|
|
22
22
|
import InstallingPluginsPage from '../lib/client/InstallingPluginsPage.jsx';
|
|
23
|
+
import RedirectingPage from '../lib/client/RedirectingPage.jsx';
|
|
23
24
|
import usePageConfig from '../lib/client/utils/usePageConfig.js';
|
|
24
25
|
|
|
25
26
|
const Page = ({
|
|
@@ -28,12 +29,18 @@ const Page = ({
|
|
|
28
29
|
config,
|
|
29
30
|
jsMap,
|
|
30
31
|
lowdefy,
|
|
31
|
-
|
|
32
|
+
onPageShown,
|
|
33
|
+
path,
|
|
32
34
|
resetContext,
|
|
33
35
|
router,
|
|
34
36
|
types,
|
|
35
37
|
}) => {
|
|
36
|
-
const { data
|
|
38
|
+
const { data } = usePageConfig(path, router.basePath, auth.user, lowdefy);
|
|
39
|
+
const pageConfig = data?.pageConfig;
|
|
40
|
+
// Past the config fetch (which suspends), this render shows the page the
|
|
41
|
+
// URL names, so a navigation Routing marked has landed. Set during render,
|
|
42
|
+
// like lowdefy.pageId (initLowdefyContext), so the two change together.
|
|
43
|
+
lowdefy._devNavigating = false;
|
|
37
44
|
|
|
38
45
|
// Push build warnings to ErrorBar via runtime error callback
|
|
39
46
|
const pushedWarningsRef = useRef(null);
|
|
@@ -46,37 +53,60 @@ const Page = ({
|
|
|
46
53
|
}
|
|
47
54
|
}, [pageConfig?._warnings, lowdefy]);
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
// Tells the in-page dev tools which page instance is on screen, from the fetched page.
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (pageConfig) {
|
|
59
|
+
onPageShown({
|
|
60
|
+
pageId: data.pageId,
|
|
61
|
+
pathParams: data.pathParams,
|
|
62
|
+
instanceKey: pageInstanceKey({
|
|
63
|
+
pageId: data.pageId,
|
|
64
|
+
path: pageConfig.path,
|
|
65
|
+
pathParams: data.pathParams,
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}, [pageConfig, data?.pageId, data?.pathParams, onPageShown]);
|
|
70
|
+
|
|
71
|
+
// Full load to the sign-in page so it can return here after sign-in — an
|
|
72
|
+
// effect, not a fetcher side effect, so the redirect re-fires if the same
|
|
73
|
+
// cached result renders again.
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (data?.authRedirect) {
|
|
76
|
+
window.location.assign(data.authRedirect);
|
|
77
|
+
}
|
|
78
|
+
}, [data?.authRedirect]);
|
|
79
|
+
|
|
80
|
+
if (!data) {
|
|
50
81
|
router.replace({ pathname: '/404' });
|
|
51
82
|
return '';
|
|
52
83
|
}
|
|
53
|
-
if (
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
source={pageConfig.source}
|
|
59
|
-
/>
|
|
60
|
-
);
|
|
84
|
+
if (data.authRedirect) {
|
|
85
|
+
return <RedirectingPage redirect={data.authRedirect} />;
|
|
86
|
+
}
|
|
87
|
+
if (data.buildError) {
|
|
88
|
+
return <BuildErrorPage errors={data.errors} message={data.message} source={data.source} />;
|
|
61
89
|
}
|
|
62
|
-
if (
|
|
63
|
-
return <InstallingPluginsPage packages={
|
|
90
|
+
if (data.installing) {
|
|
91
|
+
return <InstallingPluginsPage packages={data.packages} />;
|
|
64
92
|
}
|
|
65
93
|
|
|
66
94
|
// Merge dynamic JS entries fetched after JIT build with the static jsMap
|
|
67
95
|
const mergedJsMap = pageConfig._jsEntries ? { ...jsMap, ...pageConfig._jsEntries } : jsMap;
|
|
68
96
|
|
|
69
|
-
// Merge JIT-
|
|
70
|
-
// createIcon
|
|
71
|
-
// so mutating the original object makes
|
|
97
|
+
// Merge JIT-delivered icon data into the static icons map. Icons are data
|
|
98
|
+
// (IconData), and createIcon looks up Icons[name] on every render from the
|
|
99
|
+
// captured reference, so mutating the original object makes them available
|
|
100
|
+
// immediately.
|
|
72
101
|
if (pageConfig._dynamicIcons) {
|
|
73
|
-
|
|
74
|
-
if (!types.icons[name]) {
|
|
75
|
-
types.icons[name] = GenIcon(data);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
102
|
+
Object.assign(types.icons, pageConfig._dynamicIcons);
|
|
78
103
|
}
|
|
79
104
|
|
|
105
|
+
// The build this config was served under, for the recorder to stamp on each
|
|
106
|
+
// interaction. Set during render, like the icons above, so it is in place
|
|
107
|
+
// before any interaction on this config.
|
|
108
|
+
lowdefy._devBuildId = pageConfig._buildId ?? null;
|
|
109
|
+
|
|
80
110
|
return (
|
|
81
111
|
<Client
|
|
82
112
|
auth={auth}
|
|
@@ -87,6 +117,8 @@ const Page = ({
|
|
|
87
117
|
}}
|
|
88
118
|
jsMap={mergedJsMap}
|
|
89
119
|
lowdefy={lowdefy}
|
|
120
|
+
matchedPath={data.matchedPath}
|
|
121
|
+
pathParams={data.pathParams}
|
|
90
122
|
resetContext={resetContext}
|
|
91
123
|
router={router}
|
|
92
124
|
stage="dev"
|
|
@@ -0,0 +1,73 @@
|
|
|
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 { useContext, useEffect, useRef } from 'react';
|
|
18
|
+
import { getTrace } from '@lowdefy/engine';
|
|
19
|
+
|
|
20
|
+
import createRecorder from './recorder/createRecorder.js';
|
|
21
|
+
import DevStreamContext from './DevStreamContext.js';
|
|
22
|
+
|
|
23
|
+
// Dev-only journey recorder: records how the developer uses the app, locally,
|
|
24
|
+
// so an agent can turn what they tried into journeys (see recorder/). It
|
|
25
|
+
// renders null, like Inspector, and never lets an error reach the app.
|
|
26
|
+
//
|
|
27
|
+
// It opens no connection of its own: a second long-lived stream per tab once
|
|
28
|
+
// exhausted the browser's HTTP/1.1 connection pool (see DevStreamContext.js).
|
|
29
|
+
// It listens for `reload` on the tab's one shared stream and flushes there,
|
|
30
|
+
// only to send promptly: each record carries the build of the page config it
|
|
31
|
+
// was made on (lowdefy._devBuildId, set by Page.jsx).
|
|
32
|
+
// `path` is the path Page fetches, so a navigation starts a pageview; `page`
|
|
33
|
+
// is the page instance on screen, { pageId, pathParams, instanceKey }, as the
|
|
34
|
+
// fetched page names it, which completes it.
|
|
35
|
+
function Recorder({ basePath, lowdefy, page, path, recording }) {
|
|
36
|
+
const { source } = useContext(DevStreamContext);
|
|
37
|
+
const recorderRef = useRef(null);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
let recorder = null;
|
|
41
|
+
try {
|
|
42
|
+
recorder = createRecorder({ basePath, lowdefy, recording, window, getTrace });
|
|
43
|
+
} catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
if (recorder === null) return undefined;
|
|
47
|
+
recorderRef.current = recorder;
|
|
48
|
+
return () => {
|
|
49
|
+
recorderRef.current = null;
|
|
50
|
+
try {
|
|
51
|
+
recorder.stop();
|
|
52
|
+
} catch {
|
|
53
|
+
// Best effort.
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}, [recording?.enabled]);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
recorderRef.current?.pageview({ path });
|
|
60
|
+
}, [path, recording?.enabled]);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (page !== null) recorderRef.current?.pageShown(page);
|
|
64
|
+
}, [page?.instanceKey, recording?.enabled]);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
return recorderRef.current?.attachStream(source);
|
|
68
|
+
}, [source, recording?.enabled]);
|
|
69
|
+
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default Recorder;
|