@lowdefy/server-dev 5.6.0 → 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.
Files changed (214) hide show
  1. package/{pages/_app.js → client/App.jsx} +21 -33
  2. package/client/DevStreamContext.js +30 -0
  3. package/client/Inspector.jsx +226 -0
  4. package/{lib/client/Page.js → client/Page.jsx} +4 -8
  5. package/client/Reload.jsx +85 -0
  6. package/client/Routing.jsx +117 -0
  7. package/client/feedback/FeedbackMount.jsx +83 -0
  8. package/client/feedback/FeedbackOverlay.jsx +901 -0
  9. package/client/feedback/captureTabScreenshot.js +84 -0
  10. package/client/feedback/copyToClipboard.js +45 -0
  11. package/client/feedback/drawAnnotationsSvg.js +119 -0
  12. package/client/feedback/elementInspect.js +99 -0
  13. package/client/feedback/feedbackStyles.js +301 -0
  14. package/client/feedback/pinResponsiveImages.js +59 -0
  15. package/client/feedback/sendFeedback.js +39 -0
  16. package/client/feedback/useFeedbackToggle.js +70 -0
  17. package/client/main.jsx +42 -0
  18. package/client/openInEditor/OpenInEditorListener.jsx +268 -0
  19. package/client/openInEditor/findBlockLocation.js +51 -0
  20. package/lib/build/app.js +8 -1
  21. package/lib/build/appMeta.js +8 -1
  22. package/lib/build/auth.js +8 -1
  23. package/lib/build/config.js +8 -1
  24. package/lib/build/i18n.js +8 -1
  25. package/lib/build/logger.js +8 -1
  26. package/lib/build/theme.js +8 -1
  27. package/lib/client/auth/{Auth.js → Auth.jsx} +11 -2
  28. package/lib/client/auth/{AuthConfigured.js → AuthConfigured.jsx} +23 -10
  29. package/lib/client/setPageId.js +6 -5
  30. package/lib/client/utils/useMutateCache.js +14 -1
  31. package/lib/client/utils/usePageConfig.js +45 -43
  32. package/lib/client/utils/usePageConfig.test.mjs +62 -0
  33. package/lib/docs/captureAnnotatedScreenshot.js +88 -0
  34. package/lib/docs/checkpointPaths.js +91 -0
  35. package/lib/docs/checkpointStore.js +240 -0
  36. package/lib/docs/checkpointToMocks.js +65 -0
  37. package/lib/docs/clientErrorStore.js +36 -0
  38. package/lib/docs/configCheckpoints.test.mjs +156 -0
  39. package/lib/docs/createConfigCheckpoint.js +92 -0
  40. package/lib/docs/createDocsMcpServer.js +531 -0
  41. package/lib/docs/createDocsMcpServer.test.mjs +141 -0
  42. package/lib/docs/devMockRegistry.js +68 -0
  43. package/lib/docs/docs.test.mjs +448 -0
  44. package/lib/docs/enrichFeedback.js +71 -0
  45. package/lib/docs/evalOperator.js +47 -0
  46. package/lib/docs/evalOperator.test.mjs +157 -0
  47. package/lib/docs/evalOperatorHeadless.js +87 -0
  48. package/lib/docs/evalOperatorHeadless.test.mjs +72 -0
  49. package/lib/docs/evalOperatorInTab.js +48 -0
  50. package/lib/docs/findConfig.js +260 -0
  51. package/lib/docs/formatFeedback.js +121 -0
  52. package/lib/docs/formatFeedback.test.mjs +204 -0
  53. package/lib/docs/getAppMap.js +180 -0
  54. package/lib/docs/getBrowser.js +127 -0
  55. package/lib/docs/getBrowser.test.mjs +122 -0
  56. package/lib/docs/getBuildStatus.js +37 -0
  57. package/lib/docs/getCoreDoc.js +63 -0
  58. package/lib/docs/getDocsManifest.js +40 -0
  59. package/lib/docs/getExamples.js +58 -0
  60. package/lib/docs/getOverview.js +115 -0
  61. package/lib/docs/getPageConfig.js +53 -0
  62. package/lib/docs/getPluginDoc.js +55 -0
  63. package/lib/docs/getSchema.js +65 -0
  64. package/lib/docs/inspectState.js +47 -0
  65. package/lib/docs/inspectState.test.mjs +140 -0
  66. package/lib/docs/inspectStateFromTab.js +40 -0
  67. package/lib/docs/inspectStateHeadless.js +84 -0
  68. package/lib/docs/inspectStateHeadless.test.mjs +60 -0
  69. package/lib/docs/isWriteRequestsAllowed.js +50 -0
  70. package/lib/docs/listConfigCheckpoints.js +55 -0
  71. package/lib/docs/listPlugins.js +80 -0
  72. package/lib/docs/listTypes.js +105 -0
  73. package/lib/docs/loadState.js +152 -0
  74. package/lib/docs/mapPageBuildErrors.js +28 -0
  75. package/lib/docs/normalizeTypeKind.js +40 -0
  76. package/{pages/api/endpoints/[...endpointId].js → lib/docs/readBuildArtifact.js} +15 -12
  77. package/lib/docs/readPageArtifact.js +26 -0
  78. package/lib/docs/resolvePluginDir.js +49 -0
  79. package/lib/docs/resolveSource.js +48 -0
  80. package/lib/docs/resolveSource.test.mjs +100 -0
  81. package/lib/docs/revertConfigCheckpoint.js +73 -0
  82. package/lib/docs/runRequest.js +141 -0
  83. package/lib/docs/saveAnnotatedScreenshot.js +43 -0
  84. package/lib/docs/scaffoldPage.js +75 -0
  85. package/lib/docs/scaffoldPage.test.mjs +97 -0
  86. package/lib/docs/screenshotPage.js +110 -0
  87. package/lib/docs/screenshotPage.test.mjs +59 -0
  88. package/lib/docs/screenshotPageClip.test.mjs +102 -0
  89. package/lib/docs/searchDocs.js +67 -0
  90. package/lib/docs/setupTestFixtures.mjs +335 -0
  91. package/lib/docs/snapshotState.js +59 -0
  92. package/lib/docs/stateCheckpoints.test.mjs +366 -0
  93. package/lib/docs/tabAvailable.js +28 -0
  94. package/lib/docs/tabChannel.js +119 -0
  95. package/lib/docs/tabChannel.test.mjs +130 -0
  96. package/lib/server/auth/{getAuthOptions.js → getAuthConfig.js} +7 -4
  97. package/lib/server/auth/getDevSession.js +70 -0
  98. package/lib/server/auth/getDevSession.test.mjs +138 -0
  99. package/lib/server/auth/getHeadlessUser.js +40 -0
  100. package/lib/server/auth/{getMockSession.js → getMockUser.js} +8 -21
  101. package/lib/server/auth/headlessUser.js +29 -0
  102. package/lib/server/auth/resolveHeadlessUser.js +38 -0
  103. package/lib/server/auth/resolveHeadlessUser.test.mjs +78 -0
  104. package/lib/server/auth/session.js +39 -0
  105. package/lib/server/auth/strategies.js +47 -0
  106. package/lib/server/createLowdefyContext.js +122 -0
  107. package/lib/server/getPageJitEnrichment.test.mjs +105 -0
  108. package/lib/server/jitPageBuilder.js +125 -12
  109. package/lib/server/log/createHandleError.test.mjs +126 -0
  110. package/manager/getContext.mjs +3 -7
  111. package/manager/processes/initialBuild.mjs +0 -2
  112. package/manager/processes/installPlugins.mjs +19 -11
  113. package/manager/processes/lowdefyBuild.mjs +29 -7
  114. package/manager/processes/lowdefyBuild.test.mjs +102 -0
  115. package/manager/processes/readDotEnv.mjs +13 -1
  116. package/manager/processes/shutdownServer.mjs +6 -6
  117. package/manager/processes/startProxy.mjs +160 -0
  118. package/manager/processes/startProxy.test.mjs +102 -0
  119. package/manager/processes/startServer.mjs +33 -16
  120. package/manager/processes/startWatchers.mjs +2 -2
  121. package/manager/processes/warnAuthUrlPortMismatch.mjs +47 -0
  122. package/manager/processes/warnAuthUrlPortMismatch.test.mjs +93 -0
  123. package/manager/run.mjs +50 -0
  124. package/manager/utils/createCustomPluginMessagesMap.mjs +8 -1
  125. package/manager/utils/createCustomPluginTypesMap.mjs +1 -0
  126. package/manager/utils/formatNoticeBox.mjs +30 -0
  127. package/manager/utils/{getNextBin.mjs → getViteBin.mjs} +7 -10
  128. package/manager/utils/updatePageTailwindCss.mjs +7 -1
  129. package/manager/utils/writeBuildStatus.mjs +39 -0
  130. package/manager/utils/writeBuildStatus.test.mjs +76 -0
  131. package/manager/watchers/lowdefyBuildWatcher.mjs +0 -1
  132. package/manager/watchers/moduleBuildWatcher.mjs +0 -1
  133. package/manager/watchers/{nextBuildWatcher.mjs → serverArtifactWatcher.mjs} +18 -20
  134. package/package.json +61 -47
  135. package/package.original.json +64 -50
  136. package/postcss.config.cjs +1 -0
  137. package/src/app.js +175 -0
  138. package/src/html/renderDevPage.js +86 -0
  139. package/src/lib/getPathSegments.js +25 -0
  140. package/src/lib/safeScriptJson.js +38 -0
  141. package/src/middleware/apiContext.js +32 -0
  142. package/src/middleware/errorHandler.js +48 -0
  143. package/src/middleware/errorHandler.test.mjs +235 -0
  144. package/src/routes/agent.js +64 -0
  145. package/src/routes/apiPage.js +37 -0
  146. package/src/routes/auth.js +49 -0
  147. package/src/routes/auth.test.mjs +84 -0
  148. package/src/routes/clientError.js +57 -0
  149. package/src/routes/cron.js +47 -0
  150. package/src/routes/cronForward.js +47 -0
  151. package/src/routes/detached.js +47 -0
  152. package/src/routes/devInspect.js +111 -0
  153. package/src/routes/devInspect.test.mjs +119 -0
  154. package/{pages/[[...pageId]].js → src/routes/devTools.js} +4 -2
  155. package/{pages/404.js → src/routes/docs/appMap.js} +6 -2
  156. package/{pages/api/dev-tools.js → src/routes/docs/buildStatus.js} +5 -4
  157. package/src/routes/docs/checkpointsCreate.js +28 -0
  158. package/src/routes/docs/checkpointsList.js +23 -0
  159. package/{pages/api/icons/dynamic.js → src/routes/docs/checkpointsRevert.js} +11 -12
  160. package/src/routes/docs/content.js +31 -0
  161. package/src/routes/docs/evalOperator.js +56 -0
  162. package/src/routes/docs/examples.js +33 -0
  163. package/src/routes/docs/find.js +30 -0
  164. package/src/routes/docs/index.js +23 -0
  165. package/src/routes/docs/inspectState.js +44 -0
  166. package/src/routes/docs/loadState.js +49 -0
  167. package/src/routes/docs/mcp.js +30 -0
  168. package/src/routes/docs/pageConfig.js +36 -0
  169. package/src/routes/docs/parseUserParam.js +52 -0
  170. package/src/routes/docs/parseUserParam.test.mjs +45 -0
  171. package/src/routes/docs/pluginDoc.js +33 -0
  172. package/src/routes/docs/plugins.js +23 -0
  173. package/src/routes/docs/runRequest.js +36 -0
  174. package/{lib/server/auth/getServerSession.js → src/routes/docs/schema.js} +17 -15
  175. package/src/routes/docs/screenshot.js +72 -0
  176. package/src/routes/docs/search.js +27 -0
  177. package/src/routes/docs/snapshotState.js +36 -0
  178. package/src/routes/docs/stateCheckpointsList.js +26 -0
  179. package/src/routes/docs/types.js +33 -0
  180. package/src/routes/endpoints.js +71 -0
  181. package/src/routes/feedback.js +110 -0
  182. package/src/routes/feedback.test.mjs +204 -0
  183. package/src/routes/jitPage.js +86 -0
  184. package/src/routes/mcp.js +34 -0
  185. package/{pages/api → src/routes}/ping.js +4 -2
  186. package/src/routes/reload.js +79 -0
  187. package/src/routes/request.js +74 -0
  188. package/src/routes/request.test.mjs +124 -0
  189. package/{pages/api → src/routes}/root.js +4 -4
  190. package/src/routes/usage.js +46 -0
  191. package/src/routes/websocket.js +33 -0
  192. package/src/websocket/devWebSocket.js +78 -0
  193. package/vite.config.js +111 -0
  194. package/.eslintrc.yaml +0 -1
  195. package/lib/client/App.js +0 -80
  196. package/lib/client/Reload.js +0 -60
  197. package/lib/server/apiWrapper.js +0 -109
  198. package/lib/server/compileCss.js +0 -39
  199. package/manager/processes/compileCss.mjs +0 -54
  200. package/manager/processes/nextBuild.mjs +0 -50
  201. package/next.config.js +0 -25
  202. package/pages/_document.js +0 -109
  203. package/pages/api/agent/[...path].js +0 -86
  204. package/pages/api/auth/[...nextauth].js +0 -48
  205. package/pages/api/client-error.js +0 -45
  206. package/pages/api/js/[env].js +0 -42
  207. package/pages/api/page/[...pageId].js +0 -74
  208. package/pages/api/reload.js +0 -53
  209. package/pages/api/request/[...path].js +0 -41
  210. /package/lib/client/{BuildErrorPage.js → BuildErrorPage.jsx} +0 -0
  211. /package/lib/client/{BuildingPage.js → BuildingPage.jsx} +0 -0
  212. /package/lib/client/{ErrorBar.js → ErrorBar.jsx} +0 -0
  213. /package/lib/client/{InstallingPluginsPage.js → InstallingPluginsPage.jsx} +0 -0
  214. /package/lib/client/{RestartingPage.js → RestartingPage.jsx} +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/server-dev",
