@lowdefy/server-dev 0.0.0-experimental-20260720072521 → 0.0.0-experimental-20260720135014
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/.eslintrc.yaml +1 -0
- package/lib/build/app.js +1 -8
- package/lib/build/appMeta.js +1 -8
- package/lib/build/auth.js +1 -8
- package/lib/build/config.js +1 -8
- package/lib/build/i18n.js +1 -8
- package/lib/build/logger.js +1 -8
- package/lib/build/theme.js +1 -8
- package/lib/client/App.js +80 -0
- package/{client/Page.jsx → lib/client/Page.js} +5 -5
- package/{client/Reload.jsx → lib/client/Reload.js} +7 -5
- package/lib/client/auth/{Auth.jsx → Auth.js} +5 -12
- package/lib/client/auth/AuthConfigured.js +61 -0
- package/lib/client/auth/AuthNotConfigured.js +2 -22
- package/lib/client/setPageId.js +5 -6
- package/lib/client/utils/useMutateCache.js +1 -14
- package/lib/client/utils/usePageConfig.js +11 -31
- package/lib/server/apiWrapper.js +116 -0
- package/lib/server/auth/{getStrategies.js → getAuthOptions.js} +9 -14
- package/lib/server/auth/{getMockUser.js → getMockSession.js} +19 -10
- package/{src/routes/docs/checkpointsRevert.js → lib/server/auth/getServerSession.js} +13 -11
- package/lib/server/compileCss.js +39 -0
- package/lib/server/jitPageBuilder.js +11 -36
- package/lib/server/log/logRequest.js +3 -1
- package/manager/getContext.mjs +7 -3
- package/manager/processes/compileCss.mjs +54 -0
- package/manager/processes/initialBuild.mjs +2 -0
- package/manager/processes/installPlugins.mjs +11 -19
- package/manager/processes/lowdefyBuild.mjs +7 -29
- package/manager/processes/nextBuild.mjs +50 -0
- package/manager/processes/readDotEnv.mjs +1 -13
- package/manager/processes/shutdownServer.mjs +6 -6
- package/manager/processes/startServer.mjs +7 -8
- package/manager/processes/startWatchers.mjs +2 -2
- package/manager/run.mjs +0 -41
- package/manager/utils/createCustomPluginMessagesMap.mjs +1 -8
- package/manager/utils/createCustomPluginTypesMap.mjs +2 -3
- package/manager/utils/{getViteBin.mjs → getNextBin.mjs} +10 -7
- package/manager/utils/updatePageTailwindCss.mjs +1 -7
- package/manager/watchers/lowdefyBuildWatcher.mjs +1 -0
- package/manager/watchers/moduleBuildWatcher.mjs +1 -0
- package/manager/watchers/{serverArtifactWatcher.mjs → nextBuildWatcher.mjs} +22 -18
- package/next.config.js +25 -0
- package/package.json +47 -63
- package/package.original.json +55 -66
- package/{src/routes/devTools.js → pages/404.js} +2 -4
- package/{src/routes/docs/appMap.js → pages/[[...pageId]].js} +2 -6
- package/{client/App.jsx → pages/_app.js} +33 -21
- package/pages/_document.js +107 -0
- package/pages/api/agent/[...path].js +86 -0
- package/pages/api/auth/[...nextauth].js +48 -0
- package/pages/api/client-error.js +45 -0
- package/{src/routes/docs/buildStatus.js → pages/api/dev-tools.js} +4 -5
- package/{lib/docs/clientErrorStore.js → pages/api/endpoints/[...endpointId].js} +11 -15
- package/{src/lib/serveBuildJs.js → pages/api/icons/dynamic.js} +12 -8
- package/{src/routes/jsEnv.js → pages/api/js/[env].js} +20 -8
- package/pages/api/page/[...pageId].js +74 -0
- package/{src/routes → pages/api}/ping.js +2 -4
- package/pages/api/reload.js +53 -0
- package/pages/api/request/[...path].js +41 -0
- package/{src/routes → pages/api}/root.js +4 -4
- package/client/Inspector.jsx +0 -206
- package/client/Routing.jsx +0 -106
- package/client/feedback/FeedbackMount.jsx +0 -83
- package/client/feedback/FeedbackOverlay.jsx +0 -901
- package/client/feedback/captureTabScreenshot.js +0 -84
- package/client/feedback/copyToClipboard.js +0 -45
- package/client/feedback/drawAnnotationsSvg.js +0 -119
- package/client/feedback/elementInspect.js +0 -99
- package/client/feedback/feedbackStyles.js +0 -301
- package/client/feedback/pinResponsiveImages.js +0 -59
- package/client/feedback/sendFeedback.js +0 -39
- package/client/feedback/useFeedbackToggle.js +0 -70
- package/client/main.jsx +0 -42
- package/client/openInEditor/OpenInEditorListener.jsx +0 -261
- package/client/openInEditor/findBlockLocation.js +0 -51
- package/lib/client/auth/AuthConfigured.jsx +0 -155
- package/lib/docs/captureAnnotatedScreenshot.js +0 -88
- package/lib/docs/checkpointPaths.js +0 -91
- package/lib/docs/checkpointStore.js +0 -234
- package/lib/docs/checkpointToMocks.js +0 -65
- package/lib/docs/configCheckpoints.test.mjs +0 -156
- package/lib/docs/createConfigCheckpoint.js +0 -92
- package/lib/docs/createDocsMcpServer.js +0 -506
- package/lib/docs/createDocsMcpServer.test.mjs +0 -123
- package/lib/docs/devMockRegistry.js +0 -68
- package/lib/docs/docs.test.mjs +0 -448
- package/lib/docs/enrichFeedback.js +0 -71
- package/lib/docs/evalOperator.js +0 -39
- package/lib/docs/evalOperator.test.mjs +0 -112
- package/lib/docs/evalOperatorHeadless.js +0 -87
- package/lib/docs/evalOperatorHeadless.test.mjs +0 -72
- package/lib/docs/evalOperatorInTab.js +0 -48
- package/lib/docs/findConfig.js +0 -260
- package/lib/docs/formatFeedback.js +0 -121
- package/lib/docs/formatFeedback.test.mjs +0 -204
- package/lib/docs/getAppMap.js +0 -180
- package/lib/docs/getBrowser.js +0 -115
- package/lib/docs/getBuildStatus.js +0 -37
- package/lib/docs/getCoreDoc.js +0 -63
- package/lib/docs/getDocsManifest.js +0 -40
- package/lib/docs/getExamples.js +0 -58
- package/lib/docs/getOverview.js +0 -115
- package/lib/docs/getPageConfig.js +0 -53
- package/lib/docs/getPluginDoc.js +0 -55
- package/lib/docs/getSchema.js +0 -65
- package/lib/docs/inspectState.js +0 -41
- package/lib/docs/inspectState.test.mjs +0 -91
- package/lib/docs/inspectStateFromTab.js +0 -40
- package/lib/docs/inspectStateHeadless.js +0 -84
- package/lib/docs/inspectStateHeadless.test.mjs +0 -60
- package/lib/docs/isWriteRequestsAllowed.js +0 -50
- package/lib/docs/listConfigCheckpoints.js +0 -55
- package/lib/docs/listPlugins.js +0 -80
- package/lib/docs/listTypes.js +0 -105
- package/lib/docs/loadState.js +0 -139
- package/lib/docs/mapPageBuildErrors.js +0 -28
- package/lib/docs/normalizeTypeKind.js +0 -40
- package/lib/docs/readBuildArtifact.js +0 -35
- package/lib/docs/readPageArtifact.js +0 -26
- package/lib/docs/resolvePluginDir.js +0 -49
- package/lib/docs/revertConfigCheckpoint.js +0 -73
- package/lib/docs/runRequest.js +0 -141
- package/lib/docs/saveAnnotatedScreenshot.js +0 -43
- package/lib/docs/scaffoldPage.js +0 -75
- package/lib/docs/scaffoldPage.test.mjs +0 -97
- package/lib/docs/screenshotPage.js +0 -109
- package/lib/docs/screenshotPage.test.mjs +0 -59
- package/lib/docs/screenshotPageClip.test.mjs +0 -102
- package/lib/docs/searchDocs.js +0 -67
- package/lib/docs/setupTestFixtures.mjs +0 -335
- package/lib/docs/snapshotState.js +0 -59
- package/lib/docs/stateCheckpoints.test.mjs +0 -348
- package/lib/docs/tabAvailable.js +0 -28
- package/lib/docs/tabChannel.js +0 -119
- package/lib/docs/tabChannel.test.mjs +0 -130
- package/lib/server/auth/createSystemContext.js +0 -70
- package/lib/server/auth/getAuth.js +0 -46
- package/lib/server/auth/getHeadlessUser.js +0 -39
- package/lib/server/auth/headlessUser.js +0 -30
- package/lib/server/createLowdefyContext.js +0 -133
- package/lib/server/loadDynamicJsMap.js +0 -47
- package/manager/processes/lowdefyBuild.test.mjs +0 -102
- package/manager/utils/formatNoticeBox.mjs +0 -30
- package/manager/utils/writeBuildStatus.mjs +0 -39
- package/manager/utils/writeBuildStatus.test.mjs +0 -76
- package/postcss.config.cjs +0 -1
- package/src/app.js +0 -188
- package/src/html/renderDevPage.js +0 -86
- package/src/lib/getPathSegments.js +0 -25
- package/src/lib/safeScriptJson.js +0 -38
- package/src/middleware/apiContext.js +0 -32
- package/src/middleware/errorHandler.js +0 -55
- package/src/routes/agent.js +0 -64
- package/src/routes/auth.js +0 -43
- package/src/routes/clientError.js +0 -57
- package/src/routes/cron.js +0 -44
- package/src/routes/detached.js +0 -51
- package/src/routes/devInspect.js +0 -94
- package/src/routes/docs/checkpointsCreate.js +0 -28
- package/src/routes/docs/checkpointsList.js +0 -23
- package/src/routes/docs/content.js +0 -31
- package/src/routes/docs/evalOperator.js +0 -46
- package/src/routes/docs/examples.js +0 -33
- package/src/routes/docs/find.js +0 -30
- package/src/routes/docs/index.js +0 -23
- package/src/routes/docs/inspectState.js +0 -34
- package/src/routes/docs/loadState.js +0 -38
- package/src/routes/docs/mcp.js +0 -30
- package/src/routes/docs/pageConfig.js +0 -36
- package/src/routes/docs/pluginDoc.js +0 -33
- package/src/routes/docs/plugins.js +0 -23
- package/src/routes/docs/runRequest.js +0 -34
- package/src/routes/docs/schema.js +0 -37
- package/src/routes/docs/screenshot.js +0 -66
- package/src/routes/docs/search.js +0 -27
- package/src/routes/docs/snapshotState.js +0 -36
- package/src/routes/docs/stateCheckpointsList.js +0 -26
- package/src/routes/docs/types.js +0 -33
- package/src/routes/endpoints.js +0 -76
- package/src/routes/feedback.js +0 -110
- package/src/routes/feedback.test.mjs +0 -204
- package/src/routes/iconsDynamic.js +0 -25
- package/src/routes/jitPage.js +0 -99
- package/src/routes/reload.js +0 -81
- package/src/routes/request.js +0 -66
- package/src/routes/usage.js +0 -46
- package/src/routes/user.js +0 -27
- package/src/routes/websocket.js +0 -33
- package/src/websocket/devWebSocket.js +0 -78
- package/vite.config.js +0 -111
- /package/lib/client/{BuildErrorPage.jsx → BuildErrorPage.js} +0 -0
- /package/lib/client/{BuildingPage.jsx → BuildingPage.js} +0 -0
- /package/lib/client/{ErrorBar.jsx → ErrorBar.js} +0 -0
- /package/lib/client/{InstallingPluginsPage.jsx → InstallingPluginsPage.js} +0 -0
- /package/lib/client/{RestartingPage.jsx → RestartingPage.js} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
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 { callRequest } from '@lowdefy/api';
|
|
18
|
+
|
|
19
|
+
import apiWrapper from '../../../lib/server/apiWrapper.js';
|
|
20
|
+
|
|
21
|
+
async function handler({ context, req, res }) {
|
|
22
|
+
if (req.method !== 'POST') {
|
|
23
|
+
throw new Error('Only POST requests are supported.');
|
|
24
|
+
}
|
|
25
|
+
const segments = req.query.path;
|
|
26
|
+
if (!Array.isArray(segments) || segments.length < 2) {
|
|
27
|
+
res.status(400).json({ error: 'Invalid request path' });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const requestId = segments[segments.length - 1];
|
|
31
|
+
const pageId = segments.slice(0, -1).join('/');
|
|
32
|
+
const { actionId, blockId, payload } = req.body;
|
|
33
|
+
context.logger.info(
|
|
34
|
+
{ color: 'gray' },
|
|
35
|
+
`Request: ${pageId} · ${blockId} · ${actionId} → ${requestId}`
|
|
36
|
+
);
|
|
37
|
+
const response = await callRequest(context, { blockId, pageId, payload, requestId });
|
|
38
|
+
res.status(200).json(response);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default apiWrapper(handler);
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { getRootConfig } from '@lowdefy/api';
|
|
18
|
+
import apiWrapper from '../../lib/server/apiWrapper.js';
|
|
18
19
|
|
|
19
|
-
async function
|
|
20
|
-
const context = c.get('lowdefyContext');
|
|
20
|
+
async function handler({ context, res }) {
|
|
21
21
|
const rootConfig = await getRootConfig(context);
|
|
22
|
-
|
|
22
|
+
res.status(200).json(rootConfig);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export default
|
|
25
|
+
export default apiWrapper(handler);
|
package/client/Inspector.jsx
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
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, useRef } from 'react';
|
|
18
|
-
|
|
19
|
-
import { type, serializer } from '@lowdefy/helpers';
|
|
20
|
-
|
|
21
|
-
// Dev-only agent-state-xray channel — a sibling of Reload.jsx, but with its
|
|
22
|
-
// own /api/reload SSE connection (rather than reusing Reload's) so that
|
|
23
|
-
// connection can carry ?pageId=<pageId>. routes/reload.js only registers a
|
|
24
|
-
// connection as an inspectable tab (lib/docs/tabChannel.js) when that query
|
|
25
|
-
// param is present, which keeps Reload.jsx's plain reload/ping connection
|
|
26
|
-
// out of the tab registry entirely.
|
|
27
|
-
//
|
|
28
|
-
// pageId tracking: this effect depends on `pageId`, so React tears down and
|
|
29
|
-
// reopens the EventSource (a fresh connection, fresh tab id server-side)
|
|
30
|
-
// whenever the developer navigates to a different page — see the longer
|
|
31
|
-
// design note in src/routes/reload.js.
|
|
32
|
-
//
|
|
33
|
-
// Never let a bad payload or a plugin's operator error crash the app this is
|
|
34
|
-
// piggybacking on — every handler is wrapped, and the component itself
|
|
35
|
-
// always renders null.
|
|
36
|
-
function postResult({ basePath, requestId, result }) {
|
|
37
|
-
try {
|
|
38
|
-
fetch(`${basePath}/api/dev-inspect`, {
|
|
39
|
-
method: 'POST',
|
|
40
|
-
headers: { 'Content-Type': 'application/json' },
|
|
41
|
-
body: JSON.stringify({ requestId, result }),
|
|
42
|
-
}).catch(() => {
|
|
43
|
-
// Best-effort — a failed callback just leaves the agent's request to
|
|
44
|
-
// time out server-side.
|
|
45
|
-
});
|
|
46
|
-
} catch {
|
|
47
|
-
// JSON.stringify or fetch throwing synchronously — still best-effort.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function buildSnapshot({ lowdefy, pageId }) {
|
|
52
|
-
const context = lowdefy?.contexts?.[`page:${pageId}`];
|
|
53
|
-
if (type.isNone(context)) {
|
|
54
|
-
return { error: `No live context for page "${pageId}".` };
|
|
55
|
-
}
|
|
56
|
-
return serializer.serializeToString({
|
|
57
|
-
pageId,
|
|
58
|
-
state: context.state,
|
|
59
|
-
requests: context.requests,
|
|
60
|
-
eventLog: (context.eventLog ?? []).slice(-50),
|
|
61
|
-
global: lowdefy.lowdefyGlobal,
|
|
62
|
-
user: lowdefy.user,
|
|
63
|
-
input: lowdefy.inputs?.[`page:${pageId}`],
|
|
64
|
-
urlQuery: window.location.search,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Dev-only agent-state-xray: puts a human tester's real browser tab into a
|
|
69
|
-
// checkpoint's recorded state when it loads a page with `?_checkpoint=<name>`
|
|
70
|
-
// in the URL. Fetches the checkpoint's state part from
|
|
71
|
-
// GET <basePath>/api/dev-inspect/checkpoint/<name> (src/routes/devInspect.js
|
|
72
|
-
// — that fetch also loads the checkpoint's recorded requests into
|
|
73
|
-
// devMockRegistry server-side, so this tab's own requests replay recorded
|
|
74
|
-
// data), then injects state the same way e2e-utils' setState does:
|
|
75
|
-
// context._internal.State.set(...) + context._internal.update(). Polls
|
|
76
|
-
// briefly for the page context to exist since this can run before the page
|
|
77
|
-
// has finished mounting. Never lets a bad checkpoint or a missing context
|
|
78
|
-
// break the app — every step is try/catch, and failures just leave the app
|
|
79
|
-
// running unmodified.
|
|
80
|
-
async function bootstrapFromCheckpoint({ basePath, pageId, checkpointName, isCancelled }) {
|
|
81
|
-
try {
|
|
82
|
-
const response = await fetch(
|
|
83
|
-
`${basePath}/api/dev-inspect/checkpoint/${encodeURIComponent(checkpointName)}`
|
|
84
|
-
);
|
|
85
|
-
const body = await response.json();
|
|
86
|
-
if (!response.ok || body?.error) {
|
|
87
|
-
// eslint-disable-next-line no-console
|
|
88
|
-
console.error(
|
|
89
|
-
`Failed to load checkpoint "${checkpointName}": ${body?.error ?? response.statusText}`
|
|
90
|
-
);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const payload = serializer.deserialize(body);
|
|
94
|
-
|
|
95
|
-
const deadline = Date.now() + 5000;
|
|
96
|
-
let context;
|
|
97
|
-
while (!isCancelled() && Date.now() < deadline) {
|
|
98
|
-
context = window.lowdefy?.contexts?.[`page:${pageId}`];
|
|
99
|
-
if (context) {
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
// eslint-disable-next-line no-await-in-loop
|
|
103
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
104
|
-
}
|
|
105
|
-
if (isCancelled() || type.isNone(context)) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
Object.entries(payload.state ?? {}).forEach(([key, value]) => {
|
|
110
|
-
context._internal.State.set(key, value);
|
|
111
|
-
});
|
|
112
|
-
context._internal.update();
|
|
113
|
-
} catch (error) {
|
|
114
|
-
// eslint-disable-next-line no-console
|
|
115
|
-
console.error(`Failed to load checkpoint "${checkpointName}":`, error);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function evalExpression({ lowdefy, pageId, expression }) {
|
|
120
|
-
const context = lowdefy?.contexts?.[`page:${pageId}`];
|
|
121
|
-
if (type.isNone(context)) {
|
|
122
|
-
return { error: `No live context for page "${pageId}".` };
|
|
123
|
-
}
|
|
124
|
-
// Callers may pass the operator expression as a JSON-serializable object,
|
|
125
|
-
// or (since it travels as a JSON string end-to-end from an MCP tool
|
|
126
|
-
// argument) as a JSON string that needs one more parse.
|
|
127
|
-
const input = type.isString(expression) ? JSON.parse(expression) : expression;
|
|
128
|
-
const { output, errors } = context._internal.parser.parse({ input, location: 'agent_eval' });
|
|
129
|
-
return {
|
|
130
|
-
value: serializer.serializeToString(output),
|
|
131
|
-
errors: errors.map((error) => error.message),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const Inspector = ({ basePath, lowdefy, pageId }) => {
|
|
136
|
-
const pageIdRef = useRef(pageId);
|
|
137
|
-
pageIdRef.current = pageId;
|
|
138
|
-
|
|
139
|
-
useEffect(() => {
|
|
140
|
-
if (type.isNone(pageId)) {
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const sse = new EventSource(`${basePath}/api/reload?pageId=${encodeURIComponent(pageId)}`);
|
|
145
|
-
|
|
146
|
-
sse.addEventListener('inspect-request', (message) => {
|
|
147
|
-
let requestId;
|
|
148
|
-
try {
|
|
149
|
-
const data = JSON.parse(message.data);
|
|
150
|
-
requestId = data.requestId;
|
|
151
|
-
const targetPageId = data.pageId ?? pageIdRef.current;
|
|
152
|
-
const result = buildSnapshot({ lowdefy, pageId: targetPageId });
|
|
153
|
-
postResult({ basePath, requestId, result });
|
|
154
|
-
} catch (error) {
|
|
155
|
-
postResult({ basePath, requestId, result: { error: error.message } });
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
sse.addEventListener('eval-request', (message) => {
|
|
160
|
-
let requestId;
|
|
161
|
-
try {
|
|
162
|
-
const data = JSON.parse(message.data);
|
|
163
|
-
requestId = data.requestId;
|
|
164
|
-
const targetPageId = data.pageId ?? pageIdRef.current;
|
|
165
|
-
const result = evalExpression({
|
|
166
|
-
lowdefy,
|
|
167
|
-
pageId: targetPageId,
|
|
168
|
-
expression: data.expression,
|
|
169
|
-
});
|
|
170
|
-
postResult({ basePath, requestId, result });
|
|
171
|
-
} catch (error) {
|
|
172
|
-
postResult({ basePath, requestId, result: { error: error.message } });
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
return () => {
|
|
177
|
-
sse.close();
|
|
178
|
-
};
|
|
179
|
-
}, [basePath, lowdefy, pageId]);
|
|
180
|
-
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
if (type.isNone(pageId)) {
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
const checkpointName = new URLSearchParams(window.location.search).get('_checkpoint');
|
|
186
|
-
if (type.isNone(checkpointName)) {
|
|
187
|
-
return undefined;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
let cancelled = false;
|
|
191
|
-
bootstrapFromCheckpoint({
|
|
192
|
-
basePath,
|
|
193
|
-
pageId,
|
|
194
|
-
checkpointName,
|
|
195
|
-
isCancelled: () => cancelled,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
return () => {
|
|
199
|
-
cancelled = true;
|
|
200
|
-
};
|
|
201
|
-
}, [basePath, pageId]);
|
|
202
|
-
|
|
203
|
-
return null;
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
export default Inspector;
|
package/client/Routing.jsx
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
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 React, { Suspense, useEffect, useState } from 'react';
|
|
18
|
-
|
|
19
|
-
import Head from '@lowdefy/client/adapters/Head.js';
|
|
20
|
-
import createLinkComponent from '@lowdefy/client/adapters/Link.js';
|
|
21
|
-
|
|
22
|
-
import BuildingPage from '../lib/client/BuildingPage.jsx';
|
|
23
|
-
import FeedbackMount from './feedback/FeedbackMount.jsx';
|
|
24
|
-
import Inspector from './Inspector.jsx';
|
|
25
|
-
import OpenInEditorListener from './openInEditor/OpenInEditorListener.jsx';
|
|
26
|
-
import Reload from './Reload.jsx';
|
|
27
|
-
import Page from './Page.jsx';
|
|
28
|
-
import setPageId from '../lib/client/setPageId.js';
|
|
29
|
-
import { bumpNavVersion, getReloadVersion } from '../lib/client/utils/useMutateCache.js';
|
|
30
|
-
import useRootConfig from '../lib/client/utils/useRootConfig.js';
|
|
31
|
-
|
|
32
|
-
import actions from '../build/plugins/actions.js';
|
|
33
|
-
import blockMetas from '../build/plugins/blockMetas.json';
|
|
34
|
-
import blocks from '../build/plugins/blocks.js';
|
|
35
|
-
import icons from '../build/plugins/icons.js';
|
|
36
|
-
import operators from '../build/plugins/operators/client.js';
|
|
37
|
-
import staticJsMap from '../build/plugins/operators/clientJsMap.js';
|
|
38
|
-
|
|
39
|
-
// Replaces lib/client/App.js — page resolution driven by the custom router
|
|
40
|
-
// instead of next/router, everything else preserved.
|
|
41
|
-
function Routing({ auth, lowdefy, router }) {
|
|
42
|
-
const { data: rootConfig } = useRootConfig(router.basePath);
|
|
43
|
-
const [location, setLocation] = useState(() => router.getLocation());
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
return router.subscribe((location) => {
|
|
47
|
-
// Dynamic pages re-resolve per navigation — bump before setLocation so
|
|
48
|
-
// the page config SWR key changes with the navigation. The router
|
|
49
|
-
// notifies with a fresh location object per event, so same-URL
|
|
50
|
-
// navigations already produce a state change.
|
|
51
|
-
bumpNavVersion();
|
|
52
|
-
setLocation(location);
|
|
53
|
-
});
|
|
54
|
-
}, [router]);
|
|
55
|
-
|
|
56
|
-
const [Link] = useState(() => createLinkComponent({ router }));
|
|
57
|
-
|
|
58
|
-
if (rootConfig?.theme) {
|
|
59
|
-
lowdefy.theme = rootConfig.theme;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const { redirect, pageId } = setPageId(location, rootConfig);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
if (redirect) {
|
|
65
|
-
router.replace({ pathname: `/${pageId}` });
|
|
66
|
-
}
|
|
67
|
-
}, [redirect, pageId, router]);
|
|
68
|
-
if (redirect) {
|
|
69
|
-
return '';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<>
|
|
74
|
-
<Inspector basePath={router.basePath} lowdefy={lowdefy} pageId={pageId} />
|
|
75
|
-
<FeedbackMount basePath={router.basePath} lowdefy={lowdefy} pageId={pageId} />
|
|
76
|
-
<OpenInEditorListener basePath={router.basePath} pageId={pageId} />
|
|
77
|
-
<Reload basePath={router.basePath} lowdefy={lowdefy}>
|
|
78
|
-
{(resetContext) => (
|
|
79
|
-
<Suspense key={`${pageId}_${getReloadVersion()}`} fallback={<BuildingPage />}>
|
|
80
|
-
<Page
|
|
81
|
-
auth={auth}
|
|
82
|
-
Components={{ Head, Link }}
|
|
83
|
-
config={{
|
|
84
|
-
rootConfig,
|
|
85
|
-
}}
|
|
86
|
-
jsMap={staticJsMap}
|
|
87
|
-
lowdefy={lowdefy}
|
|
88
|
-
pageId={pageId}
|
|
89
|
-
resetContext={resetContext}
|
|
90
|
-
router={router}
|
|
91
|
-
types={{
|
|
92
|
-
actions,
|
|
93
|
-
blockMetas,
|
|
94
|
-
blocks,
|
|
95
|
-
icons,
|
|
96
|
-
operators,
|
|
97
|
-
}}
|
|
98
|
-
/>
|
|
99
|
-
</Suspense>
|
|
100
|
-
)}
|
|
101
|
-
</Reload>
|
|
102
|
-
</>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export default Routing;
|
|
@@ -1,83 +0,0 @@
|
|
|
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 React, { Suspense, useEffect, useState } from 'react';
|
|
18
|
-
|
|
19
|
-
import useFeedbackToggle from './useFeedbackToggle.js';
|
|
20
|
-
|
|
21
|
-
// Logged once per page load, not once per mount — React StrictMode / HMR can
|
|
22
|
-
// remount this component without a real reload.
|
|
23
|
-
let bannerLogged = false;
|
|
24
|
-
|
|
25
|
-
function logBannerOnce() {
|
|
26
|
-
if (bannerLogged) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
bannerLogged = true;
|
|
30
|
-
try {
|
|
31
|
-
// eslint-disable-next-line no-console
|
|
32
|
-
console.info(
|
|
33
|
-
'%cLowdefy Annotate%c — press Cmd/Ctrl+/ to point, draw, and copy annotations for your coding agent.',
|
|
34
|
-
'color: #4f9cf9; font-weight: bold;',
|
|
35
|
-
'color: inherit;'
|
|
36
|
-
);
|
|
37
|
-
// eslint-disable-next-line no-console
|
|
38
|
-
console.info(
|
|
39
|
-
'%cLowdefy Open Code%c — Cmd/Ctrl+click any element to open its yaml in VS Code.',
|
|
40
|
-
'color: #4f9cf9; font-weight: bold;',
|
|
41
|
-
'color: inherit;'
|
|
42
|
-
);
|
|
43
|
-
} catch {
|
|
44
|
-
// Never let a console-styling quirk break the app.
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Code-split: the overlay (state machine, drawing SVG, review tray) only
|
|
49
|
-
// loads once the developer actually opts in.
|
|
50
|
-
const LazyOverlay = React.lazy(() => import('./FeedbackOverlay.jsx'));
|
|
51
|
-
|
|
52
|
-
// Dev-only, always mounted alongside Inspector.jsx. Mirrors its resilience
|
|
53
|
-
// contract — nothing here may ever throw into the app it's riding along
|
|
54
|
-
// with. Stays inert until the developer presses Cmd/Ctrl+/, at which point
|
|
55
|
-
// the overlay mounts.
|
|
56
|
-
function FeedbackMount({ basePath, lowdefy, pageId }) {
|
|
57
|
-
const [active, setActive] = useState(false);
|
|
58
|
-
|
|
59
|
-
useFeedbackToggle({
|
|
60
|
-
onToggle: () => setActive((current) => !current),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
logBannerOnce();
|
|
65
|
-
}, []);
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<>
|
|
69
|
-
{active && (
|
|
70
|
-
<Suspense fallback={null}>
|
|
71
|
-
<LazyOverlay
|
|
72
|
-
basePath={basePath}
|
|
73
|
-
lowdefy={lowdefy}
|
|
74
|
-
pageId={pageId}
|
|
75
|
-
onClose={() => setActive(false)}
|
|
76
|
-
/>
|
|
77
|
-
</Suspense>
|
|
78
|
-
)}
|
|
79
|
-
</>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export default FeedbackMount;
|