@lowdefy/server-dev 5.5.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{pages/_app.js → client/App.jsx} +21 -33
- package/client/DevStreamContext.js +30 -0
- package/client/Inspector.jsx +226 -0
- package/{lib/client/Page.js → client/Page.jsx} +4 -8
- package/client/Reload.jsx +85 -0
- package/client/Routing.jsx +117 -0
- package/client/feedback/FeedbackMount.jsx +83 -0
- package/client/feedback/FeedbackOverlay.jsx +901 -0
- package/client/feedback/captureTabScreenshot.js +84 -0
- package/client/feedback/copyToClipboard.js +45 -0
- package/client/feedback/drawAnnotationsSvg.js +119 -0
- package/client/feedback/elementInspect.js +99 -0
- package/client/feedback/feedbackStyles.js +301 -0
- package/client/feedback/pinResponsiveImages.js +59 -0
- package/client/feedback/sendFeedback.js +39 -0
- package/client/feedback/useFeedbackToggle.js +70 -0
- package/client/main.jsx +42 -0
- package/client/openInEditor/OpenInEditorListener.jsx +268 -0
- package/client/openInEditor/findBlockLocation.js +51 -0
- package/lib/build/app.js +8 -1
- package/lib/build/appMeta.js +8 -1
- package/lib/build/auth.js +8 -1
- package/lib/build/config.js +8 -1
- package/lib/build/i18n.js +8 -1
- package/lib/build/logger.js +8 -1
- package/lib/build/theme.js +8 -1
- package/lib/client/auth/{Auth.js → Auth.jsx} +11 -2
- package/lib/client/auth/{AuthConfigured.js → AuthConfigured.jsx} +23 -10
- package/lib/client/setPageId.js +6 -5
- package/lib/client/utils/useMutateCache.js +14 -1
- package/lib/client/utils/usePageConfig.js +45 -43
- package/lib/client/utils/usePageConfig.test.mjs +62 -0
- package/lib/docs/captureAnnotatedScreenshot.js +88 -0
- package/lib/docs/checkpointPaths.js +91 -0
- package/lib/docs/checkpointStore.js +240 -0
- package/lib/docs/checkpointToMocks.js +65 -0
- package/lib/docs/clientErrorStore.js +36 -0
- package/lib/docs/configCheckpoints.test.mjs +156 -0
- package/lib/docs/createConfigCheckpoint.js +92 -0
- package/lib/docs/createDocsMcpServer.js +531 -0
- package/lib/docs/createDocsMcpServer.test.mjs +141 -0
- package/lib/docs/devMockRegistry.js +68 -0
- package/lib/docs/docs.test.mjs +448 -0
- package/lib/docs/enrichFeedback.js +71 -0
- package/lib/docs/evalOperator.js +47 -0
- package/lib/docs/evalOperator.test.mjs +157 -0
- package/lib/docs/evalOperatorHeadless.js +87 -0
- package/lib/docs/evalOperatorHeadless.test.mjs +72 -0
- package/lib/docs/evalOperatorInTab.js +48 -0
- package/lib/docs/findConfig.js +260 -0
- package/lib/docs/formatFeedback.js +121 -0
- package/lib/docs/formatFeedback.test.mjs +204 -0
- package/lib/docs/getAppMap.js +180 -0
- package/lib/docs/getBrowser.js +127 -0
- package/lib/docs/getBrowser.test.mjs +122 -0
- package/lib/docs/getBuildStatus.js +37 -0
- package/lib/docs/getCoreDoc.js +63 -0
- package/lib/docs/getDocsManifest.js +40 -0
- package/lib/docs/getExamples.js +58 -0
- package/lib/docs/getOverview.js +115 -0
- package/lib/docs/getPageConfig.js +53 -0
- package/lib/docs/getPluginDoc.js +55 -0
- package/lib/docs/getSchema.js +65 -0
- package/lib/docs/inspectState.js +47 -0
- package/lib/docs/inspectState.test.mjs +140 -0
- package/lib/docs/inspectStateFromTab.js +40 -0
- package/lib/docs/inspectStateHeadless.js +84 -0
- package/lib/docs/inspectStateHeadless.test.mjs +60 -0
- package/lib/docs/isWriteRequestsAllowed.js +50 -0
- package/lib/docs/listConfigCheckpoints.js +55 -0
- package/lib/docs/listPlugins.js +80 -0
- package/lib/docs/listTypes.js +105 -0
- package/lib/docs/loadState.js +152 -0
- package/lib/docs/mapPageBuildErrors.js +28 -0
- package/lib/docs/normalizeTypeKind.js +40 -0
- package/{pages/api/endpoints/[...endpointId].js → lib/docs/readBuildArtifact.js} +15 -12
- package/lib/docs/readPageArtifact.js +26 -0
- package/lib/docs/resolvePluginDir.js +49 -0
- package/lib/docs/resolveSource.js +48 -0
- package/lib/docs/resolveSource.test.mjs +100 -0
- package/lib/docs/revertConfigCheckpoint.js +73 -0
- package/lib/docs/runRequest.js +141 -0
- package/lib/docs/saveAnnotatedScreenshot.js +43 -0
- package/lib/docs/scaffoldPage.js +75 -0
- package/lib/docs/scaffoldPage.test.mjs +97 -0
- package/lib/docs/screenshotPage.js +110 -0
- package/lib/docs/screenshotPage.test.mjs +59 -0
- package/lib/docs/screenshotPageClip.test.mjs +102 -0
- package/lib/docs/searchDocs.js +67 -0
- package/lib/docs/setupTestFixtures.mjs +335 -0
- package/lib/docs/snapshotState.js +59 -0
- package/lib/docs/stateCheckpoints.test.mjs +366 -0
- package/lib/docs/tabAvailable.js +28 -0
- package/lib/docs/tabChannel.js +119 -0
- package/lib/docs/tabChannel.test.mjs +130 -0
- package/lib/server/auth/{getAuthOptions.js → getAuthConfig.js} +7 -4
- package/lib/server/auth/getDevSession.js +70 -0
- package/lib/server/auth/getDevSession.test.mjs +138 -0
- package/lib/server/auth/getHeadlessUser.js +40 -0
- package/lib/server/auth/{getMockSession.js → getMockUser.js} +8 -21
- package/lib/server/auth/headlessUser.js +29 -0
- package/lib/server/auth/resolveHeadlessUser.js +38 -0
- package/lib/server/auth/resolveHeadlessUser.test.mjs +78 -0
- package/lib/server/auth/session.js +39 -0
- package/lib/server/auth/strategies.js +47 -0
- package/lib/server/{apiWrapper.js → createLowdefyContext.js} +63 -57
- package/lib/server/getPageJitEnrichment.test.mjs +105 -0
- package/lib/server/jitPageBuilder.js +125 -12
- package/lib/server/log/createHandleError.js +9 -0
- package/lib/server/log/createHandleError.test.mjs +126 -0
- package/manager/getContext.mjs +3 -7
- package/manager/processes/initialBuild.mjs +0 -2
- package/manager/processes/installPlugins.mjs +19 -11
- package/manager/processes/lowdefyBuild.mjs +29 -7
- package/manager/processes/lowdefyBuild.test.mjs +102 -0
- package/manager/processes/readDotEnv.mjs +13 -1
- package/manager/processes/shutdownServer.mjs +6 -6
- package/manager/processes/startProxy.mjs +160 -0
- package/manager/processes/startProxy.test.mjs +102 -0
- package/manager/processes/startServer.mjs +33 -16
- package/manager/processes/startWatchers.mjs +2 -2
- package/manager/processes/warnAuthUrlPortMismatch.mjs +47 -0
- package/manager/processes/warnAuthUrlPortMismatch.test.mjs +93 -0
- package/manager/run.mjs +50 -0
- package/manager/utils/createCustomPluginMessagesMap.mjs +8 -1
- package/manager/utils/createCustomPluginTypesMap.mjs +1 -0
- package/manager/utils/formatNoticeBox.mjs +30 -0
- package/manager/utils/{getNextBin.mjs → getViteBin.mjs} +7 -10
- package/manager/utils/updatePageTailwindCss.mjs +7 -1
- package/manager/utils/writeBuildStatus.mjs +39 -0
- package/manager/utils/writeBuildStatus.test.mjs +76 -0
- package/manager/watchers/lowdefyBuildWatcher.mjs +0 -1
- package/manager/watchers/moduleBuildWatcher.mjs +0 -1
- package/manager/watchers/{nextBuildWatcher.mjs → serverArtifactWatcher.mjs} +18 -20
- package/package.json +61 -47
- package/package.original.json +64 -55
- package/postcss.config.cjs +1 -0
- package/src/app.js +175 -0
- package/src/html/renderDevPage.js +86 -0
- package/src/lib/getPathSegments.js +25 -0
- package/src/lib/safeScriptJson.js +38 -0
- package/src/middleware/apiContext.js +32 -0
- package/src/middleware/errorHandler.js +48 -0
- package/src/middleware/errorHandler.test.mjs +235 -0
- package/src/routes/agent.js +64 -0
- package/src/routes/apiPage.js +37 -0
- package/src/routes/auth.js +49 -0
- package/src/routes/auth.test.mjs +84 -0
- package/src/routes/clientError.js +57 -0
- package/src/routes/cron.js +47 -0
- package/src/routes/cronForward.js +47 -0
- package/src/routes/detached.js +47 -0
- package/src/routes/devInspect.js +111 -0
- package/src/routes/devInspect.test.mjs +119 -0
- package/{pages/[[...pageId]].js → src/routes/devTools.js} +4 -2
- package/{pages/404.js → src/routes/docs/appMap.js} +6 -2
- package/{pages/api/dev-tools.js → src/routes/docs/buildStatus.js} +5 -4
- package/src/routes/docs/checkpointsCreate.js +28 -0
- package/src/routes/docs/checkpointsList.js +23 -0
- package/{pages/api/icons/dynamic.js → src/routes/docs/checkpointsRevert.js} +11 -12
- package/src/routes/docs/content.js +31 -0
- package/src/routes/docs/evalOperator.js +56 -0
- package/src/routes/docs/examples.js +33 -0
- package/src/routes/docs/find.js +30 -0
- package/src/routes/docs/index.js +23 -0
- package/src/routes/docs/inspectState.js +44 -0
- package/src/routes/docs/loadState.js +49 -0
- package/src/routes/docs/mcp.js +30 -0
- package/src/routes/docs/pageConfig.js +36 -0
- package/src/routes/docs/parseUserParam.js +52 -0
- package/src/routes/docs/parseUserParam.test.mjs +45 -0
- package/src/routes/docs/pluginDoc.js +33 -0
- package/src/routes/docs/plugins.js +23 -0
- package/src/routes/docs/runRequest.js +36 -0
- package/{lib/server/auth/getServerSession.js → src/routes/docs/schema.js} +17 -15
- package/src/routes/docs/screenshot.js +72 -0
- package/src/routes/docs/search.js +27 -0
- package/src/routes/docs/snapshotState.js +36 -0
- package/src/routes/docs/stateCheckpointsList.js +26 -0
- package/src/routes/docs/types.js +33 -0
- package/src/routes/endpoints.js +71 -0
- package/src/routes/feedback.js +110 -0
- package/src/routes/feedback.test.mjs +204 -0
- package/src/routes/jitPage.js +86 -0
- package/src/routes/mcp.js +34 -0
- package/{pages/api → src/routes}/ping.js +4 -2
- package/src/routes/reload.js +79 -0
- package/src/routes/request.js +74 -0
- package/src/routes/request.test.mjs +124 -0
- package/{pages/api → src/routes}/root.js +4 -4
- package/src/routes/usage.js +46 -0
- package/src/routes/websocket.js +33 -0
- package/src/websocket/devWebSocket.js +78 -0
- package/vite.config.js +111 -0
- package/.eslintrc.yaml +0 -1
- package/lib/client/App.js +0 -80
- package/lib/client/Reload.js +0 -60
- package/lib/server/compileCss.js +0 -39
- package/manager/processes/compileCss.mjs +0 -54
- package/manager/processes/nextBuild.mjs +0 -50
- package/next.config.js +0 -25
- package/pages/_document.js +0 -107
- package/pages/api/agent/[...path].js +0 -86
- package/pages/api/auth/[...nextauth].js +0 -48
- package/pages/api/client-error.js +0 -45
- package/pages/api/js/[env].js +0 -42
- package/pages/api/page/[...pageId].js +0 -74
- package/pages/api/reload.js +0 -53
- package/pages/api/request/[...path].js +0 -41
- /package/lib/client/{BuildErrorPage.js → BuildErrorPage.jsx} +0 -0
- /package/lib/client/{BuildingPage.js → BuildingPage.jsx} +0 -0
- /package/lib/client/{ErrorBar.js → ErrorBar.jsx} +0 -0
- /package/lib/client/{InstallingPluginsPage.js → InstallingPluginsPage.jsx} +0 -0
- /package/lib/client/{RestartingPage.js → RestartingPage.jsx} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
import warnAuthUrlPortMismatch from './warnAuthUrlPortMismatch.mjs';
|
|
19
|
+
|
|
20
|
+
const originalAuthUrl = process.env.AUTH_URL;
|
|
21
|
+
const originalNextAuthUrl = process.env.NEXTAUTH_URL;
|
|
22
|
+
|
|
23
|
+
function createContext(port) {
|
|
24
|
+
return {
|
|
25
|
+
options: { port },
|
|
26
|
+
logger: { warn: jest.fn() },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function restoreEnv(name, value) {
|
|
31
|
+
if (value === undefined) {
|
|
32
|
+
delete process.env[name];
|
|
33
|
+
} else {
|
|
34
|
+
process.env[name] = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
delete process.env.AUTH_URL;
|
|
40
|
+
delete process.env.NEXTAUTH_URL;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
restoreEnv('AUTH_URL', originalAuthUrl);
|
|
45
|
+
restoreEnv('NEXTAUTH_URL', originalNextAuthUrl);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('warnAuthUrlPortMismatch stays silent when no auth URL is set', () => {
|
|
49
|
+
const context = createContext(3001);
|
|
50
|
+
warnAuthUrlPortMismatch({ context });
|
|
51
|
+
expect(context.logger.warn).not.toHaveBeenCalled();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('warnAuthUrlPortMismatch stays silent when AUTH_URL matches the dev port', () => {
|
|
55
|
+
process.env.AUTH_URL = 'http://localhost:3000';
|
|
56
|
+
const context = createContext(3000);
|
|
57
|
+
warnAuthUrlPortMismatch({ context });
|
|
58
|
+
expect(context.logger.warn).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('warnAuthUrlPortMismatch warns when AUTH_URL port does not match', () => {
|
|
62
|
+
process.env.AUTH_URL = 'http://localhost:3000';
|
|
63
|
+
const context = createContext(3001);
|
|
64
|
+
warnAuthUrlPortMismatch({ context });
|
|
65
|
+
expect(context.logger.warn).toHaveBeenCalledTimes(1);
|
|
66
|
+
expect(context.logger.warn.mock.calls[0][0]).toContain(
|
|
67
|
+
'AUTH_URL (http://localhost:3000) does not match the dev server port 3001'
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('warnAuthUrlPortMismatch falls back to NEXTAUTH_URL and names it in the warning', () => {
|
|
72
|
+
process.env.NEXTAUTH_URL = 'http://localhost:3000';
|
|
73
|
+
const context = createContext(3001);
|
|
74
|
+
warnAuthUrlPortMismatch({ context });
|
|
75
|
+
expect(context.logger.warn).toHaveBeenCalledTimes(1);
|
|
76
|
+
expect(context.logger.warn.mock.calls[0][0]).toContain('NEXTAUTH_URL (http://localhost:3000)');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('warnAuthUrlPortMismatch treats an https URL without a port as 443', () => {
|
|
80
|
+
process.env.AUTH_URL = 'https://example.com';
|
|
81
|
+
const context = createContext(3000);
|
|
82
|
+
warnAuthUrlPortMismatch({ context });
|
|
83
|
+
expect(context.logger.warn).toHaveBeenCalledTimes(1);
|
|
84
|
+
expect(context.logger.warn.mock.calls[0][0]).toContain('does not match the dev server port 3000');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('warnAuthUrlPortMismatch warns when the auth URL is not a valid URL', () => {
|
|
88
|
+
process.env.AUTH_URL = 'not-a-url';
|
|
89
|
+
const context = createContext(3000);
|
|
90
|
+
warnAuthUrlPortMismatch({ context });
|
|
91
|
+
expect(context.logger.warn).toHaveBeenCalledTimes(1);
|
|
92
|
+
expect(context.logger.warn.mock.calls[0][0]).toContain('is not a valid URL');
|
|
93
|
+
});
|
package/manager/run.mjs
CHANGED
|
@@ -16,9 +16,12 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { wait } from '@lowdefy/helpers';
|
|
19
|
+
import { findAvailablePort } from '@lowdefy/node-utils';
|
|
19
20
|
import opener from 'opener';
|
|
20
21
|
import getContext from './getContext.mjs';
|
|
22
|
+
import startProxy from './processes/startProxy.mjs';
|
|
21
23
|
import startServer from './processes/startServer.mjs';
|
|
24
|
+
import formatNoticeBox from './utils/formatNoticeBox.mjs';
|
|
22
25
|
|
|
23
26
|
/*
|
|
24
27
|
The run script does the following:
|
|
@@ -78,6 +81,16 @@ The run script does the following:
|
|
|
78
81
|
|
|
79
82
|
const context = await getContext();
|
|
80
83
|
|
|
84
|
+
// Shut the Vite child down on direct signals (process managers, scripts/dev.mjs
|
|
85
|
+
// signal forwarding) — terminal Ctrl+C signals the whole process group, but a
|
|
86
|
+
// targeted SIGTERM would otherwise orphan the child.
|
|
87
|
+
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
88
|
+
process.on(signal, () => {
|
|
89
|
+
context.shutdownServer();
|
|
90
|
+
process.exit(0);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
81
94
|
try {
|
|
82
95
|
await context.initialBuild();
|
|
83
96
|
|
|
@@ -85,8 +98,45 @@ try {
|
|
|
85
98
|
// because chokidar sometimes doesn't fire this event, and it seems like there isn't an issue with not waiting.
|
|
86
99
|
context.startWatchers();
|
|
87
100
|
|
|
101
|
+
// The manager is the component that binds the port, so it re-checks here to
|
|
102
|
+
// cover every launch path (CLI, monorepo dev script, direct run.mjs) and any
|
|
103
|
+
// process that grabbed the port during the initial build.
|
|
104
|
+
const availablePort = await findAvailablePort({ port: context.options.port });
|
|
105
|
+
if (availablePort !== context.options.port) {
|
|
106
|
+
context.logger.warn(
|
|
107
|
+
`Port ${context.options.port} is in use, using port ${availablePort} instead.`
|
|
108
|
+
);
|
|
109
|
+
context.options.port = availablePort;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// The manager holds the public port for the whole session and proxies to the
|
|
113
|
+
// Vite child on an internal loopback port — restarting the child (js module
|
|
114
|
+
// or .env change) then never drops the listener, so long-lived clients (MCP
|
|
115
|
+
// agents, the reload SSE stream, HMR websockets) reconnect instead of dying
|
|
116
|
+
// on ECONNREFUSED.
|
|
117
|
+
context.internalPort = await findAvailablePort({ port: context.options.port + 1 });
|
|
118
|
+
await startProxy(context);
|
|
119
|
+
|
|
88
120
|
startServer(context);
|
|
89
121
|
await wait(800);
|
|
122
|
+
const docsUrl = `http://localhost:${context.options.port}/lowdefy-docs`;
|
|
123
|
+
context.logger.info(
|
|
124
|
+
{ color: 'blue' },
|
|
125
|
+
formatNoticeBox({
|
|
126
|
+
title: 'Lowdefy coding agent tools',
|
|
127
|
+
lines: [
|
|
128
|
+
`Docs & MCP ${docsUrl}`,
|
|
129
|
+
' run `lowdefy agent-setup` to connect your agent',
|
|
130
|
+
'',
|
|
131
|
+
'Annotate Press Cmd/Ctrl+/ in the browser to point, draw,',
|
|
132
|
+
' and comment on the running app, then paste the',
|
|
133
|
+
' copied feedback into your coding agent session.',
|
|
134
|
+
'',
|
|
135
|
+
'Open code Cmd/Ctrl+click any element in the browser to open',
|
|
136
|
+
' its yaml in VS Code at the defining line.',
|
|
137
|
+
],
|
|
138
|
+
})
|
|
139
|
+
);
|
|
90
140
|
if (process.env.LOWDEFY_SERVER_DEV_OPEN_BROWSER === 'true') {
|
|
91
141
|
// TODO: Wait 1 sec for a ping and don't open if a ping is seen
|
|
92
142
|
opener(`http://localhost:${context.options.port}`);
|
|
@@ -23,6 +23,10 @@ import YAML from 'yaml';
|
|
|
23
23
|
|
|
24
24
|
const require = createRequire(import.meta.url);
|
|
25
25
|
|
|
26
|
+
// The map is rebuilt on every config rebuild — warn once per plugin per
|
|
27
|
+
// process instead of repeating the same skip message on each rebuild.
|
|
28
|
+
const warnedMissingMessages = new Set();
|
|
29
|
+
|
|
26
30
|
async function getPluginDefinitions({ directories }) {
|
|
27
31
|
let lowdefyYaml = await readFile(path.join(directories.config, 'lowdefy.yaml'));
|
|
28
32
|
if (!lowdefyYaml) {
|
|
@@ -45,7 +49,10 @@ async function createCustomPluginMessagesMap({ directories, logger }) {
|
|
|
45
49
|
messagesModule = require(`${plugin.name}/messages`);
|
|
46
50
|
} catch (e) {
|
|
47
51
|
// Plugin does not ship a `./messages` export — silently skip.
|
|
48
|
-
|
|
52
|
+
if (!warnedMissingMessages.has(plugin.name)) {
|
|
53
|
+
warnedMissingMessages.add(plugin.name);
|
|
54
|
+
logger?.debug?.(`Plugin "${plugin.name}" has no "./messages" export; skipping.`);
|
|
55
|
+
}
|
|
49
56
|
continue;
|
|
50
57
|
}
|
|
51
58
|
const messages = messagesModule.default ?? messagesModule;
|
|
@@ -0,0 +1,30 @@
|
|
|
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;
|
|
@@ -17,20 +17,17 @@
|
|
|
17
17
|
import path from 'path';
|
|
18
18
|
import { createRequire } from 'module';
|
|
19
19
|
|
|
20
|
-
function
|
|
20
|
+
function getViteBin() {
|
|
21
21
|
const require = createRequire(import.meta.url);
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const nextPath = require.resolve('next');
|
|
25
|
-
let nextMainFragment = nextPackageJson.main.substring(1);
|
|
26
|
-
let nextBinFragment = nextPackageJson.bin.next;
|
|
22
|
+
const vitePackageJsonPath = require.resolve('vite/package.json');
|
|
23
|
+
const vitePackageJson = require('vite/package.json');
|
|
27
24
|
|
|
25
|
+
let viteBinFragment = vitePackageJson.bin.vite;
|
|
28
26
|
if (process.platform === 'win32') {
|
|
29
|
-
|
|
30
|
-
nextBinFragment = nextBinFragment.replaceAll('/', '\\');
|
|
27
|
+
viteBinFragment = viteBinFragment.replaceAll('/', '\\');
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
return path.join(
|
|
30
|
+
return path.join(path.dirname(vitePackageJsonPath), viteBinFragment);
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
export default
|
|
33
|
+
export default getViteBin;
|
|
@@ -65,7 +65,13 @@ async function updatePageTailwindCss({ changedFiles, context }) {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
if (contentWritten) {
|
|
68
|
-
|
|
68
|
+
// Touch the candidates file so Vite's CSS pipeline re-runs Tailwind —
|
|
69
|
+
// globals.css imports it, putting it in the dev module graph.
|
|
70
|
+
const candidatesPath = path.join(context.directories.build, 'tailwind-candidates.css');
|
|
71
|
+
fs.writeFileSync(
|
|
72
|
+
candidatesPath,
|
|
73
|
+
`/* Generated by Lowdefy build — rewritten on page changes to trigger CSS recompilation */\n/* ${Date.now()} */\n`
|
|
74
|
+
);
|
|
69
75
|
}
|
|
70
76
|
return contentWritten;
|
|
71
77
|
}
|
|
@@ -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 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;
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
});
|
|
@@ -51,7 +51,6 @@ function lowdefyBuildWatcher(context) {
|
|
|
51
51
|
|
|
52
52
|
if (isSkeletonChange) {
|
|
53
53
|
await context.lowdefyBuild();
|
|
54
|
-
await context.compileCss();
|
|
55
54
|
} else {
|
|
56
55
|
const invalidatePath = path.join(context.directories.build, 'invalidatePages');
|
|
57
56
|
fs.writeFileSync(invalidatePath, String(Date.now()));
|
|
@@ -56,7 +56,6 @@ function moduleBuildWatcher(context) {
|
|
|
56
56
|
: 'Module skeleton files changed, running shallow rebuild.'
|
|
57
57
|
);
|
|
58
58
|
await context.lowdefyBuild();
|
|
59
|
-
await context.compileCss();
|
|
60
59
|
} else {
|
|
61
60
|
const invalidatePath = path.join(context.directories.build, 'invalidatePages');
|
|
62
61
|
fs.writeFileSync(invalidatePath, String(Date.now()));
|
|
@@ -22,25 +22,20 @@ import setupWatcher from '../utils/setupWatcher.mjs';
|
|
|
22
22
|
|
|
23
23
|
const hashes = {};
|
|
24
24
|
|
|
25
|
+
// Replaces nextBuildWatcher. Only files the server reads at startup are
|
|
26
|
+
// tracked — a change requires a server restart for a fresh ESM module cache.
|
|
27
|
+
// Client-side artifacts (blocks.js, operators/client.js, globals.css, ...)
|
|
28
|
+
// are watched by Vite itself and hot-replaced without a restart.
|
|
25
29
|
const trackedFiles = [
|
|
26
30
|
'build/app.json',
|
|
27
31
|
'build/auth.json',
|
|
28
32
|
'build/config.json',
|
|
29
|
-
'build/plugins/actions.js',
|
|
30
33
|
'build/plugins/auth/adapters.js',
|
|
31
34
|
'build/plugins/auth/callbacks.js',
|
|
32
35
|
'build/plugins/auth/events.js',
|
|
33
36
|
'build/plugins/auth/providers.js',
|
|
34
|
-
'build/plugins/blocks.js',
|
|
35
37
|
'build/plugins/connections.js',
|
|
36
|
-
'build/plugins/icons.js',
|
|
37
|
-
'build/plugins/operators/client.js',
|
|
38
|
-
'build/plugins/operators/clientJsMap.js',
|
|
39
38
|
'build/plugins/operators/server.js',
|
|
40
|
-
'build/plugins/operators/serverJsMap.js',
|
|
41
|
-
'build/plugins/styles.css',
|
|
42
|
-
'build/globals.css',
|
|
43
|
-
'public/styles.css',
|
|
44
39
|
'package.json',
|
|
45
40
|
];
|
|
46
41
|
|
|
@@ -61,8 +56,8 @@ async function sha1(filePath) {
|
|
|
61
56
|
.digest('base64');
|
|
62
57
|
}
|
|
63
58
|
|
|
64
|
-
async function
|
|
65
|
-
// Initialize hashes so that
|
|
59
|
+
async function serverArtifactWatcher(context) {
|
|
60
|
+
// Initialize hashes so that the server does not restart the first time
|
|
66
61
|
// Lowdefy build is run.
|
|
67
62
|
await Promise.all(
|
|
68
63
|
trackedFiles.map(async (filePath) => {
|
|
@@ -72,21 +67,21 @@ async function nextBuildWatcher(context) {
|
|
|
72
67
|
|
|
73
68
|
const callback = async () => {
|
|
74
69
|
let install = false;
|
|
75
|
-
let
|
|
70
|
+
let restart = false;
|
|
76
71
|
await Promise.all(
|
|
77
72
|
trackedFiles.map(async (filePath) => {
|
|
78
73
|
const hash = await sha1(filePath);
|
|
79
74
|
if (hashes[filePath] === hash) {
|
|
80
75
|
return;
|
|
81
76
|
}
|
|
82
|
-
|
|
77
|
+
restart = true;
|
|
83
78
|
if (filePath.endsWith('package.json')) {
|
|
84
79
|
install = true;
|
|
85
80
|
}
|
|
86
81
|
hashes[filePath] = hash;
|
|
87
82
|
})
|
|
88
83
|
);
|
|
89
|
-
if (!
|
|
84
|
+
if (!restart) {
|
|
90
85
|
context.logger.info({ spin: 'succeed' }, 'Reloaded app.');
|
|
91
86
|
return;
|
|
92
87
|
}
|
|
@@ -95,8 +90,8 @@ async function nextBuildWatcher(context) {
|
|
|
95
90
|
if (install) {
|
|
96
91
|
context.logger.warn('Plugin dependencies have changed and will be reinstalled.');
|
|
97
92
|
await context.installPlugins();
|
|
98
|
-
// Rebuild Lowdefy artifacts (blocks.js, icons.js,
|
|
99
|
-
// so newly installed packages are included in the
|
|
93
|
+
// Rebuild Lowdefy artifacts (blocks.js, icons.js, connections.js, etc.)
|
|
94
|
+
// so newly installed packages are included in the plugin imports.
|
|
100
95
|
await context.lowdefyBuild();
|
|
101
96
|
// Re-hash all tracked files to avoid detecting our own build output
|
|
102
97
|
// changes as new changes on the next watcher callback.
|
|
@@ -106,8 +101,6 @@ async function nextBuildWatcher(context) {
|
|
|
106
101
|
})
|
|
107
102
|
);
|
|
108
103
|
}
|
|
109
|
-
await context.nextBuild();
|
|
110
|
-
await context.compileCss();
|
|
111
104
|
context.restartServer();
|
|
112
105
|
};
|
|
113
106
|
|
|
@@ -115,8 +108,13 @@ async function nextBuildWatcher(context) {
|
|
|
115
108
|
callback,
|
|
116
109
|
context,
|
|
117
110
|
watchDotfiles: true,
|
|
118
|
-
watchPaths: [
|
|
111
|
+
watchPaths: [
|
|
112
|
+
path.join(context.directories.server, 'package.json'),
|
|
113
|
+
...trackedFiles
|
|
114
|
+
.filter((filePath) => filePath.startsWith('build/'))
|
|
115
|
+
.map((filePath) => path.join(context.directories.server, filePath)),
|
|
116
|
+
],
|
|
119
117
|
});
|
|
120
118
|
}
|
|
121
119
|
|
|
122
|
-
export default
|
|
120
|
+
export default serverArtifactWatcher;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/server-dev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -28,81 +28,95 @@
|
|
|
28
28
|
"files": [
|
|
29
29
|
"lib/*",
|
|
30
30
|
"manager/*",
|
|
31
|
-
"pages/*",
|
|
32
31
|
"public_default/*",
|
|
33
|
-
"next.config.js",
|
|
34
32
|
"package.original.json",
|
|
35
33
|
".eslintrc.yaml",
|
|
36
|
-
".npmrc"
|
|
34
|
+
".npmrc",
|
|
35
|
+
"src/*",
|
|
36
|
+
"client/*",
|
|
37
|
+
"vite.config.js",
|
|
38
|
+
"postcss.config.cjs"
|
|
37
39
|
],
|
|
38
40
|
"dependencies": {
|
|
39
|
-
"@lowdefy/actions-core": "5.5.1",
|
|
40
|
-
"@lowdefy/api": "5.5.1",
|
|
41
|
-
"@lowdefy/block-utils": "5.5.1",
|
|
42
|
-
"@lowdefy/blocks-aggrid": "5.5.1",
|
|
43
|
-
"@lowdefy/blocks-antd": "5.5.1",
|
|
44
|
-
"@lowdefy/blocks-antd-x": "5.5.1",
|
|
45
|
-
"@lowdefy/blocks-basic": "5.5.1",
|
|
46
|
-
"@lowdefy/blocks-echarts": "5.5.1",
|
|
47
|
-
"@lowdefy/blocks-loaders": "5.5.1",
|
|
48
|
-
"@lowdefy/blocks-markdown": "5.5.1",
|
|
49
|
-
"@lowdefy/blocks-tiptap": "5.5.1",
|
|
50
|
-
"@lowdefy/build": "5.5.1",
|
|
51
|
-
"@lowdefy/client": "5.5.1",
|
|
52
|
-
"@lowdefy/connection-axios-http": "5.5.1",
|
|
53
|
-
"@lowdefy/engine": "5.5.1",
|
|
54
|
-
"@lowdefy/errors": "5.5.1",
|
|
55
|
-
"@lowdefy/helpers": "5.5.1",
|
|
56
|
-
"@lowdefy/layout": "5.5.1",
|
|
57
|
-
"@lowdefy/logger": "5.5.1",
|
|
58
|
-
"@lowdefy/node-utils": "5.5.1",
|
|
59
|
-
"@lowdefy/operators-change-case": "5.5.1",
|
|
60
|
-
"@lowdefy/operators-dayjs": "5.5.1",
|
|
61
|
-
"@lowdefy/operators-diff": "5.5.1",
|
|
62
|
-
"@lowdefy/operators-js": "5.5.1",
|
|
63
|
-
"@lowdefy/operators-mql": "5.5.1",
|
|
64
|
-
"@lowdefy/operators-nunjucks": "5.5.1",
|
|
65
|
-
"@lowdefy/operators-uuid": "5.5.1",
|
|
66
|
-
"@lowdefy/operators-yaml": "5.5.1",
|
|
67
|
-
"@lowdefy/plugin-next-auth": "5.5.1",
|
|
68
41
|
"@ant-design/cssinjs": "2.1.2",
|
|
69
42
|
"@ant-design/x": "2.7.0",
|
|
43
|
+
"@auth/core": "0.41.2",
|
|
44
|
+
"@hono/auth-js": "1.1.1",
|
|
45
|
+
"@hono/mcp": "0.3.0",
|
|
46
|
+
"@hono/node-server": "2.0.4",
|
|
47
|
+
"@hono/vite-dev-server": "0.26.0",
|
|
48
|
+
"@lowdefy/actions-core": "6.0.0",
|
|
49
|
+
"@lowdefy/api": "6.0.0",
|
|
50
|
+
"@lowdefy/block-utils": "6.0.0",
|
|
51
|
+
"@lowdefy/blocks-aggrid": "6.0.0",
|
|
52
|
+
"@lowdefy/blocks-antd": "6.0.0",
|
|
53
|
+
"@lowdefy/blocks-antd-x": "6.0.0",
|
|
54
|
+
"@lowdefy/blocks-basic": "6.0.0",
|
|
55
|
+
"@lowdefy/blocks-echarts": "6.0.0",
|
|
56
|
+
"@lowdefy/blocks-loaders": "6.0.0",
|
|
57
|
+
"@lowdefy/blocks-markdown": "6.0.0",
|
|
58
|
+
"@lowdefy/blocks-tiptap": "6.0.0",
|
|
59
|
+
"@lowdefy/build": "6.0.0",
|
|
60
|
+
"@lowdefy/client": "6.0.0",
|
|
61
|
+
"@lowdefy/connection-axios-http": "6.0.0",
|
|
62
|
+
"@lowdefy/docs-content": "6.0.0",
|
|
63
|
+
"@lowdefy/engine": "6.0.0",
|
|
64
|
+
"@lowdefy/errors": "6.0.0",
|
|
65
|
+
"@lowdefy/helpers": "6.0.0",
|
|
66
|
+
"@lowdefy/layout": "6.0.0",
|
|
67
|
+
"@lowdefy/logger": "6.0.0",
|
|
68
|
+
"@lowdefy/node-utils": "6.0.0",
|
|
69
|
+
"@lowdefy/operators-change-case": "6.0.0",
|
|
70
|
+
"@lowdefy/operators-dayjs": "6.0.0",
|
|
71
|
+
"@lowdefy/operators-diff": "6.0.0",
|
|
72
|
+
"@lowdefy/operators-js": "6.0.0",
|
|
73
|
+
"@lowdefy/operators-mql": "6.0.0",
|
|
74
|
+
"@lowdefy/operators-nunjucks": "6.0.0",
|
|
75
|
+
"@lowdefy/operators-uuid": "6.0.0",
|
|
76
|
+
"@lowdefy/operators-yaml": "6.0.0",
|
|
77
|
+
"@lowdefy/plugin-next-auth": "6.0.0",
|
|
78
|
+
"@lowdefy/websockets-core": "6.0.0",
|
|
79
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
80
|
+
"@tailwindcss/postcss": "4.3.1",
|
|
81
|
+
"@vitejs/plugin-react": "6.0.2",
|
|
70
82
|
"antd": "6.3.1",
|
|
71
|
-
"dayjs": "1.11.19",
|
|
72
83
|
"chokidar": "3.5.3",
|
|
84
|
+
"dayjs": "1.11.20",
|
|
73
85
|
"dotenv": "16.3.1",
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"postcss": "8.5.6",
|
|
77
|
-
"tailwindcss": "4.2.1",
|
|
78
|
-
"next-auth": "4.24.10",
|
|
86
|
+
"hono": "4.12.25",
|
|
87
|
+
"html-to-image": "1.11.13",
|
|
79
88
|
"opener": "1.5.2",
|
|
80
|
-
"pino": "
|
|
89
|
+
"pino": "10.3.1",
|
|
90
|
+
"playwright-core": "1.59.1",
|
|
91
|
+
"postcss": "8.5.6",
|
|
81
92
|
"process": "0.11.10",
|
|
82
93
|
"react": "18.2.0",
|
|
83
94
|
"react-dom": "18.2.0",
|
|
84
95
|
"react-icons": "5.6.0",
|
|
85
96
|
"swr": "2.2.4",
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
97
|
+
"tailwindcss": "4.3.1",
|
|
98
|
+
"tinykeys": "3.0.0",
|
|
99
|
+
"uuid": "14.0.0",
|
|
100
|
+
"vite": "8.0.16",
|
|
101
|
+
"ws": "8.18.0",
|
|
102
|
+
"yaml": "2.9.0",
|
|
103
|
+
"yargs": "18.0.0",
|
|
104
|
+
"zod": "3.25.76"
|
|
89
105
|
},
|
|
90
106
|
"devDependencies": {
|
|
91
|
-
"@next/eslint-plugin-next": "16.1.6",
|
|
92
107
|
"jest": "28.1.3",
|
|
93
108
|
"webpack": "5.94.0"
|
|
94
109
|
},
|
|
95
110
|
"engines": {
|
|
96
|
-
"node": ">=
|
|
111
|
+
"node": ">=22"
|
|
97
112
|
},
|
|
98
113
|
"publishConfig": {
|
|
99
114
|
"access": "public"
|
|
100
115
|
},
|
|
116
|
+
"type": "module",
|
|
101
117
|
"scripts": {
|
|
102
118
|
"build": "cp package.json package.original.json || copy package.json package.original.json",
|
|
103
119
|
"start": "node manager/run.mjs",
|
|
104
|
-
"lint": "next lint",
|
|
105
|
-
"next": "next",
|
|
106
120
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
|
107
121
|
}
|
|
108
122
|
}
|