3
- "version": "5.6.0",
3
+ "version": "6.0.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -28,82 +28,96 @@
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
  "scripts": {
39
41
  "build": "cp package.json package.original.json || copy package.json package.original.json",
42
+ "prepublishOnly": "pnpm build",
40
43
  "start": "node manager/run.mjs",
41
- "lint": "next lint",
42
- "next": "next",
43
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
44
- "prepublishOnly": "pnpm build"
44
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
45
45
  },
46
46
  "dependencies": {
47
- "@lowdefy/actions-core": "5.6.0",
48
- "@lowdefy/api": "5.6.0",
49
- "@lowdefy/block-utils": "5.6.0",
50
- "@lowdefy/blocks-aggrid": "5.6.0",
51
- "@lowdefy/blocks-antd": "5.6.0",
52
- "@lowdefy/blocks-antd-x": "5.6.0",
53
- "@lowdefy/blocks-basic": "5.6.0",
54
- "@lowdefy/blocks-echarts": "5.6.0",
55
- "@lowdefy/blocks-loaders": "5.6.0",
56
- "@lowdefy/blocks-markdown": "5.6.0",
57
- "@lowdefy/blocks-tiptap": "5.6.0",
58
- "@lowdefy/build": "5.6.0",
59
- "@lowdefy/client": "5.6.0",
60
- "@lowdefy/connection-axios-http": "5.6.0",
61
- "@lowdefy/engine": "5.6.0",
62
- "@lowdefy/errors": "5.6.0",
63
- "@lowdefy/helpers": "5.6.0",
64
- "@lowdefy/layout": "5.6.0",
65
- "@lowdefy/logger": "5.6.0",
66
- "@lowdefy/node-utils": "5.6.0",
67
- "@lowdefy/operators-change-case": "5.6.0",
68
- "@lowdefy/operators-dayjs": "5.6.0",
69
- "@lowdefy/operators-diff": "5.6.0",
70
- "@lowdefy/operators-js": "5.6.0",
71
- "@lowdefy/operators-mql": "5.6.0",
72
- "@lowdefy/operators-nunjucks": "5.6.0",
73
- "@lowdefy/operators-uuid": "5.6.0",
74
- "@lowdefy/operators-yaml": "5.6.0",
75
- "@lowdefy/plugin-next-auth": "5.6.0",
76
47
  "@ant-design/cssinjs": "2.1.2",
77
48
  "@ant-design/x": "2.7.0",
49
+ "@auth/core": "0.41.2",
50
+ "@hono/auth-js": "1.1.1",
51
+ "@hono/mcp": "0.3.0",
52
+ "@hono/node-server": "2.0.4",
53
+ "@hono/vite-dev-server": "0.26.0",
54
+ "@lowdefy/actions-core": "6.0.0",
55
+ "@lowdefy/api": "6.0.0",
56
+ "@lowdefy/block-utils": "6.0.0",
57
+ "@lowdefy/blocks-aggrid": "6.0.0",
58
+ "@lowdefy/blocks-antd": "6.0.0",
59
+ "@lowdefy/blocks-antd-x": "6.0.0",
60
+ "@lowdefy/blocks-basic": "6.0.0",
61
+ "@lowdefy/blocks-echarts": "6.0.0",
62
+ "@lowdefy/blocks-loaders": "6.0.0",
63
+ "@lowdefy/blocks-markdown": "6.0.0",
64
+ "@lowdefy/blocks-tiptap": "6.0.0",
65
+ "@lowdefy/build": "6.0.0",
66
+ "@lowdefy/client": "6.0.0",
67
+ "@lowdefy/connection-axios-http": "6.0.0",
68
+ "@lowdefy/docs-content": "6.0.0",
69
+ "@lowdefy/engine": "6.0.0",
70
+ "@lowdefy/errors": "6.0.0",
71
+ "@lowdefy/helpers": "6.0.0",
72
+ "@lowdefy/layout": "6.0.0",
73
+ "@lowdefy/logger": "6.0.0",
74
+ "@lowdefy/node-utils": "6.0.0",
75
+ "@lowdefy/operators-change-case": "6.0.0",
76
+ "@lowdefy/operators-dayjs": "6.0.0",
77
+ "@lowdefy/operators-diff": "6.0.0",
78
+ "@lowdefy/operators-js": "6.0.0",
79
+ "@lowdefy/operators-mql": "6.0.0",
80
+ "@lowdefy/operators-nunjucks": "6.0.0",
81
+ "@lowdefy/operators-uuid": "6.0.0",
82
+ "@lowdefy/operators-yaml": "6.0.0",
83
+ "@lowdefy/plugin-next-auth": "6.0.0",
84
+ "@lowdefy/websockets-core": "6.0.0",
85
+ "@modelcontextprotocol/sdk": "1.29.0",
86
+ "@tailwindcss/postcss": "4.3.1",
87
+ "@vitejs/plugin-react": "6.0.2",
78
88
  "antd": "6.3.1",
79
- "dayjs": "1.11.19",
80
89
  "chokidar": "3.5.3",
90
+ "dayjs": "1.11.20",
81
91
  "dotenv": "16.3.1",
82
- "@tailwindcss/postcss": "4.2.1",
83
- "next": "16.1.6",
84
- "postcss": "8.5.6",
85
- "tailwindcss": "4.2.1",
86
- "next-auth": "4.24.10",
92
+ "hono": "4.12.25",
93
+ "html-to-image": "1.11.13",
87
94
  "opener": "1.5.2",
88
- "pino": "8.16.2",
95
+ "pino": "10.3.1",
96
+ "playwright-core": "1.59.1",
97
+ "postcss": "8.5.6",
89
98
  "process": "0.11.10",
90
99
  "react": "18.2.0",
91
100
  "react-dom": "18.2.0",
92
101
  "react-icons": "5.6.0",
93
102
  "swr": "2.2.4",
94
- "uuid": "13.0.0",
95
- "yaml": "2.3.4",
96
- "yargs": "17.7.2"
103
+ "tailwindcss": "4.3.1",
104
+ "tinykeys": "3.0.0",
105
+ "uuid": "14.0.0",
106
+ "vite": "8.0.16",
107
+ "ws": "8.18.0",
108
+ "yaml": "2.9.0",
109
+ "yargs": "18.0.0",
110
+ "zod": "3.25.76"
97
111
  },
