@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,127 @@
|
|
|
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 { jest } from '@jest/globals';
|
|
18
|
+
|
|
19
|
+
// searchIcons reads the dev build's iconAliases.json and customTypesMap.json,
|
|
20
|
+
// which only exist in a built server directory, and loads installed icon set
|
|
21
|
+
// plugins through the build's loader. Lucide's names are real.
|
|
22
|
+
const mockReadBuildArtifact = jest.fn();
|
|
23
|
+
jest.unstable_mockModule('./readBuildArtifact.js', () => ({
|
|
24
|
+
default: mockReadBuildArtifact,
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
const buildDev = await import('@lowdefy/build/dev');
|
|
28
|
+
const mockLoadIconSets = jest.fn();
|
|
29
|
+
jest.unstable_mockModule('@lowdefy/build/dev', () => ({
|
|
30
|
+
...buildDev,
|
|
31
|
+
loadIconSets: mockLoadIconSets,
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const { default: searchIcons } = await import('./searchIcons.js');
|
|
35
|
+
|
|
36
|
+
function layer(names) {
|
|
37
|
+
return { names: new Set(names) };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mockArtifacts({ aliases = null, iconSets = {} } = {}) {
|
|
41
|
+
mockReadBuildArtifact.mockImplementation(({ name }) => {
|
|
42
|
+
if (name === 'iconAliases.json') return aliases;
|
|
43
|
+
if (name === 'customTypesMap.json') return { iconSets };
|
|
44
|
+
return null;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
mockReadBuildArtifact.mockReset();
|
|
50
|
+
mockLoadIconSets.mockReset();
|
|
51
|
+
mockLoadIconSets.mockResolvedValue({ lucide: [layer([])] });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('searchIcons lists matching semantic names, then canonical Lucide names, then aliases', async () => {
|
|
55
|
+
mockArtifacts({ aliases: { delete: 'Trash', edit: 'Pencil' } });
|
|
56
|
+
const result = await searchIcons({ query: 'trash' });
|
|
57
|
+
expect(result.semantic).toEqual([{ name: 'delete', icon: 'Trash' }]);
|
|
58
|
+
expect(result.icons[0]).toBe('Trash');
|
|
59
|
+
expect(result.icons).toContain('Trash2');
|
|
60
|
+
// Trash2 is a canonical name in Lucide 1.x; aliases come after every canonical name.
|
|
61
|
+
const { canonical } = buildDev.getLucideIconNames();
|
|
62
|
+
const firstAlias = result.icons.findIndex((name) => !canonical.includes(name));
|
|
63
|
+
if (firstAlias !== -1) {
|
|
64
|
+
expect(result.icons.slice(firstAlias).every((name) => !canonical.includes(name))).toBe(true);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('searchIcons ranks canonical names before Lucide alias names', async () => {
|
|
69
|
+
mockArtifacts();
|
|
70
|
+
const result = await searchIcons({ query: 'house', limit: 100 });
|
|
71
|
+
expect(result.icons).toContain('House');
|
|
72
|
+
const home = await searchIcons({ query: 'home', limit: 100 });
|
|
73
|
+
// Home is an alias of House.
|
|
74
|
+
expect(home.icons).toContain('Home');
|
|
75
|
+
expect(home.icons.indexOf('Home')).toBeGreaterThan(home.icons.indexOf('HousePlus'));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('searchIcons includes theme aliases from the build', async () => {
|
|
79
|
+
mockArtifacts({ aliases: { invoice: 'Receipt' } });
|
|
80
|
+
const result = await searchIcons({ query: 'invoice' });
|
|
81
|
+
expect(result.semantic).toEqual([{ name: 'invoice', icon: 'Receipt' }]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('searchIcons falls back to the built-in names before the first build', async () => {
|
|
85
|
+
mockArtifacts();
|
|
86
|
+
const result = await searchIcons({ query: 'external link' });
|
|
87
|
+
expect(result.semantic).toEqual([{ name: 'external-link', icon: 'ExternalLink' }]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('searchIcons lists installed set names qualified, after Lucide names', async () => {
|
|
91
|
+
const iconSets = { tabler: [{ package: '@acme/icons-tabler', version: '1.0.0' }] };
|
|
92
|
+
mockArtifacts({ iconSets });
|
|
93
|
+
mockLoadIconSets.mockResolvedValue({
|
|
94
|
+
lucide: [layer(['Pencil']), layer(['PencilInvoice'])],
|
|
95
|
+
tabler: [layer(['PencilBolt', 'Other'])],
|
|
96
|
+
});
|
|
97
|
+
const result = await searchIcons({ query: 'pencil', limit: 100 });
|
|
98
|
+
expect(result.icons[0]).toBe('Pencil');
|
|
99
|
+
// An icon a plugin adds to lucide is listed unqualified; other sets qualified.
|
|
100
|
+
expect(result.icons.slice(-2)).toEqual(['PencilInvoice', 'tabler:PencilBolt']);
|
|
101
|
+
expect(mockLoadIconSets).toHaveBeenCalledWith({
|
|
102
|
+
context: { directories: { server: process.cwd() }, typesMap: { iconSets } },
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('searchIcons requires every query word to match', async () => {
|
|
107
|
+
mockArtifacts();
|
|
108
|
+
const result = await searchIcons({ query: 'arrow right circle', limit: 50 });
|
|
109
|
+
expect(result.icons.length).toBeGreaterThan(0);
|
|
110
|
+
result.icons.forEach((name) => {
|
|
111
|
+
const lower = name.toLowerCase();
|
|
112
|
+
expect(lower).toContain('arrow');
|
|
113
|
+
expect(lower).toContain('right');
|
|
114
|
+
expect(lower).toContain('circle');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('searchIcons caps icon names at the limit', async () => {
|
|
119
|
+
mockArtifacts();
|
|
120
|
+
expect((await searchIcons({ query: 'user', limit: 5 })).icons).toHaveLength(5);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('searchIcons throws without a query', async () => {
|
|
124
|
+
await expect(searchIcons({ query: ' ' })).rejects.toThrow(
|
|
125
|
+
'searchIcons requires a "query" string.'
|
|
126
|
+
);
|
|
127
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
// What the lowdefy_run_journey tool returns of a run's `exercised` block.
|
|
20
|
+
// The full block lists every request, endpoint, event and rendered block, which
|
|
21
|
+
// is hundreds of lines for a short journey, so the tool returns a count of each
|
|
22
|
+
// by default. `selection` true returns the block whole, false leaves it out.
|
|
23
|
+
// Only the tool's response is trimmed: the REST route, and so `lowdefy test`'s
|
|
24
|
+
// exercised.json that the journey lints read, always carries the whole block.
|
|
25
|
+
function selectExercised({ exercised, selection }) {
|
|
26
|
+
if (selection === true || type.isNone(exercised)) {
|
|
27
|
+
return { exercised };
|
|
28
|
+
}
|
|
29
|
+
if (selection === false) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
const counts = {};
|
|
33
|
+
Object.entries(exercised).forEach(([key, value]) => {
|
|
34
|
+
if (type.isArray(value)) counts[key] = value.length;
|
|
35
|
+
});
|
|
36
|
+
return { exercised: { counts, note: 'Pass exercised: true for the full block.' } };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default selectExercised;
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { get, type } from '@lowdefy/helpers';
|
|
18
|
+
|
|
19
|
+
// The final state is returned whole when it is small. A page holding request
|
|
20
|
+
// results or long lists can hold hundreds of KB, more than an agent's context
|
|
21
|
+
// should take on every journey, so above this it is summarised instead.
|
|
22
|
+
const DEFAULT_STATE_LIMIT = 10_000;
|
|
23
|
+
|
|
24
|
+
function summariseState({ state, characters }) {
|
|
25
|
+
const keys = Object.fromEntries(
|
|
26
|
+
Object.entries(state)
|
|
27
|
+
.map(([key, value]) => [key, (JSON.stringify(value) ?? '').length])
|
|
28
|
+
.sort(([, a], [, b]) => b - a)
|
|
29
|
+
);
|
|
30
|
+
return {
|
|
31
|
+
characters,
|
|
32
|
+
keys,
|
|
33
|
+
note: `The final state is ${characters} characters, over the ${DEFAULT_STATE_LIMIT} returned by default. keys lists each top-level key with its size. Pass state: ["path", ...] for the paths you need, or state: true for all of it.`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Picks what the journey result carries of the final page state:
|
|
38
|
+
// false nothing
|
|
39
|
+
// true the whole state
|
|
40
|
+
// [path, ...] { [path]: value } for each path, null where it is undefined
|
|
41
|
+
// undefined the whole state when it is at most DEFAULT_STATE_LIMIT
|
|
42
|
+
// characters of JSON, otherwise `stateOmitted`, a summary of
|
|
43
|
+
// its size and top-level keys
|
|
44
|
+
// A state that could not be read ({ error }) is returned as is, since the
|
|
45
|
+
// error is what the caller needs to see.
|
|
46
|
+
function selectFinalState({ state, selection }) {
|
|
47
|
+
if (selection === false) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
if (selection === true || !type.isObject(state) || !type.isUndefined(state.error)) {
|
|
51
|
+
return { state };
|
|
52
|
+
}
|
|
53
|
+
if (type.isArray(selection)) {
|
|
54
|
+
return {
|
|
55
|
+
state: Object.fromEntries(selection.map((path) => [path, get(state, path) ?? null])),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const characters = JSON.stringify(state).length;
|
|
59
|
+
if (characters <= DEFAULT_STATE_LIMIT) {
|
|
60
|
+
return { state };
|
|
61
|
+
}
|
|
62
|
+
return { stateOmitted: summariseState({ state, characters }) };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { DEFAULT_STATE_LIMIT };
|
|
66
|
+
export default selectFinalState;
|
|
@@ -0,0 +1,51 @@
|
|
|
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 selectFinalState, { DEFAULT_STATE_LIMIT } from './selectFinalState.js';
|
|
18
|
+
|
|
19
|
+
test('selectFinalState returns a small state whole by default', () => {
|
|
20
|
+
expect(selectFinalState({ state: { a: 1 } })).toEqual({ state: { a: 1 } });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('selectFinalState summarises a state over the limit, largest key first', () => {
|
|
24
|
+
const state = { small: 1, large: 'x'.repeat(DEFAULT_STATE_LIMIT) };
|
|
25
|
+
const { state: returned, stateOmitted } = selectFinalState({ state });
|
|
26
|
+
expect(returned).toBeUndefined();
|
|
27
|
+
expect(stateOmitted.characters).toEqual(JSON.stringify(state).length);
|
|
28
|
+
expect(Object.entries(stateOmitted.keys)).toEqual([
|
|
29
|
+
['large', DEFAULT_STATE_LIMIT + 2],
|
|
30
|
+
['small', 1],
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('selectFinalState returns the paths asked for, null where undefined', () => {
|
|
35
|
+
const state = { form: { name: 'Ada', tags: [] }, flag: false };
|
|
36
|
+
expect(selectFinalState({ state, selection: ['form.name', 'flag', 'form.missing'] })).toEqual({
|
|
37
|
+
state: { 'form.name': 'Ada', flag: false, 'form.missing': null },
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('selectFinalState returns nothing for false and everything for true', () => {
|
|
42
|
+
const state = { large: 'x'.repeat(DEFAULT_STATE_LIMIT * 2) };
|
|
43
|
+
expect(selectFinalState({ state, selection: false })).toEqual({});
|
|
44
|
+
expect(selectFinalState({ state, selection: true })).toEqual({ state });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('selectFinalState passes a state read error through whatever was selected', () => {
|
|
48
|
+
const state = { error: 'Could not read final state: Target closed' };
|
|
49
|
+
expect(selectFinalState({ state, selection: ['a'] })).toEqual({ state });
|
|
50
|
+
expect(selectFinalState({ state })).toEqual({ state });
|
|
51
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
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 { publish } from './devEventBus.js';
|
|
18
|
+
import getBuildId from './getBuildId.js';
|
|
19
|
+
import isRunErrorEntry from './isRunErrorEntry.js';
|
|
20
|
+
import { recordRunError } from './runErrorBuffers.js';
|
|
21
|
+
|
|
22
|
+
// Module-level ring buffer of recent server-side errors (request, endpoint, MCP
|
|
23
|
+
// and agent tool failures) — feeds the getBuildStatus feedback endpoint so
|
|
24
|
+
// agents can see server errors, with their config source, without tailing
|
|
25
|
+
// server logs. Deliberately in-memory only: entries are lost on server
|
|
26
|
+
// restart, which is fine since this is a live-session debugging aid.
|
|
27
|
+
const MAX_ENTRIES = 50;
|
|
28
|
+
|
|
29
|
+
const entries = [];
|
|
30
|
+
|
|
31
|
+
// Each entry is stamped with the build it happened under (see getBuildId).
|
|
32
|
+
// An entry a journey run caused goes to that run's own
|
|
33
|
+
// buffer only (see runErrorBuffers), or is dropped when the run has ended:
|
|
34
|
+
// kept out of this ring and the event bus, it never reaches build-status or
|
|
35
|
+
// an agent's event stream, and a run that trips many errors cannot evict the
|
|
36
|
+
// developer's own. The run reports its errors in its own result.
|
|
37
|
+
function push(entry) {
|
|
38
|
+
const stamped = { ...entry, buildId: getBuildId() };
|
|
39
|
+
if (isRunErrorEntry(stamped)) {
|
|
40
|
+
recordRunError({ ...stamped, store: 'server' });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
entries.push(stamped);
|
|
44
|
+
if (entries.length > MAX_ENTRIES) {
|
|
45
|
+
entries.shift();
|
|
46
|
+
}
|
|
47
|
+
publish({ type: 'server_error', ...stamped });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function list() {
|
|
51
|
+
return [...entries];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default { push, list };
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
import { jest } from '@jest/globals';
|
|
17
|
+
|
|
18
|
+
const mockPublish = jest.fn();
|
|
19
|
+
jest.unstable_mockModule('./devEventBus.js', () => ({
|
|
20
|
+
publish: mockPublish,
|
|
21
|
+
}));
|
|
22
|
+
jest.unstable_mockModule('./getBuildId.js', () => ({
|
|
23
|
+
default: () => '2026-01-01T00:00:00.000Z',
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
const { default: serverErrorStore } = await import('./serverErrorStore.js');
|
|
27
|
+
|
|
28
|
+
const buildId = '2026-01-01T00:00:00.000Z';
|
|
29
|
+
|
|
30
|
+
test('serverErrorStore push adds an entry stamped with the current build, list returns it, and it is published as a server_error event', () => {
|
|
31
|
+
serverErrorStore.push({ message: 'first' });
|
|
32
|
+
expect(serverErrorStore.list()).toEqual([{ message: 'first', buildId }]);
|
|
33
|
+
expect(mockPublish).toHaveBeenCalledWith({ type: 'server_error', message: 'first', buildId });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('serverErrorStore list returns a copy that does not alias the store', () => {
|
|
37
|
+
const entries = serverErrorStore.list();
|
|
38
|
+
entries.push({ message: 'not stored' });
|
|
39
|
+
expect(serverErrorStore.list()).toEqual([{ message: 'first', buildId }]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('serverErrorStore caps at 50 entries and drops the oldest', () => {
|
|
43
|
+
for (let i = 0; i < 60; i++) {
|
|
44
|
+
serverErrorStore.push({ index: i });
|
|
45
|
+
}
|
|
46
|
+
const entries = serverErrorStore.list();
|
|
47
|
+
expect(entries.length).toEqual(50);
|
|
48
|
+
expect(entries[0].index).toEqual(10);
|
|
49
|
+
expect(entries[49].index).toEqual(59);
|
|
50
|
+
});
|
|
@@ -33,10 +33,15 @@ function setupTestFixtures() {
|
|
|
33
33
|
|
|
34
34
|
// lib/build/config.js reads this at import time (screenshotPage → basePath).
|
|
35
35
|
write('build/config.json', {});
|
|
36
|
+
write('build/routes.json', [{ pageId: 'home', path: 'home' }]);
|
|
36
37
|
|
|
37
38
|
write('build/plugins/availableTypes.json', {
|
|
38
39
|
actions: {
|
|
39
|
-
SetState: {
|
|
40
|
+
SetState: {
|
|
41
|
+
package: '@lowdefy/actions-core',
|
|
42
|
+
originalTypeName: 'SetState',
|
|
43
|
+
version: '5.0.0',
|
|
44
|
+
},
|
|
40
45
|
},
|
|
41
46
|
agents: {},
|
|
42
47
|
auth: { adapters: {}, callbacks: {}, events: {}, providers: {} },
|
|
@@ -58,7 +63,11 @@ function setupTestFixtures() {
|
|
|
58
63
|
},
|
|
59
64
|
server: {
|
|
60
65
|
_get: { package: '@lowdefy/operators-js', originalTypeName: '_get', version: '5.0.0' },
|
|
61
|
-
_secret: {
|
|
66
|
+
_secret: {
|
|
67
|
+
package: '@lowdefy/operators-js',
|
|
68
|
+
originalTypeName: '_secret',
|
|
69
|
+
version: '5.0.0',
|
|
70
|
+
},
|
|
62
71
|
},
|
|
63
72
|
},
|
|
64
73
|
requests: {
|
|
@@ -105,23 +114,52 @@ function setupTestFixtures() {
|
|
|
105
114
|
TestBlock: { type: 'object', properties: {} },
|
|
106
115
|
});
|
|
107
116
|
write('build/plugins/blockMetas.json', {
|
|
108
|
-
Button: { category: 'display' },
|
|
109
|
-
TestBlock: {
|
|
117
|
+
Button: { category: 'display', hazards: [] },
|
|
118
|
+
TestBlock: {
|
|
119
|
+
category: 'input',
|
|
120
|
+
valueType: 'string',
|
|
121
|
+
hazards: [
|
|
122
|
+
{ id: 'test-block-hazard', message: 'TestBlock does something surprising.', see: null },
|
|
123
|
+
// Same id as a framework hazard — getHazards must de-duplicate, keeping
|
|
124
|
+
// the plugin's own wording.
|
|
125
|
+
{
|
|
126
|
+
id: 'visible-false-prunes-state',
|
|
127
|
+
message: 'Plugin wording for visible: false.',
|
|
128
|
+
see: null,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
110
132
|
});
|
|
111
133
|
write('build/plugins/actionSchemas.json', { SetState: { type: 'object' } });
|
|
112
134
|
write('build/plugins/operatorSchemas.json', { _get: { params: { type: 'object' } } });
|
|
135
|
+
write('build/plugins/operatorMetas.json', {
|
|
136
|
+
_get: {
|
|
137
|
+
hazards: [
|
|
138
|
+
{ id: 'get-fixture-hazard', message: '_get fixture hazard.', see: 'operators/_get' },
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
});
|
|
113
142
|
write('build/plugins/connectionSchemas.json', {
|
|
114
143
|
AxiosHttp: { schema: { type: 'object' }, requests: ['AxiosHttp'] },
|
|
115
144
|
});
|
|
116
145
|
write('build/plugins/requestSchemas.json', {
|
|
117
146
|
AxiosHttp: { schema: { type: 'object' }, meta: { checkRead: false, checkWrite: false } },
|
|
118
147
|
ReadOnlyRequest: { schema: { type: 'object' }, meta: { checkRead: true, checkWrite: false } },
|
|
119
|
-
WriteRequest: {
|
|
148
|
+
WriteRequest: {
|
|
149
|
+
schema: { type: 'object' },
|
|
150
|
+
meta: {
|
|
151
|
+
checkRead: true,
|
|
152
|
+
checkWrite: true,
|
|
153
|
+
hazards: [{ id: 'write-request-hazard', message: 'Writes are final.', see: null }],
|
|
154
|
+
},
|
|
155
|
+
},
|
|
120
156
|
// No "meta" at all — some custom plugins don't declare it; treated as unknown.
|
|
121
157
|
UnknownMetaRequest: { schema: { type: 'object' } },
|
|
122
158
|
});
|
|
123
159
|
write('build/customTypesMap.json', {
|
|
124
|
-
blocks: {
|
|
160
|
+
blocks: {
|
|
161
|
+
TestBlock: { package: 'test-plugin', originalTypeName: 'TestBlock', version: '1.0.0' },
|
|
162
|
+
},
|
|
125
163
|
});
|
|
126
164
|
write('build/installedPluginPackages.json', [
|
|
127
165
|
'@lowdefy/blocks-antd',
|
|
@@ -139,7 +177,7 @@ function setupTestFixtures() {
|
|
|
139
177
|
);
|
|
140
178
|
|
|
141
179
|
// Feedback-loop fixtures — build status, and a JIT-built page's registry,
|
|
142
|
-
//
|
|
180
|
+
// key map and ref map entries (see packages/build/src/build/addKeys.js for
|
|
143
181
|
// the key path format: `[index:id]` / `[index:id:Type]`).
|
|
144
182
|
write('build/buildStatus.json', {
|
|
145
183
|
status: 'ok',
|
|
@@ -155,12 +193,12 @@ function setupTestFixtures() {
|
|
|
155
193
|
unbuilt: { pageId: 'unbuilt', auth: null, refId: 'ref-unbuilt', refPath: 'pages/unbuilt.yaml' },
|
|
156
194
|
});
|
|
157
195
|
|
|
158
|
-
// Mirrors the real dev
|
|
159
|
-
// config (`root.pages[N:id]` page stubs only), while each JIT
|
|
160
|
-
// runs addKeys on the page object itself
|
|
161
|
-
// `root.blocks[...]` with no page
|
|
162
|
-
// built page, distinguishable only via
|
|
163
|
-
// reference a parent id that is never written
|
|
196
|
+
// Mirrors the real dev key map shape: the skeleton build keys the whole
|
|
197
|
+
// config (`root.pages[N:id]` page stubs only) in keyMap.json, while each JIT
|
|
198
|
+
// page build runs addKeys on the page object itself and writes its keys to a
|
|
199
|
+
// jitMaps/ file — so page CONTENT keys are `root.blocks[...]` with no page
|
|
200
|
+
// segment, one `root`-keyed subtree per built page, distinguishable only via
|
|
201
|
+
// the ~k_parent chain. Tree roots reference a parent id that is never written.
|
|
164
202
|
write('build/keyMap.json', {
|
|
165
203
|
'key-root': { key: 'root', '~k_parent': 'key-root-parent' },
|
|
166
204
|
'key-pages': { key: 'root.pages', '~k_parent': 'key-root', '~r': 'ref-home' },
|
|
@@ -176,32 +214,6 @@ function setupTestFixtures() {
|
|
|
176
214
|
'~r': 'ref-other',
|
|
177
215
|
'~l': 1,
|
|
178
216
|
},
|
|
179
|
-
// JIT subtree for page "home".
|
|
180
|
-
'key-home': { key: 'root', '~k_parent': 'key-home-jit-parent', '~r': 'ref-home', '~l': 1 },
|
|
181
|
-
'key-button': {
|
|
182
|
-
key: 'root.blocks[2:my_button:Button]',
|
|
183
|
-
'~k_parent': 'key-home',
|
|
184
|
-
'~r': 'ref-home',
|
|
185
|
-
'~l': 5,
|
|
186
|
-
},
|
|
187
|
-
// List item block — config ids inside lists carry the `$` placeholder;
|
|
188
|
-
// runtime block ids have array indices applied (`my_list.0.item_title`).
|
|
189
|
-
'key-list-item': {
|
|
190
|
-
key: 'root.blocks[3:my_list:List].blocks[0:my_list.$.item_title:Title]',
|
|
191
|
-
'~k_parent': 'key-home',
|
|
192
|
-
'~r': 'ref-home',
|
|
193
|
-
'~l': 9,
|
|
194
|
-
},
|
|
195
|
-
// JIT subtree for page "other" — holds a block id that also exists on
|
|
196
|
-
// home, with an IDENTICAL key shape. findConfig must scope pageId scans
|
|
197
|
-
// via the ~k_parent chain, not the key path.
|
|
198
|
-
'key-other': { key: 'root', '~k_parent': 'key-other-jit-parent', '~r': 'ref-other', '~l': 1 },
|
|
199
|
-
'key-other-button': {
|
|
200
|
-
key: 'root.blocks[0:my_button:Button]',
|
|
201
|
-
'~k_parent': 'key-other',
|
|
202
|
-
'~r': 'ref-other',
|
|
203
|
-
'~l': 4,
|
|
204
|
-
},
|
|
205
217
|
// Skeleton-built page (like the default 404) — content is keyed inside
|
|
206
218
|
// the global config tree with the page segment inline, and chains to the
|
|
207
219
|
// shared config root rather than a page-specific one.
|
|
@@ -219,6 +231,63 @@ function setupTestFixtures() {
|
|
|
219
231
|
},
|
|
220
232
|
});
|
|
221
233
|
|
|
234
|
+
// JIT subtree for page "home".
|
|
235
|
+
write('build/jitMaps/abc123-1-1.json', {
|
|
236
|
+
keyMap: {
|
|
237
|
+
'key-home': { key: 'root', '~k_parent': 'key-home-jit-parent', '~r': 'ref-home', '~l': 1 },
|
|
238
|
+
'key-button': {
|
|
239
|
+
key: 'root.blocks[2:my_button:Button]',
|
|
240
|
+
'~k_parent': 'key-home',
|
|
241
|
+
'~r': 'ref-home',
|
|
242
|
+
'~l': 5,
|
|
243
|
+
},
|
|
244
|
+
// List item block — config ids inside lists carry the `$` placeholder;
|
|
245
|
+
// runtime block ids have array indices applied (`my_list.0.item_title`).
|
|
246
|
+
'key-list-item': {
|
|
247
|
+
key: 'root.blocks[3:my_list:List].blocks[0:my_list.$.item_title:Title]',
|
|
248
|
+
'~k_parent': 'key-home',
|
|
249
|
+
'~r': 'ref-home',
|
|
250
|
+
'~l': 9,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
refMap: {},
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// JIT subtree for page "other" — holds a block id that also exists on
|
|
257
|
+
// home, with an IDENTICAL key shape. findConfig must scope pageId scans
|
|
258
|
+
// via the ~k_parent chain, not the key path.
|
|
259
|
+
write('build/jitMaps/abc123-1-2.json', {
|
|
260
|
+
keyMap: {
|
|
261
|
+
'key-other': {
|
|
262
|
+
key: 'root',
|
|
263
|
+
'~k_parent': 'key-other-jit-parent',
|
|
264
|
+
'~r': 'ref-other',
|
|
265
|
+
'~l': 1,
|
|
266
|
+
},
|
|
267
|
+
'key-other-button': {
|
|
268
|
+
key: 'root.blocks[0:my_button:Button]',
|
|
269
|
+
'~k_parent': 'key-other',
|
|
270
|
+
'~r': 'ref-other',
|
|
271
|
+
'~l': 4,
|
|
272
|
+
},
|
|
273
|
+
// Requests over a tenant-walled and a shared connection — findConfig
|
|
274
|
+
// resolves connectionId from the per-request artifact for hazards.
|
|
275
|
+
'key-other-req-tenant': {
|
|
276
|
+
key: 'root.requests[0:req-tenant:WriteRequest]',
|
|
277
|
+
'~k_parent': 'key-other',
|
|
278
|
+
'~r': 'ref-other',
|
|
279
|
+
'~l': 12,
|
|
280
|
+
},
|
|
281
|
+
'key-other-req-shared': {
|
|
282
|
+
key: 'root.requests[1:req-shared:WriteRequest]',
|
|
283
|
+
'~k_parent': 'key-other',
|
|
284
|
+
'~r': 'ref-other',
|
|
285
|
+
'~l': 18,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
refMap: {},
|
|
289
|
+
});
|
|
290
|
+
|
|
222
291
|
write('build/refMap.json', {
|
|
223
292
|
'ref-home': { parent: null, path: 'pages/home.yaml' },
|
|
224
293
|
'ref-other': { parent: null, path: 'pages/other.yaml' },
|
|
@@ -227,6 +296,9 @@ function setupTestFixtures() {
|
|
|
227
296
|
|
|
228
297
|
write('build/pages/home.json', {
|
|
229
298
|
pageId: 'home',
|
|
299
|
+
// The skeleton build keys the page's auth, chaining to the global root —
|
|
300
|
+
// a real artifact carries this before any JIT-keyed block.
|
|
301
|
+
auth: { public: true, '~k': 'key-home-stub' },
|
|
230
302
|
blocks: [
|
|
231
303
|
{ id: 'my_button', type: 'Button', '~k': 'key-button' },
|
|
232
304
|
{
|
|
@@ -285,6 +357,28 @@ function setupTestFixtures() {
|
|
|
285
357
|
properties: {},
|
|
286
358
|
});
|
|
287
359
|
|
|
360
|
+
write('build/pages/other/requests/req-tenant.json', {
|
|
361
|
+
id: 'request:other:req-tenant',
|
|
362
|
+
requestId: 'req-tenant',
|
|
363
|
+
pageId: 'other',
|
|
364
|
+
connectionId: 'tenant_db',
|
|
365
|
+
type: 'WriteRequest',
|
|
366
|
+
payload: {},
|
|
367
|
+
properties: {},
|
|
368
|
+
});
|
|
369
|
+
write('build/pages/other/requests/req-shared.json', {
|
|
370
|
+
id: 'request:other:req-shared',
|
|
371
|
+
requestId: 'req-shared',
|
|
372
|
+
pageId: 'other',
|
|
373
|
+
connectionId: 'shared_db',
|
|
374
|
+
type: 'WriteRequest',
|
|
375
|
+
payload: {},
|
|
376
|
+
properties: {},
|
|
377
|
+
});
|
|
378
|
+
// Index of walled connections (packages/build/src/build/full/writeConnections.js)
|
|
379
|
+
// — shared connections are never listed here.
|
|
380
|
+
write('build/tenantConnections.json', [{ connectionId: 'tenant_db', type: 'MongoDBCollection' }]);
|
|
381
|
+
|
|
288
382
|
write('build/connectionIds.json', ['axios']);
|
|
289
383
|
write('build/connections/axios.json', {
|
|
290
384
|
id: 'connection:axios',
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
// The name the journey runner's selector engine is registered under
|
|
18
|
+
// (registerShownTextEngine.js).
|
|
19
|
+
const SHOWN_TEXT_ENGINE = 'lowdefy-shown-text';
|
|
20
|
+
|
|
21
|
+
// The selector for a `containing` target. The body is a JSON string, so `>>` or
|
|
22
|
+
// quotes in the text never split the selector.
|
|
23
|
+
function shownTextSelector(text) {
|
|
24
|
+
return `${SHOWN_TEXT_ENGINE}=${JSON.stringify(text)}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { SHOWN_TEXT_ENGINE };
|
|
28
|
+
export default shownTextSelector;
|