@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
|
@@ -1,70 +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 path from 'node:path';
|
|
18
|
-
import { createSystemContext as buildSystemContext } from '@lowdefy/api';
|
|
19
|
-
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
|
20
|
-
import { v4 as uuid } from 'uuid';
|
|
21
|
-
|
|
22
|
-
import agents from '../../../build/plugins/agents.js';
|
|
23
|
-
import appMeta from '../../build/appMeta.js';
|
|
24
|
-
import config from '../../build/config.js';
|
|
25
|
-
import connections from '../../../build/plugins/connections.js';
|
|
26
|
-
import createHandleError from '../log/createHandleError.js';
|
|
27
|
-
import createLogger from '../log/createLogger.js';
|
|
28
|
-
import fileCache from '../fileCache.js';
|
|
29
|
-
import i18nConfig from '../../build/i18n.js';
|
|
30
|
-
import loadDynamicJsMap from '../loadDynamicJsMap.js';
|
|
31
|
-
import notifications from '../../../build/plugins/notifications.js';
|
|
32
|
-
import operators from '../../../build/plugins/operators/server.js';
|
|
33
|
-
import steps from '../../../build/plugins/steps.js';
|
|
34
|
-
import websockets from '../../../build/plugins/websockets.js';
|
|
35
|
-
|
|
36
|
-
const secrets = getSecretsFromEnv();
|
|
37
|
-
|
|
38
|
-
// Builds a fresh system context per auth hook fire - the trusted internal
|
|
39
|
-
// caller the BetterAuth engine uses to invoke hook endpoints. All fields are
|
|
40
|
-
// startup singletons except the per-fire rid, logger, handleError, the
|
|
41
|
-
// dynamic jsMap re-read (JIT rebuilds rewrite serverJsMap.js), and auth -
|
|
42
|
-
// auth is threaded in by the caller (createHookDispatch) rather than
|
|
43
|
-
// imported directly, since it comes from the same BetterAuth construction
|
|
44
|
-
// that this factory is a dependency of (see createHookDispatch.js).
|
|
45
|
-
function createSystemContext({ auth } = {}) {
|
|
46
|
-
const rid = uuid();
|
|
47
|
-
const buildDirectory = path.join(process.cwd(), 'build');
|
|
48
|
-
return buildSystemContext({
|
|
49
|
-
rid,
|
|
50
|
-
agents,
|
|
51
|
-
appMeta,
|
|
52
|
-
auth,
|
|
53
|
-
buildDirectory,
|
|
54
|
-
config,
|
|
55
|
-
configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
|
|
56
|
-
connections,
|
|
57
|
-
createHandleError,
|
|
58
|
-
fileCache,
|
|
59
|
-
i18n: i18nConfig,
|
|
60
|
-
jsMap: loadDynamicJsMap(buildDirectory),
|
|
61
|
-
logger: createLogger({ rid }),
|
|
62
|
-
notifications,
|
|
63
|
-
operators,
|
|
64
|
-
secrets,
|
|
65
|
-
steps,
|
|
66
|
-
websockets,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export default createSystemContext;
|
|
@@ -1,46 +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 { getBetterAuth } from '@lowdefy/api';
|
|
18
|
-
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
|
19
|
-
|
|
20
|
-
import adapters from '../../../build/plugins/auth/adapters.js';
|
|
21
|
-
import appMeta from '../../build/appMeta.js';
|
|
22
|
-
import authJson from '../../build/auth.js';
|
|
23
|
-
import createSystemContext from './createSystemContext.js';
|
|
24
|
-
import lowdefyConfig from '../../build/config.js';
|
|
25
|
-
import providers from '../../../build/plugins/auth/providers.js';
|
|
26
|
-
|
|
27
|
-
// Returns the BetterAuth instance (memoized in @lowdefy/api), or null when
|
|
28
|
-
// auth is not configured. dev: true relaxes cookies for plain-http localhost
|
|
29
|
-
// and derives a per-app cookie prefix so parallel dev apps do not collide.
|
|
30
|
-
function getAuth({ logger }) {
|
|
31
|
-
if (authJson.configured !== true) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
return getBetterAuth({
|
|
35
|
-
appMeta,
|
|
36
|
-
authJson,
|
|
37
|
-
config: lowdefyConfig,
|
|
38
|
-
createSystemContext,
|
|
39
|
-
dev: true,
|
|
40
|
-
logger,
|
|
41
|
-
plugins: { adapters, providers },
|
|
42
|
-
secrets: getSecretsFromEnv(),
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export default getAuth;
|
|
@@ -1,39 +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 { HEADLESS_USER_COOKIE } from './headlessUser.js';
|
|
18
|
-
|
|
19
|
-
// Mirrors the e2e user-injection pattern (server-e2e/lib/server/auth/getUser.js):
|
|
20
|
-
// the headless renderer sets a base64-JSON user cookie on its own browser
|
|
21
|
-
// context, so its /api/* fetches carry a pre-resolved caller while the
|
|
22
|
-
// developer's real browser (no cookie) is unaffected. Returns the raw decoded
|
|
23
|
-
// user, or null on miss - the caller floors the shape via normalizeInjectedCaller.
|
|
24
|
-
function getHeadlessUser(c) {
|
|
25
|
-
const cookieHeader = c.req.header('cookie') ?? '';
|
|
26
|
-
const match = cookieHeader.match(new RegExp(`${HEADLESS_USER_COOKIE}=([^;]+)`));
|
|
27
|
-
if (!match) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const decoded = Buffer.from(decodeURIComponent(match[1]), 'base64').toString();
|
|
33
|
-
return JSON.parse(decoded);
|
|
34
|
-
} catch {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default getHeadlessUser;
|
|
@@ -1,30 +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
|
-
// Shared between the headless renderer (getBrowser.js, which sets the cookie on
|
|
18
|
-
// its browser context) and the dev caller resolver (getHeadlessUser.js, which
|
|
19
|
-
// decodes it) so the cookie name and injected user shape live in one place.
|
|
20
|
-
const HEADLESS_USER_COOKIE = 'lowdefy_headless_user';
|
|
21
|
-
|
|
22
|
-
// BetterAuth's session user carries `id`, never `sub`. attributes is floored to
|
|
23
|
-
// {} by normalizeInjectedCaller at injection, so it is not spelled out here.
|
|
24
|
-
const headlessUser = {
|
|
25
|
-
id: 'lowdefy-headless',
|
|
26
|
-
name: 'Lowdefy Headless',
|
|
27
|
-
roles: [],
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export { HEADLESS_USER_COOKIE, headlessUser };
|
|
@@ -1,133 +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 path from 'node:path';
|
|
18
|
-
import {
|
|
19
|
-
createApiContext,
|
|
20
|
-
normalizeInjectedCaller,
|
|
21
|
-
resolveAuthentication,
|
|
22
|
-
resolvePinnedOrganization,
|
|
23
|
-
} from '@lowdefy/api';
|
|
24
|
-
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
|
25
|
-
import { v4 as uuid } from 'uuid';
|
|
26
|
-
|
|
27
|
-
import agents from '../../build/plugins/agents.js';
|
|
28
|
-
import appMeta from '../build/appMeta.js';
|
|
29
|
-
import config from '../build/config.js';
|
|
30
|
-
import connections from '../../build/plugins/connections.js';
|
|
31
|
-
import createHandleError from './log/createHandleError.js';
|
|
32
|
-
import createLogger from './log/createLogger.js';
|
|
33
|
-
import fileCache from './fileCache.js';
|
|
34
|
-
import getAuth from './auth/getAuth.js';
|
|
35
|
-
import getHeadlessUser from './auth/getHeadlessUser.js';
|
|
36
|
-
import getMockUser from './auth/getMockUser.js';
|
|
37
|
-
import getStrategies from './auth/getStrategies.js';
|
|
38
|
-
import i18nConfig from '../build/i18n.js';
|
|
39
|
-
import loadDynamicJsMap from './loadDynamicJsMap.js';
|
|
40
|
-
import logRequest from './log/logRequest.js';
|
|
41
|
-
import notifications, {
|
|
42
|
-
interpolateProperties,
|
|
43
|
-
renderEmail,
|
|
44
|
-
} from '../../build/plugins/notifications.js';
|
|
45
|
-
import operators from '../../build/plugins/operators/server.js';
|
|
46
|
-
import steps from '../../build/plugins/steps.js';
|
|
47
|
-
import websockets from '../../build/plugins/websockets.js';
|
|
48
|
-
|
|
49
|
-
const secrets = getSecretsFromEnv();
|
|
50
|
-
|
|
51
|
-
// Builds the per-request lowdefy API context (connections, secrets,
|
|
52
|
-
// operators, logger, resolved user, etc.). Factored out of the /api/*
|
|
53
|
-
// middleware (src/middleware/apiContext.js) so run_request
|
|
54
|
-
// (lib/docs/runRequest.js) can build an identical context outside the Hono
|
|
55
|
-
// middleware chain, to call callRequest directly for agent-driven request
|
|
56
|
-
// execution.
|
|
57
|
-
async function createLowdefyContext({ c }) {
|
|
58
|
-
const buildDirectory = path.join(process.cwd(), 'build');
|
|
59
|
-
const jsMap = loadDynamicJsMap(buildDirectory);
|
|
60
|
-
|
|
61
|
-
const rid = uuid();
|
|
62
|
-
const context = {
|
|
63
|
-
rid,
|
|
64
|
-
agents,
|
|
65
|
-
appMeta,
|
|
66
|
-
buildDirectory,
|
|
67
|
-
configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
|
|
68
|
-
config,
|
|
69
|
-
connections,
|
|
70
|
-
fileCache,
|
|
71
|
-
headers: c.req.header(),
|
|
72
|
-
// The deployment's own origin — detached endpoint calls loop back
|
|
73
|
-
// through it so the target runs in its own function invocation.
|
|
74
|
-
origin: new URL(c.req.url).origin,
|
|
75
|
-
i18n: i18nConfig,
|
|
76
|
-
interpolateProperties,
|
|
77
|
-
jsMap,
|
|
78
|
-
logger: createLogger({ rid }),
|
|
79
|
-
notifications,
|
|
80
|
-
operators,
|
|
81
|
-
renderEmail,
|
|
82
|
-
req: {
|
|
83
|
-
url: c.req.path,
|
|
84
|
-
method: c.req.method,
|
|
85
|
-
hostname: c.req.header('host'),
|
|
86
|
-
},
|
|
87
|
-
secrets,
|
|
88
|
-
steps,
|
|
89
|
-
websockets,
|
|
90
|
-
};
|
|
91
|
-
context.handleError = createHandleError({ context });
|
|
92
|
-
const mockUser = getMockUser();
|
|
93
|
-
const headlessUser = getHeadlessUser(c);
|
|
94
|
-
if (mockUser) {
|
|
95
|
-
// The mock user is a pre-resolved caller - it substitutes for the
|
|
96
|
-
// whole resolveAuthentication step and its roles are authoritative.
|
|
97
|
-
// No auth engine runs while dev.mockUser is active (see src/app.js),
|
|
98
|
-
// so mock mode never touches the auth database. normalizeInjectedCaller
|
|
99
|
-
// floors it to the resolved-caller shape.
|
|
100
|
-
context.auth = null;
|
|
101
|
-
context.user = normalizeInjectedCaller(mockUser);
|
|
102
|
-
} else if (headlessUser) {
|
|
103
|
-
// The headless renderer (docs/MCP screenshot and state tools) injects a
|
|
104
|
-
// user cookie on its own browser context (getBrowser.js), so its /api/*
|
|
105
|
-
// fetches carry a pre-resolved caller and auth-protected pages render.
|
|
106
|
-
// The developer's real browser has no cookie and resolves through the
|
|
107
|
-
// auth engine below, so it is unaffected.
|
|
108
|
-
context.auth = null;
|
|
109
|
-
context.user = normalizeInjectedCaller(headlessUser);
|
|
110
|
-
} else {
|
|
111
|
-
// Hoisted once per request - resolveAuthentication also needs it, and
|
|
112
|
-
// getBetterAuth memoizes the instance, but this keeps the auth engine
|
|
113
|
-
// construction to a single call site per request.
|
|
114
|
-
context.auth = getAuth({ logger: context.logger });
|
|
115
|
-
// The engine is constructed lazily on the first request, which would
|
|
116
|
-
// otherwise race the startup pinned-org ensure - await the memoized
|
|
117
|
-
// resolve so createApiContext reads a retained binding.
|
|
118
|
-
await resolvePinnedOrganization({ auth: context.auth, logger: context.logger });
|
|
119
|
-
if (!c.req.path.includes('/api/auth')) {
|
|
120
|
-
// resolveAuthentication is the single writer of context.user.
|
|
121
|
-
await resolveAuthentication(context, {
|
|
122
|
-
auth: context.auth,
|
|
123
|
-
headers: c.req.raw.headers,
|
|
124
|
-
strategies: getStrategies({ logger: context.logger }),
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
createApiContext(context);
|
|
129
|
-
logRequest({ context });
|
|
130
|
-
return context;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export default createLowdefyContext;
|
|
@@ -1,47 +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 fs from 'node:fs';
|
|
18
|
-
import path from 'node:path';
|
|
19
|
-
|
|
20
|
-
import staticJsMap from '../../build/plugins/operators/serverJsMap.js';
|
|
21
|
-
|
|
22
|
-
// Dynamic JS map loading for JIT-built pages — the build rewrites
|
|
23
|
-
// serverJsMap.js when a JIT page discovers new _js operators.
|
|
24
|
-
let cachedJsMapMtime = null;
|
|
25
|
-
let cachedJsMap = staticJsMap;
|
|
26
|
-
|
|
27
|
-
function loadDynamicJsMap(buildDirectory) {
|
|
28
|
-
const jsMapPath = path.join(buildDirectory, 'plugins', 'operators', 'serverJsMap.js');
|
|
29
|
-
try {
|
|
30
|
-
const stat = fs.statSync(jsMapPath);
|
|
31
|
-
if (cachedJsMapMtime && stat.mtimeMs === cachedJsMapMtime) {
|
|
32
|
-
return cachedJsMap;
|
|
33
|
-
}
|
|
34
|
-
cachedJsMapMtime = stat.mtimeMs;
|
|
35
|
-
// For server-side, we can read and eval the JS file
|
|
36
|
-
const content = fs.readFileSync(jsMapPath, 'utf8');
|
|
37
|
-
const fn = new Function('exports', content.replace('export default', 'exports.default ='));
|
|
38
|
-
const exports = {};
|
|
39
|
-
fn(exports);
|
|
40
|
-
cachedJsMap = { ...staticJsMap, ...(exports.default ?? {}) };
|
|
41
|
-
return cachedJsMap;
|
|
42
|
-
} catch {
|
|
43
|
-
return cachedJsMap;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export default loadDynamicJsMap;
|
|
@@ -1,102 +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 { jest } from '@jest/globals';
|
|
18
|
-
|
|
19
|
-
const mockShallowBuild = jest.fn();
|
|
20
|
-
const mockSerializeBuildException = jest.fn((exception) => ({ message: exception.message }));
|
|
21
|
-
const mockWriteBuildStatus = jest.fn();
|
|
22
|
-
const mockCreateCustomPluginTypesMap = jest.fn().mockResolvedValue({});
|
|
23
|
-
const mockCreateCustomPluginMessagesMap = jest.fn().mockResolvedValue({});
|
|
24
|
-
|
|
25
|
-
jest.unstable_mockModule('@lowdefy/build/dev', () => ({
|
|
26
|
-
shallowBuild: mockShallowBuild,
|
|
27
|
-
serializeBuildException: mockSerializeBuildException,
|
|
28
|
-
}));
|
|
29
|
-
jest.unstable_mockModule('../utils/writeBuildStatus.mjs', () => ({
|
|
30
|
-
default: mockWriteBuildStatus,
|
|
31
|
-
}));
|
|
32
|
-
jest.unstable_mockModule('../utils/createCustomPluginTypesMap.mjs', () => ({
|
|
33
|
-
default: mockCreateCustomPluginTypesMap,
|
|
34
|
-
}));
|
|
35
|
-
jest.unstable_mockModule('../utils/createCustomPluginMessagesMap.mjs', () => ({
|
|
36
|
-
default: mockCreateCustomPluginMessagesMap,
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
const { default: lowdefyBuild } = await import('./lowdefyBuild.mjs');
|
|
40
|
-
|
|
41
|
-
function createContext() {
|
|
42
|
-
return {
|
|
43
|
-
directories: { build: '/app/build' },
|
|
44
|
-
logger: { info: jest.fn() },
|
|
45
|
-
options: { refResolver: undefined },
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
test('lowdefyBuild writes an ok buildStatus.json after a successful build', async () => {
|
|
50
|
-
const context = createContext();
|
|
51
|
-
const warning = { message: 'Deprecated feature used' };
|
|
52
|
-
mockShallowBuild.mockResolvedValue({
|
|
53
|
-
components: {},
|
|
54
|
-
pageRegistry: {},
|
|
55
|
-
context: { warnings: [warning] },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const build = lowdefyBuild(context);
|
|
59
|
-
await build();
|
|
60
|
-
|
|
61
|
-
expect(mockWriteBuildStatus).toHaveBeenCalledWith({
|
|
62
|
-
directories: context.directories,
|
|
63
|
-
status: 'ok',
|
|
64
|
-
errors: [],
|
|
65
|
-
warnings: [{ message: 'Deprecated feature used' }],
|
|
66
|
-
});
|
|
67
|
-
expect(mockSerializeBuildException).toHaveBeenCalledWith(warning, 0, [warning]);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('lowdefyBuild writes an error buildStatus.json and rethrows when the build fails', async () => {
|
|
71
|
-
const context = createContext();
|
|
72
|
-
const buildError = new Error('Build failed with 1 error(s). See above for details.');
|
|
73
|
-
buildError.errors = [{ message: 'Bad config' }];
|
|
74
|
-
buildError.warnings = [{ message: 'Deprecated feature used' }];
|
|
75
|
-
mockShallowBuild.mockRejectedValue(buildError);
|
|
76
|
-
|
|
77
|
-
const build = lowdefyBuild(context);
|
|
78
|
-
await expect(build()).rejects.toBe(buildError);
|
|
79
|
-
|
|
80
|
-
expect(mockWriteBuildStatus).toHaveBeenCalledWith({
|
|
81
|
-
directories: context.directories,
|
|
82
|
-
status: 'error',
|
|
83
|
-
errors: [{ message: 'Bad config' }],
|
|
84
|
-
warnings: [{ message: 'Deprecated feature used' }],
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('lowdefyBuild falls back to the raw error message when the thrown error has no errors array', async () => {
|
|
89
|
-
const context = createContext();
|
|
90
|
-
const buildError = new Error('Build failed due to internal error. See above for details.');
|
|
91
|
-
mockShallowBuild.mockRejectedValue(buildError);
|
|
92
|
-
|
|
93
|
-
const build = lowdefyBuild(context);
|
|
94
|
-
await expect(build()).rejects.toBe(buildError);
|
|
95
|
-
|
|
96
|
-
expect(mockWriteBuildStatus).toHaveBeenCalledWith({
|
|
97
|
-
directories: context.directories,
|
|
98
|
-
status: 'error',
|
|
99
|
-
errors: [{ message: 'Build failed due to internal error. See above for details.' }],
|
|
100
|
-
warnings: [],
|
|
101
|
-
});
|
|
102
|
-
});
|
|
@@ -1,30 +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
|
-
// Draws a rounded box around a title and body lines for CLI startup notices.
|
|
18
|
-
// The border width is derived from the longest line so it's always aligned,
|
|
19
|
-
// regardless of the content passed in. Returned with a leading newline so it
|
|
20
|
-
// starts on its own line under the CLI logger's timestamp/symbol prefix.
|
|
21
|
-
function formatNoticeBox({ title, lines }) {
|
|
22
|
-
const inner = Math.max(title.length + 1, ...lines.map((line) => line.length));
|
|
23
|
-
const pad = (line) => line + ' '.repeat(inner - line.length);
|
|
24
|
-
const top = `╭─ ${title} ${'─'.repeat(inner - title.length - 1)}╮`;
|
|
25
|
-
const bottom = `╰${'─'.repeat(inner + 2)}╯`;
|
|
26
|
-
const body = lines.map((line) => `│ ${pad(line)} │`);
|
|
27
|
-
return ['', top, ...body, bottom].join('\n');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default formatNoticeBox;
|
|
@@ -1,39 +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 path from 'path';
|
|
18
|
-
|
|
19
|
-
import { writeFileIfChanged } from '@lowdefy/node-utils';
|
|
20
|
-
|
|
21
|
-
// Written after every dev build attempt (success or failure) so the Hono
|
|
22
|
-
// process - a separate process from this manager, sharing only the build
|
|
23
|
-
// directory - can serve current build errors/warnings to AI coding agents.
|
|
24
|
-
// writeFileIfChanged creates the build directory if it does not exist, which
|
|
25
|
-
// covers the case where the build attempt cleaned it before failing.
|
|
26
|
-
async function writeBuildStatus({ directories, status, errors, warnings }) {
|
|
27
|
-
const buildStatus = {
|
|
28
|
-
status,
|
|
29
|
-
timestamp: new Date().toISOString(),
|
|
30
|
-
errors,
|
|
31
|
-
warnings,
|
|
32
|
-
};
|
|
33
|
-
await writeFileIfChanged(
|
|
34
|
-
path.join(directories.build, 'buildStatus.json'),
|
|
35
|
-
JSON.stringify(buildStatus)
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default writeBuildStatus;
|
|
@@ -1,76 +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 fs from 'fs';
|
|
18
|
-
import os from 'os';
|
|
19
|
-
import path from 'path';
|
|
20
|
-
|
|
21
|
-
import writeBuildStatus from './writeBuildStatus.mjs';
|
|
22
|
-
|
|
23
|
-
let buildDir;
|
|
24
|
-
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
buildDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lowdefy-build-status-test-'));
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
function readBuildStatus() {
|
|
34
|
-
return JSON.parse(fs.readFileSync(path.join(buildDir, 'buildStatus.json'), 'utf8'));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
test('writeBuildStatus writes an ok status with a timestamp', async () => {
|
|
38
|
-
await writeBuildStatus({
|
|
39
|
-
directories: { build: buildDir },
|
|
40
|
-
status: 'ok',
|
|
41
|
-
errors: [],
|
|
42
|
-
warnings: [{ message: 'Deprecated feature used' }],
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const buildStatus = readBuildStatus();
|
|
46
|
-
expect(buildStatus.status).toBe('ok');
|
|
47
|
-
expect(buildStatus.errors).toEqual([]);
|
|
48
|
-
expect(buildStatus.warnings).toEqual([{ message: 'Deprecated feature used' }]);
|
|
49
|
-
expect(new Date(buildStatus.timestamp).toString()).not.toBe('Invalid Date');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('writeBuildStatus writes an error status with the errors array', async () => {
|
|
53
|
-
await writeBuildStatus({
|
|
54
|
-
directories: { build: buildDir },
|
|
55
|
-
status: 'error',
|
|
56
|
-
errors: [{ message: 'Bad config' }],
|
|
57
|
-
warnings: [],
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const buildStatus = readBuildStatus();
|
|
61
|
-
expect(buildStatus.status).toBe('error');
|
|
62
|
-
expect(buildStatus.errors).toEqual([{ message: 'Bad config' }]);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('writeBuildStatus creates the build directory when it does not exist', async () => {
|
|
66
|
-
const missingDir = path.join(buildDir, 'nested', 'build');
|
|
67
|
-
|
|
68
|
-
await writeBuildStatus({
|
|
69
|
-
directories: { build: missingDir },
|
|
70
|
-
status: 'error',
|
|
71
|
-
errors: [{ message: 'Bad config' }],
|
|
72
|
-
warnings: [],
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
expect(fs.existsSync(path.join(missingDir, 'buildStatus.json'))).toBe(true);
|
|
76
|
-
});
|
package/postcss.config.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = { plugins: { '@tailwindcss/postcss': {} } };
|