98
112
  "devDependencies": {
99
- "@next/eslint-plugin-next": "16.1.6",
100
113
  "jest": "28.1.3",
101
114
  "webpack": "5.94.0"
102
115
  },
103
116
  "engines": {
104
- "node": ">=18"
117
+ "node": ">=22"
105
118
  },
106
119
  "publishConfig": {
107
120
  "access": "public"
108
- }
121
+ },
122
+ "type": "module"
109
123
  }
@@ -0,0 +1 @@
1
+ module.exports = { plugins: { '@tailwindcss/postcss': {} } };
package/src/app.js ADDED
@@ -0,0 +1,175 @@
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 { Hono } from 'hono';
18
+ import { bodyLimit } from 'hono/body-limit';
19
+ import { initAuthConfig } from '@hono/auth-js';
20
+ import { serveStatic } from '@hono/node-server/serve-static';
21
+
22
+ import agentHandler from './routes/agent.js';
23
+ import apiContext from './middleware/apiContext.js';
24
+ import authJson from '../lib/build/auth.js';
25
+ import authMiddleware from './routes/auth.js';
26
+ import clientErrorHandler from './routes/clientError.js';
27
+ import createErrorHandler from './middleware/errorHandler.js';
28
+ import createLogger from '../lib/server/log/createLogger.js';
29
+ import cronForwardHandler from './routes/cronForward.js';
30
+ import cronHandler from './routes/cron.js';
31
+ import detachedHandler from './routes/detached.js';
32
+ import devInspectHandler from './routes/devInspect.js';
33
+ import devToolsHandler from './routes/devTools.js';
34
+ import feedbackHandler from './routes/feedback.js';
35
+ import docsAppMapHandler from './routes/docs/appMap.js';
36
+ import docsBuildStatusHandler from './routes/docs/buildStatus.js';
37
+ import docsCheckpointsCreateHandler from './routes/docs/checkpointsCreate.js';
38
+ import docsCheckpointsListHandler from './routes/docs/checkpointsList.js';
39
+ import docsCheckpointsRevertHandler from './routes/docs/checkpointsRevert.js';
40
+ import docsContentHandler from './routes/docs/content.js';
41
+ import docsEvalOperatorHandler from './routes/docs/evalOperator.js';
42
+ import docsExamplesHandler from './routes/docs/examples.js';
43
+ import docsFindHandler from './routes/docs/find.js';
44
+ import docsIndexHandler from './routes/docs/index.js';
45
+ import docsInspectStateHandler from './routes/docs/inspectState.js';
46
+ import docsLoadStateHandler from './routes/docs/loadState.js';
47
+ import docsMcpHandler from './routes/docs/mcp.js';
48
+ import docsPageConfigHandler from './routes/docs/pageConfig.js';
49
+ import docsRunRequestHandler from './routes/docs/runRequest.js';
50
+ import docsSnapshotStateHandler from './routes/docs/snapshotState.js';
51
+ import docsStateCheckpointsListHandler from './routes/docs/stateCheckpointsList.js';
52
+ import docsPluginDocHandler from './routes/docs/pluginDoc.js';
53
+ import docsPluginsHandler from './routes/docs/plugins.js';
54
+ import docsSchemaHandler from './routes/docs/schema.js';
55
+ import docsScreenshotHandler from './routes/docs/screenshot.js';
56
+ import docsSearchHandler from './routes/docs/search.js';
57
+ import docsTypesHandler from './routes/docs/types.js';
58
+ import endpointsHandler from './routes/endpoints.js';
59
+ import getAuthConfig from '../lib/server/auth/getAuthConfig.js';
60
+ import jitPageHandler from './routes/jitPage.js';
61
+ import lowdefyConfig from '../lib/build/config.js';
62
+ import mcpHandler from './routes/mcp.js';
63
+ import pingHandler from './routes/ping.js';
64
+ import reloadHandler from './routes/reload.js';
65
+ import renderDevPage from './html/renderDevPage.js';
66
+ import requestHandler from './routes/request.js';
67
+ import rootHandler from './routes/root.js';
68
+ import usageHandler from './routes/usage.js';
69
+ import websocketHandler from './routes/websocket.js';
70
+
71
+ const basePath = lowdefyConfig.basePath ?? '';
72
+
73
+ // Dev Hono app — mounted into Vite via @hono/vite-dev-server (Vite owns HTTP
74
+ // and serves /client/* modules with HMR; everything else lands here).
75
+ // No compression in dev (parity with the old next.config compress: false,
76
+ // and SSE must stay unbuffered).
77
+ function createApp() {
78
+ const app = basePath ? new Hono().basePath(basePath) : new Hono();
79
+ const logger = createLogger({ server: 'lowdefy-dev' });
80
+
81
+ // No api context: SSE/health routes had no apiWrapper before.
82
+ app.get('/api/reload', reloadHandler);
83
+ app.get('/api/ping', pingHandler);
84
+ app.get('/api/dev-tools', devToolsHandler);
85
+ // Annotation helper: the in-page overlay (Cmd/Ctrl+/) POSTs annotation
86
+ // batches here and gets back the enriched agent-readable text, which the
87
+ // overlay copies to the clipboard. No api context needed.
88
+ // /lowdefy-feedback is a reserved page-path prefix in dev, like /lowdefy-docs.
89
+ app.post('/lowdefy-feedback', feedbackHandler);
90
+
91
+ // Auth config must be registered before the /lowdefy-docs routes: Hono
92
+ // middleware only applies to routes registered after it, and run-request/
93
+ // eval-operator build a full Lowdefy context whose getSession(c) reads the
94
+ // authConfig this middleware sets. It does not protect any route — it only
95
+ // makes the auth config available on the Hono context.
96
+ if (authJson.configured === true) {
97
+ app.use(
98
+ '*',
99
+ initAuthConfig(() => getAuthConfig({ logger }))
100
+ );
101
+ }
102
+
103
+ // Docs and MCP endpoint for AI coding agents — always on in dev. Serves
104
+ // schemas/examples/docs for every installed plugin (core and local) plus
105
+ // the extracted core docs (@lowdefy/docs-content). Mounted outside /api/*
106
+ // so it can't clash with user API endpoints; /lowdefy-docs is a reserved page
107
+ // prefix in dev. The handlers need no auth protection or api context —
108
+ // they read build artifacts and node_modules directly — but run-request
109
+ // and eval-operator read the caller's session, hence initAuthConfig above.
110
+ app.all('/lowdefy-docs/mcp', docsMcpHandler);
111
+ app.get('/lowdefy-docs', docsIndexHandler);
112
+ app.get('/lowdefy-docs/build-status', docsBuildStatusHandler);
113
+ app.get('/lowdefy-docs/page-config/:pageId', docsPageConfigHandler);
114
+ app.get('/lowdefy-docs/find/:id', docsFindHandler);
115
+ app.get('/lowdefy-docs/screenshot/:pageId', docsScreenshotHandler);
116
+ app.get('/lowdefy-docs/inspect-state/:pageId', docsInspectStateHandler);
117
+ app.post('/lowdefy-docs/eval-operator', docsEvalOperatorHandler);
118
+ app.post('/lowdefy-docs/run-request', docsRunRequestHandler);
119
+ app.get('/lowdefy-docs/app-map', docsAppMapHandler);
120
+ app.get('/lowdefy-docs/checkpoints', docsCheckpointsListHandler);
121
+ app.post('/lowdefy-docs/checkpoints', docsCheckpointsCreateHandler);
122
+ app.post('/lowdefy-docs/checkpoints/revert', docsCheckpointsRevertHandler);
123
+ app.get('/lowdefy-docs/state-checkpoints', docsStateCheckpointsListHandler);
124
+ app.post('/lowdefy-docs/state-checkpoints/snapshot', docsSnapshotStateHandler);
125
+ app.post('/lowdefy-docs/state-checkpoints/load', docsLoadStateHandler);
126
+ // Live-tab inspection channel: dev tabs (client/Inspector.jsx) answer
127
+ // targeted SSE events by posting results here; GET lists connected tabs
128
+ // and serves checkpoint parts for the ?_checkpoint bootstrap.
129
+ app.all('/api/dev-inspect', devInspectHandler);
130
+ app.all('/api/dev-inspect/*', devInspectHandler);
131
+ app.get('/lowdefy-docs/plugins', docsPluginsHandler);
132
+ app.get('/lowdefy-docs/schema/:kind/:type', docsSchemaHandler);
133
+ app.get('/lowdefy-docs/examples/:type', docsExamplesHandler);
134
+ app.get('/lowdefy-docs/search', docsSearchHandler);
135
+ app.get('/lowdefy-docs/plugin-doc/:package{.+}', docsPluginDocHandler);
136
+ app.get('/lowdefy-docs/content/:slug{.+}', docsContentHandler);
137
+ app.get('/lowdefy-docs/:kind', docsTypesHandler);
138
+
139
+ app.use('/api/*', apiContext());
140
+ app.use('/api/auth/*', authMiddleware());
141
+ app.get('/api/root', rootHandler);
142
+ app.get('/api/page/*', jitPageHandler);
143
+ app.all('/api/request/*', requestHandler);
144
+ // Endpoint payloads may carry base64 file content (emitFileContent + CallAPI);
145
+ // cap bodies at 10 MiB to match the agent route.
146
+ app.all('/api/endpoints/*', bodyLimit({ maxSize: 10 * 1024 * 1024 }), endpointsHandler);
147
+ app.get('/api/cron/*', cronHandler);
148
+ app.get('/api/cron-forward/*', cronForwardHandler);
149
+ app.post('/api/detached/*', detachedHandler);
150
+ app.all('/api/client-error', clientErrorHandler);
151
+ app.all('/api/usage', usageHandler);
152
+ app.all('/api/agent/*', bodyLimit({ maxSize: 10 * 1024 * 1024 }), agentHandler);
153
+ app.all('/api/mcp', bodyLimit({ maxSize: 10 * 1024 * 1024 }), mcpHandler);
154
+ app.get('/api/websocket', websocketHandler);
155
+
156
+ // User public assets (icons, images). Vite serves /client modules itself.
157
+ app.use(
158
+ '/*',
159
+ serveStatic({
160
+ root: './public',
161
+ rewriteRequestPath: basePath ? (path) => path.replace(basePath, '') : undefined,
162
+ })
163
+ );
164
+
165
+ // Every page path renders the same shell — the client fetches config and
166
+ // handles home/404 routing, exactly like the old dev pages router did.
167
+ app.get('/', (c) => renderDevPage(c, { basePath }));
168
+ app.get('/:rest{.+}', (c) => renderDevPage(c, { basePath }));
169
+
170
+ app.onError(createErrorHandler({ basePath, logger }));
171
+
172
+ return app;
173
+ }
174
+
175
+ export default createApp();
@@ -0,0 +1,86 @@
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 safeScriptJson from '../lib/safeScriptJson.js';
21
+
22
+ // Dev HTML shell — config-free: the client fetches root config and page
23
+ // config over the API (SWR), exactly like the old dev pages did. Theme and
24
+ // app config are read per request so a lowdefyBuild does not require a
25
+ // server restart for the pre-hydration values to update.
26
+ //
27
+ // @hono/vite-dev-server injects /@vite/client into this response; the
28
+ // react-refresh preamble must be inlined here for @vitejs/plugin-react.
29
+ const layerOrderScript = `(function(){var s=document.createElement("style");s.id="__lf-layer-order";s.textContent="@layer theme, base, antd, components, utilities;";document.head.prepend(s);new MutationObserver(function(){if(document.head.firstChild!==s)document.head.prepend(s)}).observe(document.head,{childList:true})})();`;
30
+
31
+ function readBuildJson(name) {
32
+ try {
33
+ return JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build', `${name}.json`), 'utf8'));
34
+ } catch {
35
+ return {};
36
+ }
37
+ }
38
+
39
+ function renderDevPage(c, { basePath = '' }) {
40
+ const themeConfig = readBuildJson('theme');
41
+ const appJson = readBuildJson('app');
42
+
43
+ const VALID_COLOR_MODES = ['system', 'light', 'dark'];
44
+ const configColorMode = VALID_COLOR_MODES.includes(themeConfig.darkMode)
45
+ ? themeConfig.darkMode
46
+ : 'system';
47
+ const darkBg = themeConfig?.antd?.darkToken?.colorBgLayout ?? '#000';
48
+ const lightBg = themeConfig?.antd?.lightToken?.colorBgLayout ?? '';
49
+
50
+ const darkModeScript = `(function(){var c=${safeScriptJson(
51
+ configColorMode
52
+ )};var db=${safeScriptJson(darkBg)};var lb=${safeScriptJson(
53
+ lightBg
54
+ )};var d;if(c==="dark")d=true;else if(c==="light")d=false;else{try{var p=localStorage.getItem("lowdefy_darkMode");if(p==="dark")d=true;else if(p==="light")d=false;else d=window.matchMedia("(prefers-color-scheme:dark)").matches}catch(e){d=window.matchMedia("(prefers-color-scheme:dark)").matches}}var bg=d?db:lb;document.documentElement.style.colorScheme=d?"dark":"light";if(bg)document.documentElement.style.backgroundColor=bg})();`;
55
+
56
+ const html = `<!DOCTYPE html>
57
+ <html class="lowdefy">
58
+ <head>
59
+ <meta charset="utf-8" />
60
+ <script>${layerOrderScript}</script>
61
+ <script>${darkModeScript}</script>
62
+ <link rel="manifest" href="${basePath}/manifest.webmanifest" />
63
+ <link rel="icon" type="image/svg+xml" href="${basePath}/icon.svg" />
64
+ <link rel="apple-touch-icon" href="${basePath}/apple-touch-icon.png" />
65
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
66
+ <script type="module">
67
+ import RefreshRuntime from '${basePath}/@react-refresh';
68
+ RefreshRuntime.injectIntoGlobalHook(window);
69
+ window.$RefreshReg$ = () => {};
70
+ window.$RefreshSig$ = () => (type) => type;
71
+ window.__vite_plugin_react_preamble_installed__ = true;
72
+ </script>
73
+ ${appJson.html?.appendHead ?? ''}
74
+ </head>
75
+ <body>
76
+ <div id="root"></div>
77
+ <script id="__LOWDEFY_CONFIG__" type="application/json">${safeScriptJson({ basePath })}</script>
78
+ ${appJson.html?.appendBody ?? ''}
79
+ <script type="module" src="${basePath}/client/main.jsx"></script>
80
+ </body>
81
+ </html>`;
82
+
83
+ return c.html(html);
84
+ }
85
+
86
+ export default renderDevPage;
@@ -0,0 +1,25 @@
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
+ // Splits the rest of a catch-all route into decoded segments, independent of
18
+ // any configured basePath. Mirrors the Next.js [...param] query arrays —
19
+ // nested ids (slashes in pageId or endpointId) are real.
20
+ function getPathSegments(c, prefix) {
21
+ const rest = c.req.path.split(prefix)[1] ?? '';
22
+ return rest.split('/').filter(Boolean).map(decodeURIComponent);
23
+ }
24
+
25
+ export default getPathSegments;
@@ -0,0 +1,38 @@
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
+ // Escape characters that could break out of the enclosing <script> tag or
18
+ // terminate a JS string literal. Used to defuse the js/bad-code-sanitization
19
+ // class of injection for values embedded into inline scripts and the
20
+ // application/json config script.
21
+ const SCRIPT_ESCAPES = {
22
+ '<': '\\u003C',
23
+ '>': '\\u003E',
24
+ '\b': '\\b',
25
+ '\f': '\\f',
26
+ '\n': '\\n',
27
+ '\r': '\\r',
28
+ '\t': '\\t',
29
+ '\0': '\\0',
30
+ '\u2028': '\\u2028',
31
+ '\u2029': '\\u2029',
32
+ };
33
+
34
+ function safeScriptJson(value) {
35
+ return JSON.stringify(value).replace(/[<>\b\f\n\r\t\0\u2028\u2029]/g, (c) => SCRIPT_ESCAPES[c]);
36
+ }
37
+
38
+ export default safeScriptJson;
@@ -0,0 +1,32 @@
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 createLowdefyContext from '../../lib/server/createLowdefyContext.js';
18
+
19
+ // Replaces lib/server/apiWrapper.js. Errors thrown by handlers are routed by
20
+ // Hono to the app-level error handler (src/middleware/errorHandler.js).
21
+ function apiContext() {
22
+ return async function apiContextMiddleware(c, next) {
23
+ if (c.get('lowdefyContext')) {
24
+ return next();
25
+ }
26
+ const context = await createLowdefyContext({ c });
27
+ c.set('lowdefyContext', context);
28
+ return next();
29
+ };
30
+ }
31
+
32
+ export default apiContext;
@@ -0,0 +1,48 @@
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 { redactErrorResponse } from '@lowdefy/api';
18
+
19
+ // Hono routes every handler error to the app-level error handler — upstream
20
+ // middleware try/catch never sees them. API routes get the serialized error
21
+ // JSON the old apiWrapper returned; page routes get a plain 500.
22
+ function createErrorHandler({ basePath = '', logger }) {
23
+ return async function errorHandler(error, c) {
24
+ const path = basePath ? c.req.path.replace(basePath, '') : c.req.path;
25
+ // Unauthenticated requests to protected endpoints are expected traffic -
26
+ // one warning line and a 401, skipping the structured error log so
27
+ // probing cannot flood it. Keys strictly on the error name.
28
+ if (error.name === 'AuthenticationError') {
29
+ logger.warn(`Unauthenticated request: ${c.req.method} ${c.req.path}`);
30
+ if (path.startsWith('/api/')) {
31
+ return c.json({ name: error.name, message: error.message }, 401);
32
+ }
33
+ return c.text('Unauthorized', 401);
34
+ }
35
+ const context = c.get('lowdefyContext');
36
+ if (context) {
37
+ await context.handleError(error);
38
+ } else {
39
+ logger.error(error);
40
+ }
41
+ if (path.startsWith('/api/')) {
42
+ return c.json(redactErrorResponse(context, error), 500);
43
+ }
44
+ return c.text('Internal Server Error', 500);
45
+ };
46
+ }
47
+
48
+ export default createErrorHandler;