@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
|
@@ -14,27 +14,22 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { getNextAuthConfig } from '@lowdefy/api';
|
|
18
18
|
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
|
19
19
|
|
|
20
|
-
import
|
|
20
|
+
import adapters from '../../../build/plugins/auth/adapters.js';
|
|
21
21
|
import authJson from '../../build/auth.js';
|
|
22
|
-
import
|
|
22
|
+
import callbacks from '../../../build/plugins/auth/callbacks.js';
|
|
23
|
+
import events from '../../../build/plugins/auth/events.js';
|
|
24
|
+
import providers from '../../../build/plugins/auth/providers.js';
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// in config order when no session resolves.
|
|
27
|
-
function getStrategies({ logger }) {
|
|
28
|
-
if (authJson.configured !== true) {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
return getAuthStrategies({
|
|
32
|
-
appMeta,
|
|
26
|
+
function getAuthOptions({ logger }) {
|
|
27
|
+
return getNextAuthConfig({
|
|
33
28
|
authJson,
|
|
34
29
|
logger,
|
|
35
|
-
plugins: {
|
|
30
|
+
plugins: { adapters, callbacks, events, providers },
|
|
36
31
|
secrets: getSecretsFromEnv(),
|
|
37
32
|
});
|
|
38
33
|
}
|
|
39
34
|
|
|
40
|
-
export default
|
|
35
|
+
export default getAuthOptions;
|
|
@@ -14,15 +14,13 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { createSessionCallback } from '@lowdefy/api';
|
|
17
18
|
import { serializer } from '@lowdefy/helpers';
|
|
18
19
|
|
|
19
20
|
import authJson from '../../build/auth.js';
|
|
21
|
+
import callbacks from '../../../build/plugins/auth/callbacks.js';
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
// resolveAuthentication step - no auth engine, no session lookup, no
|
|
23
|
-
// membership wall. Its roles are authoritative. LOWDEFY_DEV_USER takes
|
|
24
|
-
// priority over auth.dev.mockUser from lowdefy.yaml.
|
|
25
|
-
function getMockUser() {
|
|
23
|
+
async function getMockSession() {
|
|
26
24
|
const mockUserJson = process.env.LOWDEFY_DEV_USER;
|
|
27
25
|
let mockUser;
|
|
28
26
|
|
|
@@ -37,7 +35,7 @@ function getMockUser() {
|
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
if (!mockUser) {
|
|
40
|
-
return
|
|
38
|
+
return undefined;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
// Deserialize to restore arrays from ~arr markers and remove other build markers
|
|
@@ -50,9 +48,20 @@ function getMockUser() {
|
|
|
50
48
|
);
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
// Create session callback to transform mock user
|
|
52
|
+
const sessionCallback = createSessionCallback({
|
|
53
|
+
authConfig: authJson,
|
|
54
|
+
plugins: { callbacks },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Transform mock user through session callback (mock user acts as token)
|
|
58
|
+
const session = await sessionCallback({
|
|
59
|
+
session: { user: {} },
|
|
60
|
+
token: mockUser,
|
|
61
|
+
user: mockUser,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return session;
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
export default
|
|
67
|
+
export default getMockSession;
|
|
@@ -14,20 +14,22 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import { getServerSession as getNextAuthServerSession } from 'next-auth/next';
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
import authJson from '../../build/auth.js';
|
|
20
|
+
import getMockSession from './getMockSession.js';
|
|
21
|
+
|
|
22
|
+
async function getServerSession({ authOptions, req, res }) {
|
|
23
|
+
// Check for mock user first (dev server only)
|
|
24
|
+
const mockSession = await getMockSession();
|
|
25
|
+
if (mockSession) {
|
|
26
|
+
return mockSession;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return c.json(result);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
return c.json({ error: error.message }, 400);
|
|
29
|
+
if (authJson.configured === true) {
|
|
30
|
+
return getNextAuthServerSession(req, res, authOptions);
|
|
30
31
|
}
|
|
32
|
+
return undefined;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
export default
|
|
35
|
+
export default getServerSession;
|
|
@@ -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 fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import postcss from 'postcss';
|
|
20
|
+
import tailwindcssPlugin from '@tailwindcss/postcss';
|
|
21
|
+
|
|
22
|
+
async function compileCss(buildDirectory) {
|
|
23
|
+
const serverDirectory = path.resolve(buildDirectory, '..');
|
|
24
|
+
const inputPath = path.join(buildDirectory, 'globals.css');
|
|
25
|
+
const outputPath = path.join(serverDirectory, 'public/tailwind-jit.css');
|
|
26
|
+
if (!fs.existsSync(inputPath)) return;
|
|
27
|
+
const css = fs.readFileSync(inputPath, 'utf8');
|
|
28
|
+
const result = await postcss([tailwindcssPlugin()]).process(css, {
|
|
29
|
+
from: inputPath,
|
|
30
|
+
to: outputPath,
|
|
31
|
+
});
|
|
32
|
+
// The Tailwind PostCSS plugin consumes the @layer order declaration from
|
|
33
|
+
// globals.css during compilation. Re-inject it as the first line so the
|
|
34
|
+
// browser establishes the correct cascade priority (antd > base/preflight).
|
|
35
|
+
const layerOrder = '@layer theme, base, antd, components, utilities;\n';
|
|
36
|
+
fs.writeFileSync(outputPath, layerOrder + result.css);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default compileCss;
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
import fs from 'fs';
|
|
18
18
|
import path from 'path';
|
|
19
19
|
import { serializer } from '@lowdefy/helpers';
|
|
20
|
-
import { buildPageJit, createContext,
|
|
20
|
+
import { buildPageJit, createContext, makeId } from '@lowdefy/build/dev';
|
|
21
21
|
|
|
22
|
+
import compileCss from './compileCss.js';
|
|
22
23
|
import createLogger from './log/createLogger.js';
|
|
23
24
|
import PageCache from './pageCache.mjs';
|
|
24
25
|
import readBuildApiArtifacts from './readBuildApiArtifacts.mjs';
|
|
@@ -35,10 +36,10 @@ let cachedRegistry = null;
|
|
|
35
36
|
let cachedBuildContext = null;
|
|
36
37
|
let lastInvalidationMtime = null;
|
|
37
38
|
|
|
38
|
-
// Frozen snapshot of icon imports from the initial build (what's actually in the
|
|
39
|
+
// Frozen snapshot of icon imports from the initial build (what's actually in the Next.js bundle).
|
|
39
40
|
// Module-level so it persists across context resets (skeleton rebuilds update iconImports.json
|
|
40
|
-
// with newly discovered icons, but those aren't in the bundle until
|
|
41
|
-
// Only resets when the server process restarts.
|
|
41
|
+
// with newly discovered icons, but those aren't in the bundle until the next nextBuild).
|
|
42
|
+
// Only resets when the server process restarts (which happens after every nextBuild).
|
|
42
43
|
let bundledIconImports = null;
|
|
43
44
|
|
|
44
45
|
function readJsonFile(filePath) {
|
|
@@ -91,10 +92,10 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
91
92
|
const keyMap = readJsonFile(path.join(buildDirectory, 'keyMap.json')) ?? {};
|
|
92
93
|
const jsMap = readJsonFile(path.join(buildDirectory, 'jsMap.json')) ?? { client: {}, server: {} };
|
|
93
94
|
const connectionIds = readJsonFile(path.join(buildDirectory, 'connectionIds.json')) ?? [];
|
|
94
|
-
const websocketIds = readJsonFile(path.join(buildDirectory, 'websocketIds.json')) ?? [];
|
|
95
95
|
|
|
96
96
|
const customTypesMap = readJsonFile(path.join(buildDirectory, 'customTypesMap.json')) ?? {};
|
|
97
|
-
const customMessagesMap =
|
|
97
|
+
const customMessagesMap =
|
|
98
|
+
readJsonFile(path.join(buildDirectory, 'customMessagesMap.json')) ?? {};
|
|
98
99
|
|
|
99
100
|
cachedBuildContext = createContext({
|
|
100
101
|
customMessagesMap,
|
|
@@ -108,7 +109,7 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
108
109
|
stage: 'dev',
|
|
109
110
|
});
|
|
110
111
|
|
|
111
|
-
// Restore refMap, keyMap, jsMap,
|
|
112
|
+
// Restore refMap, keyMap, jsMap, and connectionIds from skeleton build
|
|
112
113
|
Object.assign(cachedBuildContext.refMap, refMap);
|
|
113
114
|
Object.assign(cachedBuildContext.keyMap, keyMap);
|
|
114
115
|
cachedBuildContext.jsMap.client = jsMap.client ?? {};
|
|
@@ -116,9 +117,6 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
116
117
|
for (const id of connectionIds) {
|
|
117
118
|
cachedBuildContext.connectionIds.add(id);
|
|
118
119
|
}
|
|
119
|
-
for (const id of websocketIds) {
|
|
120
|
-
cachedBuildContext.websocketIds.add(id);
|
|
121
|
-
}
|
|
122
120
|
|
|
123
121
|
// Load installed packages snapshot from skeleton build for missing-package detection
|
|
124
122
|
const installedPluginPackages =
|
|
@@ -131,27 +129,15 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
131
129
|
Object.assign(cachedBuildContext.modules, modules);
|
|
132
130
|
}
|
|
133
131
|
|
|
134
|
-
// Hydrate the deferred-record registry — module component bodies referenced
|
|
135
|
-
// by '~deferred' placeholders in modules.json live here. readJsonFile runs
|
|
136
|
-
// the marker-restoring reviver, so record-body ~r/~l markers survive.
|
|
137
|
-
const deferredRecords = readJsonFile(path.join(buildDirectory, 'deferredRecords.json'));
|
|
138
|
-
if (deferredRecords) {
|
|
139
|
-
hydrateDeferredRecords(cachedBuildContext, deferredRecords);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Restore app metadata so JIT page builds resolve _app / _build.app against
|
|
143
|
-
// the same metadata the skeleton build computed.
|
|
144
|
-
cachedBuildContext.appMeta = readJsonFile(path.join(buildDirectory, 'appMeta.json')) ?? null;
|
|
145
|
-
|
|
146
132
|
// Restore api endpoint configs so JIT CallAPI validation (validateCallApiRefs in
|
|
147
133
|
// buildPageJit) can resolve endpointIds. Without this the dev context has no
|
|
148
134
|
// components.api and every CallAPI action is flagged as a non-existent endpoint.
|
|
149
135
|
cachedBuildContext.components = { api: readBuildApiArtifacts(buildDirectory) };
|
|
150
136
|
|
|
151
137
|
// Use the frozen icon imports from the initial build for JIT detection.
|
|
152
|
-
// This represents what's actually in the
|
|
138
|
+
// This represents what's actually in the Next.js bundle — not what shallowBuild
|
|
153
139
|
// discovers on subsequent rebuilds (those icons aren't bundled yet).
|
|
154
|
-
// bundledIconImports is module-level and only resets on server restart.
|
|
140
|
+
// bundledIconImports is module-level and only resets on server restart (after nextBuild).
|
|
155
141
|
if (!bundledIconImports) {
|
|
156
142
|
bundledIconImports = readJsonFile(path.join(buildDirectory, 'iconImports.json')) ?? [];
|
|
157
143
|
}
|
|
@@ -204,18 +190,7 @@ async function buildPageIfNeeded({ pageId, buildDirectory, configDirectory }) {
|
|
|
204
190
|
return result;
|
|
205
191
|
}
|
|
206
192
|
pageCache.markCompiled(pageId);
|
|
207
|
-
|
|
208
|
-
// classes the JIT build discovered — globals.css imports it. This import
|
|
209
|
-
// is the ONLY recompile trigger: the tailwind .html scan inputs are
|
|
210
|
-
// excluded from Vite's watcher (their .html change events would force
|
|
211
|
-
// full browser reloads). Only touched when the build actually changed
|
|
212
|
-
// tailwind content, so unchanged rebuilds cause no CSS recompile.
|
|
213
|
-
if (result?._tailwindChanged) {
|
|
214
|
-
fs.writeFileSync(
|
|
215
|
-
path.join(buildDirectory, 'tailwind-candidates.css'),
|
|
216
|
-
`/* Generated by Lowdefy build — rewritten on page changes to trigger CSS recompilation */\n/* ${Date.now()} */\n`
|
|
217
|
-
);
|
|
218
|
-
}
|
|
193
|
+
await compileCss(buildDirectory);
|
|
219
194
|
jitLogger.info(
|
|
220
195
|
{ spin: 'succeed', color: 'white' },
|
|
221
196
|
`Built page "${pageId}" in ${formatDuration(Date.now() - startTime)}.`
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
|
|
17
17
|
// TODO: Better name needed here maybe?
|
|
18
18
|
function logRequest({ context }) {
|
|
19
|
-
const user =
|
|
19
|
+
const { user = {} } = context;
|
|
20
20
|
context.logger.debug({
|
|
21
21
|
user: {
|
|
22
22
|
id: user.id,
|
|
23
23
|
roles: user.roles,
|
|
24
|
+
sub: user.sub,
|
|
25
|
+
session_id: user.session_id,
|
|
24
26
|
},
|
|
25
27
|
url: context.req.url,
|
|
26
28
|
method: context.req.method,
|
package/manager/getContext.mjs
CHANGED
|
@@ -22,16 +22,18 @@ import { hideBin } from 'yargs/helpers';
|
|
|
22
22
|
import pino from 'pino';
|
|
23
23
|
import { createNodeLogger } from '@lowdefy/logger/node';
|
|
24
24
|
import checkMockUserWarning from './processes/checkMockUserWarning.mjs';
|
|
25
|
+
import compileCss from './processes/compileCss.mjs';
|
|
25
26
|
import initialBuild from './processes/initialBuild.mjs';
|
|
26
27
|
import installPlugins from './processes/installPlugins.mjs';
|
|
27
28
|
import lowdefyBuild from './processes/lowdefyBuild.mjs';
|
|
29
|
+
import nextBuild from './processes/nextBuild.mjs';
|
|
28
30
|
import readDotEnv from './processes/readDotEnv.mjs';
|
|
29
31
|
import reloadClients from './processes/reloadClients.mjs';
|
|
30
32
|
import restartServer from './processes/restartServer.mjs';
|
|
31
33
|
import shutdownServer from './processes/shutdownServer.mjs';
|
|
32
34
|
import startWatchers from './processes/startWatchers.mjs';
|
|
33
35
|
|
|
34
|
-
import
|
|
36
|
+
import getNextBin from './utils/getNextBin.mjs';
|
|
35
37
|
|
|
36
38
|
const argv = yargs(hideBin(process.argv)).array('watch').array('watchIgnore').argv;
|
|
37
39
|
|
|
@@ -40,7 +42,7 @@ async function getContext() {
|
|
|
40
42
|
|
|
41
43
|
const context = {
|
|
42
44
|
bin: {
|
|
43
|
-
|
|
45
|
+
next: getNextBin(),
|
|
44
46
|
},
|
|
45
47
|
directories: {
|
|
46
48
|
build: path.resolve(process.cwd(), './build'),
|
|
@@ -54,7 +56,7 @@ async function getContext() {
|
|
|
54
56
|
destination: pino.destination({ dest: 1, sync: true }),
|
|
55
57
|
}),
|
|
56
58
|
options: {
|
|
57
|
-
port:
|
|
59
|
+
port: argv.port ?? env.PORT ?? 3000,
|
|
58
60
|
refResolver: argv.refResolver ?? env.LOWDEFY_BUILD_REF_RESOLVER,
|
|
59
61
|
watch:
|
|
60
62
|
argv.watch ?? env.LOWDEFY_SERVER_DEV_WATCH ? JSON.parse(env.LOWDEFY_SERVER_DEV_WATCH) : [],
|
|
@@ -85,6 +87,8 @@ async function getContext() {
|
|
|
85
87
|
}
|
|
86
88
|
};
|
|
87
89
|
|
|
90
|
+
context.compileCss = compileCss(context);
|
|
91
|
+
context.nextBuild = nextBuild(context);
|
|
88
92
|
context.readDotEnv = readDotEnv(context);
|
|
89
93
|
context.reloadClients = reloadClients(context);
|
|
90
94
|
context.restartServer = restartServer(context);
|
|
@@ -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 fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import postcss from 'postcss';
|
|
20
|
+
import tailwindcssPlugin from '@tailwindcss/postcss';
|
|
21
|
+
|
|
22
|
+
function formatDuration(ms) {
|
|
23
|
+
if (ms < 1000) return `${ms}ms`;
|
|
24
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function compileCss({ directories, logger }) {
|
|
28
|
+
return async () => {
|
|
29
|
+
const inputPath = path.join(directories.build, 'globals.css');
|
|
30
|
+
const outputPath = path.join(directories.server, 'public/tailwind-jit.css');
|
|
31
|
+
if (!fs.existsSync(inputPath)) return;
|
|
32
|
+
|
|
33
|
+
logger.info({ spin: 'start' }, 'Compiling CSS...');
|
|
34
|
+
const startTime = Date.now();
|
|
35
|
+
|
|
36
|
+
const css = fs.readFileSync(inputPath, 'utf8');
|
|
37
|
+
const result = await postcss([tailwindcssPlugin()]).process(css, {
|
|
38
|
+
from: inputPath,
|
|
39
|
+
to: outputPath,
|
|
40
|
+
});
|
|
41
|
+
// The Tailwind PostCSS plugin consumes the @layer order declaration from
|
|
42
|
+
// globals.css during compilation. Re-inject it as the first line so the
|
|
43
|
+
// browser establishes the correct cascade priority (antd > base/preflight).
|
|
44
|
+
const layerOrder = '@layer theme, base, antd, components, utilities;\n';
|
|
45
|
+
fs.writeFileSync(outputPath, layerOrder + result.css);
|
|
46
|
+
|
|
47
|
+
logger.info(
|
|
48
|
+
{ spin: 'succeed' },
|
|
49
|
+
`Compiled CSS in ${formatDuration(Date.now() - startTime)}.`
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default compileCss;
|
|
@@ -14,29 +14,21 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { spawnProcess } from '@lowdefy/node-utils';
|
|
18
18
|
|
|
19
|
-
function installPlugins({
|
|
19
|
+
function installPlugins({ logger, packageManagerCmd }) {
|
|
20
20
|
return async () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
processOptions: {
|
|
27
|
-
// https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2#command-injection-via-args-parameter-of-child_processspawn-without-shell-option-enabled-on-windows-cve-2024-27980---high
|
|
28
|
-
shell: process.platform === 'win32',
|
|
29
|
-
},
|
|
30
|
-
command: packageManagerCmd,
|
|
31
|
-
args: ['install', '--no-frozen-lockfile'],
|
|
32
|
-
stdOutLineHandler: (line) => logger.debug(line),
|
|
33
|
-
});
|
|
34
|
-
logger.info('Installed plugins.');
|
|
21
|
+
logger.info({ spin: 'start' }, 'Installing plugins...');
|
|
22
|
+
await spawnProcess({
|
|
23
|
+
processOptions: {
|
|
24
|
+
// https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2#command-injection-via-args-parameter-of-child_processspawn-without-shell-option-enabled-on-windows-cve-2024-27980---high
|
|
25
|
+
shell: process.platform === 'win32',
|
|
35
26
|
},
|
|
27
|
+
command: packageManagerCmd,
|
|
28
|
+
args: ['install', '--no-frozen-lockfile'],
|
|
29
|
+
stdOutLineHandler: (line) => logger.debug(line),
|
|
36
30
|
});
|
|
37
|
-
|
|
38
|
-
logger.debug('Plugin dependencies unchanged, skipped install.');
|
|
39
|
-
}
|
|
31
|
+
logger.info('Installed plugins.');
|
|
40
32
|
};
|
|
41
33
|
}
|
|
42
34
|
|
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { shallowBuild } from '@lowdefy/build/dev';
|
|
18
18
|
import createCustomPluginMessagesMap from '../utils/createCustomPluginMessagesMap.mjs';
|
|
19
19
|
import createCustomPluginTypesMap from '../utils/createCustomPluginTypesMap.mjs';
|
|
20
|
-
import writeBuildStatus from '../utils/writeBuildStatus.mjs';
|
|
21
20
|
|
|
22
21
|
function formatDuration(ms) {
|
|
23
22
|
if (ms < 1000) return `${ms}ms`;
|
|
@@ -31,34 +30,13 @@ function lowdefyBuild({ directories, logger, options }) {
|
|
|
31
30
|
const customTypesMap = await createCustomPluginTypesMap({ directories, logger });
|
|
32
31
|
const customMessagesMap = await createCustomPluginMessagesMap({ directories, logger });
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
customMessagesMap,
|
|
38
|
-
customTypesMap,
|
|
39
|
-
directories,
|
|
40
|
-
logger,
|
|
41
|
-
refResolver: options.refResolver,
|
|
42
|
-
stage: 'dev',
|
|
43
|
-
});
|
|
44
|
-
} catch (error) {
|
|
45
|
-
// Write the artifact after the attempt fails - the build may have
|
|
46
|
-
// cleaned the build directory before failing, so this must not run
|
|
47
|
-
// before the attempt completes.
|
|
48
|
-
await writeBuildStatus({
|
|
49
|
-
directories,
|
|
50
|
-
status: 'error',
|
|
51
|
-
errors: error.errors ?? [{ message: error.message }],
|
|
52
|
-
warnings: error.warnings ?? [],
|
|
53
|
-
});
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
await writeBuildStatus({
|
|
33
|
+
const result = await shallowBuild({
|
|
34
|
+
customMessagesMap,
|
|
35
|
+
customTypesMap,
|
|
58
36
|
directories,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
logger,
|
|
38
|
+
refResolver: options.refResolver,
|
|
39
|
+
stage: 'dev',
|
|
62
40
|
});
|
|
63
41
|
|
|
64
42
|
// Return result so getContext can store registries
|
|
@@ -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
|
+
|
|
17
|
+
import { BuildError } from '@lowdefy/errors';
|
|
18
|
+
import { spawnProcess } from '@lowdefy/node-utils';
|
|
19
|
+
|
|
20
|
+
function formatDuration(ms) {
|
|
21
|
+
if (ms < 1000) return `${ms}ms`;
|
|
22
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function nextBuild({ bin, logger }) {
|
|
26
|
+
return async () => {
|
|
27
|
+
logger.info({ spin: 'start' }, 'Building app...');
|
|
28
|
+
const startTime = Date.now();
|
|
29
|
+
const errorLines = [];
|
|
30
|
+
try {
|
|
31
|
+
await spawnProcess({
|
|
32
|
+
command: 'node',
|
|
33
|
+
args: ['--max-old-space-size=4096', bin.next, 'build'],
|
|
34
|
+
stdOutLineHandler: (line) => logger.debug(line),
|
|
35
|
+
stdErrLineHandler: (line) => {
|
|
36
|
+
logger.debug(line);
|
|
37
|
+
errorLines.push(line);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (errorLines.length > 0) {
|
|
42
|
+
errorLines.forEach((line) => logger.error(line));
|
|
43
|
+
}
|
|
44
|
+
throw new BuildError('Next.js build failed. See above for details.');
|
|
45
|
+
}
|
|
46
|
+
logger.info({ spin: 'succeed' }, `Built app in ${formatDuration(Date.now() - startTime)}.`);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default nextBuild;
|
|
@@ -18,20 +18,8 @@ import path from 'path';
|
|
|
18
18
|
import dotenv from 'dotenv';
|
|
19
19
|
|
|
20
20
|
function readDotEnv(context) {
|
|
21
|
-
// dotenv.config() never overwrites env vars that are already set, so on
|
|
22
|
-
// the first load the real shell environment wins over .env (standard
|
|
23
|
-
// dotenv behavior). On reloads triggered by the .env watcher the previous
|
|
24
|
-
// load has already populated process.env, so without override the changed
|
|
25
|
-
// values would never take effect and the server would restart with stale
|
|
26
|
-
// env.
|
|
27
|
-
let loadedOnce = false;
|
|
28
21
|
return () => {
|
|
29
|
-
dotenv.config({
|
|
30
|
-
path: path.join(context.directories.config, '.env'),
|
|
31
|
-
silent: true,
|
|
32
|
-
override: loadedOnce,
|
|
33
|
-
});
|
|
34
|
-
loadedOnce = true;
|
|
22
|
+
dotenv.config({ path: path.join(context.directories.config, '.env'), silent: true });
|
|
35
23
|
};
|
|
36
24
|
}
|
|
37
25
|
|
|
@@ -16,18 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
function shutdownServer(context) {
|
|
18
18
|
return () => {
|
|
19
|
-
if (context.
|
|
19
|
+
if (context.nextServer) {
|
|
20
20
|
context.logger.debug(
|
|
21
|
-
`Existing
|
|
21
|
+
`Existing next server with pid ${context.nextServer.pid}, killed: ${context.nextServer.killed}`
|
|
22
22
|
);
|
|
23
|
-
if (!context.
|
|
23
|
+
if (!context.nextServer.killed) {
|
|
24
24
|
context.logger.info({ spin: 'start' }, 'Shutting down server...');
|
|
25
|
-
context.
|
|
25
|
+
context.nextServer.kill();
|
|
26
26
|
context.logger.debug(
|
|
27
|
-
`Killed
|
|
27
|
+
`Killed next server with pid ${context.nextServer.pid}, killed: ${context.nextServer.killed}`
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
|
-
context.
|
|
30
|
+
context.nextServer = null;
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
}
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
import { spawn } from 'child_process';
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
function createStdErrLineHandler({ context }) {
|
|
21
20
|
const port = context.options.port;
|
|
22
21
|
return function stdErrLineHandler(line) {
|
|
@@ -33,7 +32,7 @@ function createStdErrLineHandler({ context }) {
|
|
|
33
32
|
function startServer(context) {
|
|
34
33
|
context.shutdownServer();
|
|
35
34
|
|
|
36
|
-
const
|
|
35
|
+
const nextServer = spawn('node', [context.bin.next, 'start'], {
|
|
37
36
|
stdio: ['ignore', 'inherit', 'pipe'],
|
|
38
37
|
env: {
|
|
39
38
|
...process.env,
|
|
@@ -43,7 +42,7 @@ function startServer(context) {
|
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
const stdErrLineHandler = createStdErrLineHandler({ context });
|
|
46
|
-
|
|
45
|
+
nextServer.stderr.on('data', (data) => {
|
|
47
46
|
data
|
|
48
47
|
.toString('utf8')
|
|
49
48
|
.split('\n')
|
|
@@ -52,14 +51,14 @@ function startServer(context) {
|
|
|
52
51
|
});
|
|
53
52
|
});
|
|
54
53
|
|
|
55
|
-
context.logger.debug(`Started
|
|
56
|
-
|
|
57
|
-
context.logger.debug(`
|
|
54
|
+
context.logger.debug(`Started next server with pid ${nextServer.pid}.`);
|
|
55
|
+
nextServer.on('exit', (code, signal) => {
|
|
56
|
+
context.logger.debug(`nextServer exit ${nextServer.pid}, signal: ${signal}, code: ${code}`);
|
|
58
57
|
});
|
|
59
|
-
|
|
58
|
+
nextServer.on('error', (error) => {
|
|
60
59
|
context.logger.error(error);
|
|
61
60
|
});
|
|
62
|
-
context.
|
|
61
|
+
context.nextServer = nextServer;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
export default startServer;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import envWatcher from '../watchers/envWatcher.mjs';
|
|
18
18
|
import lowdefyBuildWatcher from '../watchers/lowdefyBuildWatcher.mjs';
|
|
19
19
|
import moduleBuildWatcher from '../watchers/moduleBuildWatcher.mjs';
|
|
20
|
-
import
|
|
20
|
+
import nextBuildWatcher from '../watchers/nextBuildWatcher.mjs';
|
|
21
21
|
|
|
22
22
|
function startWatchers(context) {
|
|
23
23
|
return async () => {
|
|
@@ -25,7 +25,7 @@ function startWatchers(context) {
|
|
|
25
25
|
envWatcher(context),
|
|
26
26
|
lowdefyBuildWatcher(context),
|
|
27
27
|
moduleBuildWatcher(context),
|
|
28
|
-
|
|
28
|
+
nextBuildWatcher(context),
|
|
29
29
|
]);
|
|
30
30
|
};
|
|
31
31
|
}
|