@lowdefy/server-dev 0.0.0-experimental-20260827092002 → 0.0.0-experimental-20260827105525

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 (194) hide show
  1. package/.eslintrc.yaml +1 -0
  2. package/lib/build/app.js +1 -8
  3. package/lib/build/appMeta.js +1 -8
  4. package/lib/build/auth.js +1 -8
  5. package/lib/build/config.js +1 -8
  6. package/lib/build/i18n.js +1 -8
  7. package/lib/build/logger.js +1 -8
  8. package/lib/build/theme.js +1 -8
  9. package/lib/client/App.js +80 -0
  10. package/{client/Page.jsx → lib/client/Page.js} +5 -5
  11. package/{client/Reload.jsx → lib/client/Reload.js} +7 -5
  12. package/lib/client/auth/{Auth.jsx → Auth.js} +2 -11
  13. package/lib/client/auth/{AuthConfigured.jsx → AuthConfigured.js} +10 -23
  14. package/lib/client/setPageId.js +5 -6
  15. package/lib/client/utils/useMutateCache.js +1 -14
  16. package/lib/client/utils/usePageConfig.js +11 -24
  17. package/lib/server/{createLowdefyContext.js → apiWrapper.js} +58 -60
  18. package/lib/server/auth/{getAuthConfig.js → getAuthOptions.js} +4 -7
  19. package/lib/server/auth/{getMockUser.js → getMockSession.js} +21 -8
  20. package/{src/routes/docs/checkpointsRevert.js → lib/server/auth/getServerSession.js} +13 -11
  21. package/lib/server/compileCss.js +39 -0
  22. package/lib/server/jitPageBuilder.js +11 -36
  23. package/manager/getContext.mjs +7 -3
  24. package/manager/processes/compileCss.mjs +54 -0
  25. package/manager/processes/initialBuild.mjs +2 -0
  26. package/manager/processes/installPlugins.mjs +11 -19
  27. package/manager/processes/lowdefyBuild.mjs +7 -29
  28. package/manager/processes/nextBuild.mjs +50 -0
  29. package/manager/processes/readDotEnv.mjs +1 -13
  30. package/manager/processes/shutdownServer.mjs +6 -6
  31. package/manager/processes/startServer.mjs +7 -10
  32. package/manager/processes/startWatchers.mjs +2 -2
  33. package/manager/run.mjs +0 -41
  34. package/manager/utils/createCustomPluginMessagesMap.mjs +1 -8
  35. package/manager/utils/createCustomPluginTypesMap.mjs +0 -1
  36. package/manager/utils/{getViteBin.mjs → getNextBin.mjs} +10 -7
  37. package/manager/utils/updatePageTailwindCss.mjs +1 -7
  38. package/manager/watchers/lowdefyBuildWatcher.mjs +1 -0
  39. package/manager/watchers/moduleBuildWatcher.mjs +1 -0
  40. package/manager/watchers/{serverArtifactWatcher.mjs → nextBuildWatcher.mjs} +20 -18
  41. package/next.config.js +25 -0
  42. package/package.json +47 -61
  43. package/package.original.json +50 -64
  44. package/{src/routes/devTools.js → pages/404.js} +2 -4
  45. package/{src/routes/docs/appMap.js → pages/[[...pageId]].js} +2 -6
  46. package/{client/App.jsx → pages/_app.js} +33 -21
  47. package/pages/_document.js +107 -0
  48. package/pages/api/agent/[...path].js +86 -0
  49. package/pages/api/auth/[...nextauth].js +48 -0
  50. package/pages/api/client-error.js +45 -0
  51. package/{src/routes/docs/buildStatus.js → pages/api/dev-tools.js} +4 -5
  52. package/{lib/docs/clientErrorStore.js → pages/api/endpoints/[...endpointId].js} +11 -15
  53. package/{src/lib/serveBuildJs.js → pages/api/icons/dynamic.js} +12 -8
  54. package/{src/routes/jsEnv.js → pages/api/js/[env].js} +20 -8
  55. package/{src/routes/jitPage.js → pages/api/page/[...pageId].js} +23 -29
  56. package/{src/routes → pages/api}/ping.js +2 -4
  57. package/pages/api/reload.js +53 -0
  58. package/pages/api/request/[...path].js +41 -0
  59. package/{src/routes → pages/api}/root.js +4 -4
  60. package/client/Inspector.jsx +0 -206
  61. package/client/Routing.jsx +0 -106
  62. package/client/feedback/FeedbackMount.jsx +0 -83
  63. package/client/feedback/FeedbackOverlay.jsx +0 -901
  64. package/client/feedback/captureTabScreenshot.js +0 -84
  65. package/client/feedback/copyToClipboard.js +0 -45
  66. package/client/feedback/drawAnnotationsSvg.js +0 -119
  67. package/client/feedback/elementInspect.js +0 -99
  68. package/client/feedback/feedbackStyles.js +0 -301
  69. package/client/feedback/pinResponsiveImages.js +0 -59
  70. package/client/feedback/sendFeedback.js +0 -39
  71. package/client/feedback/useFeedbackToggle.js +0 -70
  72. package/client/main.jsx +0 -42
  73. package/client/openInEditor/OpenInEditorListener.jsx +0 -261
  74. package/client/openInEditor/findBlockLocation.js +0 -51
  75. package/lib/docs/captureAnnotatedScreenshot.js +0 -88
  76. package/lib/docs/checkpointPaths.js +0 -91
  77. package/lib/docs/checkpointStore.js +0 -234
  78. package/lib/docs/checkpointToMocks.js +0 -65
  79. package/lib/docs/configCheckpoints.test.mjs +0 -156
  80. package/lib/docs/createConfigCheckpoint.js +0 -92
  81. package/lib/docs/createDocsMcpServer.js +0 -506
  82. package/lib/docs/createDocsMcpServer.test.mjs +0 -123
  83. package/lib/docs/devMockRegistry.js +0 -68
  84. package/lib/docs/docs.test.mjs +0 -448
  85. package/lib/docs/enrichFeedback.js +0 -71
  86. package/lib/docs/evalOperator.js +0 -39
  87. package/lib/docs/evalOperator.test.mjs +0 -112
  88. package/lib/docs/evalOperatorHeadless.js +0 -87
  89. package/lib/docs/evalOperatorHeadless.test.mjs +0 -72
  90. package/lib/docs/evalOperatorInTab.js +0 -48
  91. package/lib/docs/findConfig.js +0 -260
  92. package/lib/docs/formatFeedback.js +0 -121
  93. package/lib/docs/formatFeedback.test.mjs +0 -204
  94. package/lib/docs/getAppMap.js +0 -180
  95. package/lib/docs/getBrowser.js +0 -115
  96. package/lib/docs/getBuildStatus.js +0 -37
  97. package/lib/docs/getCoreDoc.js +0 -63
  98. package/lib/docs/getDocsManifest.js +0 -40
  99. package/lib/docs/getExamples.js +0 -58
  100. package/lib/docs/getOverview.js +0 -115
  101. package/lib/docs/getPageConfig.js +0 -53
  102. package/lib/docs/getPluginDoc.js +0 -55
  103. package/lib/docs/getSchema.js +0 -65
  104. package/lib/docs/inspectState.js +0 -41
  105. package/lib/docs/inspectState.test.mjs +0 -91
  106. package/lib/docs/inspectStateFromTab.js +0 -40
  107. package/lib/docs/inspectStateHeadless.js +0 -84
  108. package/lib/docs/inspectStateHeadless.test.mjs +0 -60
  109. package/lib/docs/isWriteRequestsAllowed.js +0 -50
  110. package/lib/docs/listConfigCheckpoints.js +0 -55
  111. package/lib/docs/listPlugins.js +0 -80
  112. package/lib/docs/listTypes.js +0 -105
  113. package/lib/docs/loadState.js +0 -139
  114. package/lib/docs/mapPageBuildErrors.js +0 -28
  115. package/lib/docs/normalizeTypeKind.js +0 -40
  116. package/lib/docs/readBuildArtifact.js +0 -35
  117. package/lib/docs/readPageArtifact.js +0 -26
  118. package/lib/docs/resolvePluginDir.js +0 -49
  119. package/lib/docs/revertConfigCheckpoint.js +0 -73
  120. package/lib/docs/runRequest.js +0 -141
  121. package/lib/docs/saveAnnotatedScreenshot.js +0 -43
  122. package/lib/docs/scaffoldPage.js +0 -75
  123. package/lib/docs/scaffoldPage.test.mjs +0 -97
  124. package/lib/docs/screenshotPage.js +0 -109
  125. package/lib/docs/screenshotPage.test.mjs +0 -59
  126. package/lib/docs/screenshotPageClip.test.mjs +0 -102
  127. package/lib/docs/searchDocs.js +0 -67
  128. package/lib/docs/setupTestFixtures.mjs +0 -335
  129. package/lib/docs/snapshotState.js +0 -59
  130. package/lib/docs/stateCheckpoints.test.mjs +0 -348
  131. package/lib/docs/tabAvailable.js +0 -28
  132. package/lib/docs/tabChannel.js +0 -119
  133. package/lib/docs/tabChannel.test.mjs +0 -130
  134. package/lib/server/auth/getDevSession.js +0 -70
  135. package/lib/server/auth/getDevSession.test.mjs +0 -138
  136. package/lib/server/auth/getHeadlessUser.js +0 -40
  137. package/lib/server/auth/headlessUser.js +0 -29
  138. package/lib/server/auth/session.js +0 -39
  139. package/manager/processes/lowdefyBuild.test.mjs +0 -102
  140. package/manager/processes/warnAuthUrlPortMismatch.mjs +0 -47
  141. package/manager/processes/warnAuthUrlPortMismatch.test.mjs +0 -93
  142. package/manager/utils/formatNoticeBox.mjs +0 -30
  143. package/manager/utils/writeBuildStatus.mjs +0 -39
  144. package/manager/utils/writeBuildStatus.test.mjs +0 -76
  145. package/postcss.config.cjs +0 -1
  146. package/src/app.js +0 -175
  147. package/src/html/renderDevPage.js +0 -86
  148. package/src/lib/getPathSegments.js +0 -25
  149. package/src/lib/safeScriptJson.js +0 -38
  150. package/src/middleware/apiContext.js +0 -32
  151. package/src/middleware/errorHandler.js +0 -44
  152. package/src/routes/agent.js +0 -64
  153. package/src/routes/apiPage.js +0 -37
  154. package/src/routes/auth.js +0 -49
  155. package/src/routes/auth.test.mjs +0 -84
  156. package/src/routes/clientError.js +0 -57
  157. package/src/routes/cron.js +0 -44
  158. package/src/routes/detached.js +0 -47
  159. package/src/routes/devInspect.js +0 -94
  160. package/src/routes/docs/checkpointsCreate.js +0 -28
  161. package/src/routes/docs/checkpointsList.js +0 -23
  162. package/src/routes/docs/content.js +0 -31
  163. package/src/routes/docs/evalOperator.js +0 -46
  164. package/src/routes/docs/examples.js +0 -33
  165. package/src/routes/docs/find.js +0 -30
  166. package/src/routes/docs/index.js +0 -23
  167. package/src/routes/docs/inspectState.js +0 -34
  168. package/src/routes/docs/loadState.js +0 -38
  169. package/src/routes/docs/mcp.js +0 -30
  170. package/src/routes/docs/pageConfig.js +0 -36
  171. package/src/routes/docs/pluginDoc.js +0 -33
  172. package/src/routes/docs/plugins.js +0 -23
  173. package/src/routes/docs/runRequest.js +0 -36
  174. package/src/routes/docs/schema.js +0 -37
  175. package/src/routes/docs/screenshot.js +0 -66
  176. package/src/routes/docs/search.js +0 -27
  177. package/src/routes/docs/snapshotState.js +0 -36
  178. package/src/routes/docs/stateCheckpointsList.js +0 -26
  179. package/src/routes/docs/types.js +0 -33
  180. package/src/routes/endpoints.js +0 -71
  181. package/src/routes/feedback.js +0 -110
  182. package/src/routes/feedback.test.mjs +0 -204
  183. package/src/routes/iconsDynamic.js +0 -25
  184. package/src/routes/reload.js +0 -81
  185. package/src/routes/request.js +0 -66
  186. package/src/routes/usage.js +0 -46
  187. package/src/routes/websocket.js +0 -33
  188. package/src/websocket/devWebSocket.js +0 -78
  189. package/vite.config.js +0 -111
  190. /package/lib/client/{BuildErrorPage.jsx → BuildErrorPage.js} +0 -0
  191. /package/lib/client/{BuildingPage.jsx → BuildingPage.js} +0 -0
  192. /package/lib/client/{ErrorBar.jsx → ErrorBar.js} +0 -0
  193. /package/lib/client/{InstallingPluginsPage.jsx → InstallingPluginsPage.js} +0 -0
  194. /package/lib/client/{RestartingPage.jsx → RestartingPage.js} +0 -0
package/.eslintrc.yaml ADDED
@@ -0,0 +1 @@
1
+ extends: 'plugin:@next/next/core-web-vitals'
package/lib/build/app.js CHANGED
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/app.json'), 'utf8'));
17
+ import raw from '../../build/app.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/appMeta.json'), 'utf8'));
17
+ import raw from '../../build/appMeta.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
package/lib/build/auth.js CHANGED
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/auth.json'), 'utf8'));
17
+ import raw from '../../build/auth.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/config.json'), 'utf8'));
17
+ import raw from '../../build/config.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
package/lib/build/i18n.js CHANGED
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/i18n.json'), 'utf8'));
17
+ import raw from '../../build/i18n.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/logger.json'), 'utf8'));
17
+ import raw from '../../build/logger.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
@@ -13,14 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- // Build artifacts are read from disk because the Hono server runs as
18
- // unbundled Node.js ESM — JSON imports would need import attributes, and
19
- // client code imports the build JSON directly through Vite instead.
20
- import fs from 'node:fs';
21
- import path from 'node:path';
22
16
  import { serializer } from '@lowdefy/helpers';
23
-
24
- const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/theme.json'), 'utf8'));
17
+ import raw from '../../build/theme.json';
25
18
 
26
19
  export default serializer.deserialize(raw);
@@ -0,0 +1,80 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import React, { Suspense } from 'react';
18
+
19
+ import { useRouter } from 'next/router';
20
+
21
+ import Head from 'next/head';
22
+ import Link from 'next/link';
23
+
24
+ import BuildingPage from './BuildingPage.js';
25
+ import Reload from './Reload.js';
26
+ import Page from './Page.js';
27
+ import setPageId from './setPageId.js';
28
+ import { getReloadVersion } from './utils/useMutateCache.js';
29
+ import useRootConfig from './utils/useRootConfig.js';
30
+
31
+ import actions from '../../build/plugins/actions.js';
32
+ import blockMetas from '../../build/plugins/blockMetas.json';
33
+ import blocks from '../../build/plugins/blocks.js';
34
+ import icons from '../../build/plugins/icons.js';
35
+ import operators from '../../build/plugins/operators/client.js';
36
+ import staticJsMap from '../../build/plugins/operators/clientJsMap.js';
37
+
38
+ const App = ({ auth, lowdefy }) => {
39
+ const router = useRouter();
40
+ const { data: rootConfig } = useRootConfig(router.basePath);
41
+
42
+ if (rootConfig?.theme) {
43
+ lowdefy.theme = rootConfig.theme;
44
+ }
45
+
46
+ const { redirect, pageId } = setPageId(router, rootConfig);
47
+ if (redirect) {
48
+ router.push(`/${pageId}`);
49
+ return '';
50
+ }
51
+ return (
52
+ <Reload basePath={router.basePath} lowdefy={lowdefy}>
53
+ {(resetContext) => (
54
+ <Suspense key={`${pageId}_${getReloadVersion()}`} fallback={<BuildingPage />}>
55
+ <Page
56
+ auth={auth}
57
+ Components={{ Head, Link }}
58
+ config={{
59
+ rootConfig,
60
+ }}
61
+ jsMap={staticJsMap}
62
+ lowdefy={lowdefy}
63
+ pageId={pageId}
64
+ resetContext={resetContext}
65
+ router={router}
66
+ types={{
67
+ actions,
68
+ blockMetas,
69
+ blocks,
70
+ icons,
71
+ operators,
72
+ }}
73
+ />
74
+ </Suspense>
75
+ )}
76
+ </Reload>
77
+ );
78
+ };
79
+
80
+ export default App;
@@ -18,10 +18,10 @@ import React, { useEffect, useRef } from 'react';
18
18
  import { GenIcon } from 'react-icons/lib';
19
19
  import Client from '@lowdefy/client';
20
20
 
21
- import BuildErrorPage from '../lib/client/BuildErrorPage.jsx';
22
- import InstallingPluginsPage from '../lib/client/InstallingPluginsPage.jsx';
23
- import RestartingPage from '../lib/client/RestartingPage.jsx';
24
- import usePageConfig from '../lib/client/utils/usePageConfig.js';
21
+ import BuildErrorPage from './BuildErrorPage.js';
22
+ import InstallingPluginsPage from './InstallingPluginsPage.js';
23
+ import RestartingPage from './RestartingPage.js';
24
+ import usePageConfig from './utils/usePageConfig.js';
25
25
 
26
26
  const Page = ({
27
27
  auth,
@@ -48,7 +48,7 @@ const Page = ({
48
48
  }, [pageConfig?._warnings, lowdefy]);
49
49
 
50
50
  if (!pageConfig) {
51
- router.replace({ pathname: '/404' });
51
+ router.replace(`/404`);
52
52
  return '';
53
53
  }
54
54
  if (pageConfig.buildError) {
@@ -16,12 +16,9 @@
16
16
 
17
17
  import React, { useEffect, useState } from 'react';
18
18
 
19
- import useMutateCache from '../lib/client/utils/useMutateCache.js';
20
- import waitForRestartedServer from '../lib/client/utils/waitForRestartedServer.js';
19
+ import useMutateCache from './utils/useMutateCache.js';
20
+ import waitForRestartedServer from './utils/waitForRestartedServer.js';
21
21
 
22
- // SSE listener — config rebuilds notify via /api/reload. Tailwind CSS updates
23
- // arrive through Vite HMR now (globals.css is in the dev module graph), so
24
- // the old tailwind-jit.css link cache-bust is gone.
25
22
  const Reload = ({ children, basePath, lowdefy }) => {
26
23
  const [reset, setReset] = useState(false);
27
24
  const [restarting, setRestarting] = useState(false);
@@ -37,6 +34,11 @@ const Reload = ({ children, basePath, lowdefy }) => {
37
34
  if (lowdefy._internal?.initialised) {
38
35
  lowdefy._internal.initialised = false;
39
36
  }
37
+ // Refresh JIT CSS link to pick up newly compiled Tailwind classes
38
+ const cssLink = document.getElementById('tailwind-jit-css');
39
+ if (cssLink) {
40
+ cssLink.href = `${basePath}/tailwind-jit.css?v=${Date.now()}`;
41
+ }
40
42
  setReset(true);
41
43
  console.log('Reloaded config.');
42
44
  }, 600);
@@ -13,22 +13,13 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
16
  /* eslint-disable react/jsx-props-no-spreading */
18
17
 
19
18
  import React from 'react';
20
- import AuthConfigured from './AuthConfigured.jsx';
19
+ import AuthConfigured from './AuthConfigured.js';
21
20
  import AuthNotConfigured from './AuthNotConfigured.js';
22
21
 
23
- import { serializer } from '@lowdefy/helpers';
24
-
25
- // Client code imports the build JSON directly — Vite handles JSON imports;
26
- // the lib/build/*.js wrappers are server-only (they read from disk).
27
- // Deserialize to restore arrays from their ~arr build markers (providers
28
- // must be a real array for single-provider inference in createAuthMethods).
29
- import rawAuthConfig from '../../../build/auth.json';
30
-
31
- const authConfig = serializer.deserialize(rawAuthConfig);
22
+ import authConfig from '../../build/auth.js';
32
23
 
33
24
  function Auth({ children, session }) {
34
25
  if (authConfig.configured === true) {
@@ -13,30 +13,12 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
16
  /* eslint-disable react/jsx-props-no-spreading */
18
17
 
19
18
  import React, { useEffect, useRef } from 'react';
20
- import {
21
- authConfigManager,
22
- getSession,
23
- SessionProvider,
24
- signIn,
25
- signOut,
26
- useSession,
27
- } from '@hono/auth-js/react';
28
-
29
- import { serializer } from '@lowdefy/helpers';
30
-
31
- import rawLowdefyConfig from '../../../build/config.json';
19
+ import { getSession, SessionProvider, signIn, signOut, useSession } from 'next-auth/react';
32
20
 
33
- const lowdefyConfig = serializer.deserialize(rawLowdefyConfig);
34
-
35
- // @hono/auth-js/react configures its fetch paths through a module-level
36
- // manager instead of SessionProvider props.
37
- if (lowdefyConfig.basePath) {
38
- authConfigManager.setConfig({ basePath: `${lowdefyConfig.basePath}/api/auth` });
39
- }
21
+ import lowdefyConfig from '../../build/config.js';
40
22
 
41
23
  function Session({ children }) {
42
24
  const wasAuthenticated = useRef(false);
@@ -49,8 +31,9 @@ function Session({ children }) {
49
31
  }
50
32
  }, [status]);
51
33
 
52
- // If session is passed to SessionProvider from the server-rendered config
53
- // we won't have a loading state here, but unauthenticated first loads do.
34
+ // If session is passed to SessionProvider from getServerSideProps
35
+ // we won't have a loading state here.
36
+ // But 404 uses getStaticProps so we have this for 404.
54
37
  if (status === 'loading') {
55
38
  return '';
56
39
  }
@@ -59,8 +42,12 @@ function Session({ children }) {
59
42
 
60
43
  function AuthConfigured({ authConfig, children, serverSession }) {
61
44
  const auth = { authConfig, getSession, signIn, signOut };
45
+ let basePath = lowdefyConfig.basePath;
46
+ if (basePath) {
47
+ basePath = `${basePath}/api/auth`;
48
+ }
62
49
  return (
63
- <SessionProvider session={serverSession}>
50
+ <SessionProvider session={serverSession} basePath={basePath}>
64
51
  <Session>
65
52
  {(session) => {
66
53
  auth.session = session;
@@ -14,19 +14,18 @@
14
14
  limitations under the License.
15
15
  */
16
16
 
17
- // location comes from the custom router (@lowdefy/client/adapters):
18
- // { pageId, pathname, search }. pageId is null at the root path.
19
- function setPageId(location, rootConfig) {
20
- if (location.pageId === '404') {
17
+ function setPageId(router, rootConfig) {
18
+ if (router.pathname === `/404`) {
21
19
  return { redirect: false, pageId: '404' };
22
20
  }
23
- if (!location.pageId) {
21
+ const segments = router.query.pageId;
22
+ if (!segments || segments.length === 0) {
24
23
  if (rootConfig.home.configured === false) {
25
24
  return { redirect: true, pageId: rootConfig.home.pageId };
26
25
  }
27
26
  return { redirect: false, pageId: rootConfig.home.pageId };
28
27
  }
29
- return { redirect: false, pageId: location.pageId };
28
+ return { redirect: false, pageId: segments.join('/') };
30
29
  }
31
30
 
32
31
  export default setPageId;
@@ -16,25 +16,12 @@
16
16
 
17
17
  import { useSWRConfig } from 'swr';
18
18
 
19
- // Module-level counters that bust usePageConfig SWR keys: reloadVersion moves
20
- // on config reloads (all pages), navVersion on client-side navigations
21
- // (dynamic pages only — server-resolved content must re-resolve per
22
- // navigation, never serve from the SWR cache).
23
19
  let reloadVersion = 0;
24
- let navVersion = 0;
25
20
 
26
21
  function getReloadVersion() {
27
22
  return reloadVersion;
28
23
  }
29
24
 
30
- function bumpNavVersion() {
31
- navVersion += 1;
32
- }
33
-
34
- function getNavVersion() {
35
- return navVersion;
36
- }
37
-
38
25
  function useMutateCache(basePath) {
39
26
  const { mutate } = useSWRConfig();
40
27
  return () => {
@@ -47,5 +34,5 @@ function useMutateCache(basePath) {
47
34
  };
48
35
  }
49
36
 
50
- export { bumpNavVersion, getNavVersion, getReloadVersion };
37
+ export { getReloadVersion };
51
38
  export default useMutateCache;
@@ -13,12 +13,7 @@
13
13
 
14
14
  import useSWR from 'swr';
15
15
 
16
- import { getNavVersion, getReloadVersion } from './useMutateCache.js';
17
-
18
- // URLs whose config is server-resolved per request — learned from the fetched
19
- // config's dynamic flag, so the first visit caches like a static page and
20
- // every later navigation refetches.
21
- const dynamicUrls = new Set();
16
+ import { getReloadVersion } from './useMutateCache.js';
22
17
 
23
18
  function parseJsModule(text) {
24
19
  const fn = new Function('exports', text.replace('export default', 'exports.default ='));
@@ -76,31 +71,23 @@ async function fetchPageConfig(url) {
76
71
  data._jsEntries = jsEntries;
77
72
  data._dynamicIcons = dynamicIcons;
78
73
 
79
- if (data?.dynamic === true) {
80
- dynamicUrls.add(url);
74
+ // Bust CSS cache so the browser picks up newly compiled Tailwind classes
75
+ const cssLink = document.getElementById('tailwind-jit-css');
76
+ if (cssLink) {
77
+ cssLink.href = `${basePath}/tailwind-jit.css?v=${Date.now()}`;
81
78
  }
82
79
 
83
80
  return data;
84
81
  }
85
82
 
86
83
  function usePageConfig(pageId, basePath) {
87
- // Forward the current query string so server-side Dynamic block resolution
88
- // sees the same urlQuery as an initial HTML load. Including it in the SWR
89
- // key also caches dynamic pages per query string.
90
- const url = `${basePath}/api/page/${pageId}${window.location.search}`;
84
+ const url = `${basePath}/api/page/${pageId}`;
91
85
  // Include reloadVersion in the SWR key so that after a config reload,
92
- // previously cached page data is not reused. Dynamic pages also key on the
93
- // navigation version — server-resolved content must re-resolve on every
94
- // navigation, never serve from the SWR cache. The fetcher receives
95
- // [url, ...versions] but only uses url — the versions just bust the cache.
96
- const navVersion = dynamicUrls.has(url) ? getNavVersion() : 0;
97
- const { data } = useSWR(
98
- [url, getReloadVersion(), navVersion],
99
- ([fetchUrl]) => fetchPageConfig(fetchUrl),
100
- {
101
- suspense: true,
102
- }
103
- );
86
+ // previously cached page data is not reused. The fetcher receives
87
+ // [url, version] but only uses url — the version just busts the cache.
88
+ const { data } = useSWR([url, getReloadVersion()], ([fetchUrl]) => fetchPageConfig(fetchUrl), {
89
+ suspense: true,
90
+ });
104
91
  return { data };
105
92
  }
106
93
 
@@ -13,35 +13,30 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
-
17
- import fs from 'node:fs';
18
- import path from 'node:path';
16
+ import fs from 'fs';
17
+ import path from 'path';
19
18
  import { createApiContext } from '@lowdefy/api';
20
19
  import { getSecretsFromEnv } from '@lowdefy/node-utils';
20
+ import { serializer } from '@lowdefy/helpers';
21
21
  import { v4 as uuid } from 'uuid';
22
22
 
23
23
  import agents from '../../build/plugins/agents.js';
24
24
  import appMeta from '../build/appMeta.js';
25
25
  import config from '../build/config.js';
26
+ import i18nConfig from '../build/i18n.js';
26
27
  import connections from '../../build/plugins/connections.js';
27
- import createHandleError from './log/createHandleError.js';
28
28
  import createLogger from './log/createLogger.js';
29
29
  import fileCache from './fileCache.js';
30
- import getSession from './auth/session.js';
31
- import i18nConfig from '../build/i18n.js';
30
+ import getServerSession from './auth/getServerSession.js';
31
+ import createHandleError from './log/createHandleError.js';
32
32
  import logRequest from './log/logRequest.js';
33
- import notifications, {
34
- interpolateProperties,
35
- renderEmail,
36
- } from '../../build/plugins/notifications.js';
37
33
  import operators from '../../build/plugins/operators/server.js';
38
34
  import staticJsMap from '../../build/plugins/operators/serverJsMap.js';
39
- import websockets from '../../build/plugins/websockets.js';
35
+ import getAuthOptions from './auth/getAuthOptions.js';
40
36
 
41
37
  const secrets = getSecretsFromEnv();
42
38
 
43
- // Dynamic JS map loading for JIT-built pages — the build rewrites
44
- // serverJsMap.js when a JIT page discovers new _js operators.
39
+ // Dynamic JS map loading for JIT-built pages
45
40
  let cachedJsMapMtime = null;
46
41
  let cachedJsMap = staticJsMap;
47
42
 
@@ -65,54 +60,57 @@ function loadDynamicJsMap(buildDirectory) {
65
60
  }
66
61
  }
67
62
 
68
- // Builds the per-request lowdefy API context (connections, secrets,
69
- // operators, logger, session, etc.). Factored out of the /api/* middleware
70
- // (src/middleware/apiContext.js) so run_request (lib/docs/runRequest.js) can
71
- // build an identical context outside the Hono middleware chain, to call
72
- // callRequest directly for agent-driven request execution.
73
- async function createLowdefyContext({ c }) {
74
- const buildDirectory = path.join(process.cwd(), 'build');
75
- const jsMap = loadDynamicJsMap(buildDirectory);
63
+ function apiWrapper(handler) {
64
+ return async function wrappedHandler(req, res) {
65
+ const buildDirectory = path.join(process.cwd(), 'build');
66
+ const jsMap = loadDynamicJsMap(buildDirectory);
76
67
 
77
- const context = {
78
- rid: uuid(),
79
- agents,
80
- appMeta,
81
- buildDirectory,
82
- configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
83
- config,
84
- connections,
85
- fileCache,
86
- headers: c.req.header(),
87
- // The deployment's own origin — detached endpoint calls loop back
88
- // through it so the target runs in its own function invocation.
89
- origin: new URL(c.req.url).origin,
90
- i18n: i18nConfig,
91
- interpolateProperties,
92
- jsMap,
93
- handleError: async (err) => {
94
- console.error(err);
95
- },
96
- logger: console,
97
- notifications,
98
- operators,
99
- renderEmail,
100
- req: {
101
- url: c.req.path,
102
- method: c.req.method,
103
- hostname: c.req.header('host'),
104
- },
105
- secrets,
106
- websockets,
68
+ const context = {
69
+ // Important to give absolute path so Next can trace build files
70
+ rid: uuid(),
71
+ agents,
72
+ appMeta,
73
+ buildDirectory,
74
+ configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
75
+ config,
76
+ connections,
77
+ fileCache,
78
+ headers: req?.headers,
79
+ i18n: i18nConfig,
80
+ jsMap,
81
+ handleError: async (err) => {
82
+ console.error(err);
83
+ },
84
+ logger: console,
85
+ operators,
86
+ req,
87
+ res,
88
+ secrets,
89
+ };
90
+ try {
91
+ context.logger = createLogger();
92
+ context.handleError = createHandleError({ context });
93
+ context.authOptions = getAuthOptions(context);
94
+ if (!req.url.startsWith('/api/auth')) {
95
+ context.session = await getServerSession(context);
96
+ }
97
+ createApiContext(context);
98
+ logRequest({ context });
99
+ // Await here so that if handler throws it is caught.
100
+ const response = await handler({ context, req, res });
101
+ // TODO: Log response time?
102
+ return response;
103
+ } catch (error) {
104
+ await context.handleError(error);
105
+ const serialized = serializer.serialize(error);
106
+ if (serialized?.['~e']) {
107
+ delete serialized['~e'].received;
108
+ delete serialized['~e'].stack;
109
+ delete serialized['~e'].configKey;
110
+ }
111
+ res.status(500).json(serialized);
112
+ }
107
113
  };
108
- context.logger = createLogger();
109
- context.handleError = createHandleError({ context });
110
- if (!c.req.path.includes('/api/auth')) {
111
- context.session = await getSession(c);
112
- }
113
- createApiContext(context);
114
- logRequest({ context });
115
- return context;
116
114
  }
117
115
 
118
- export default createLowdefyContext;
116
+ export default apiWrapper;
@@ -14,25 +14,22 @@
14
14
  limitations under the License.
15
15
  */
16
16
 
17
- import { getAuthConfig as getApiAuthConfig } from '@lowdefy/api';
17
+ import { getNextAuthConfig } from '@lowdefy/api';
18
18
  import { getSecretsFromEnv } from '@lowdefy/node-utils';
19
19
 
20
20
  import adapters from '../../../build/plugins/auth/adapters.js';
21
- import appMeta from '../../build/appMeta.js';
22
21
  import authJson from '../../build/auth.js';
23
22
  import callbacks from '../../../build/plugins/auth/callbacks.js';
24
23
  import events from '../../../build/plugins/auth/events.js';
25
24
  import providers from '../../../build/plugins/auth/providers.js';
26
25
 
27
- function getAuthConfig({ logger }) {
28
- return getApiAuthConfig({
29
- appMeta,
26
+ function getAuthOptions({ logger }) {
27
+ return getNextAuthConfig({
30
28
  authJson,
31
- dev: true,
32
29
  logger,
33
30
  plugins: { adapters, callbacks, events, providers },
34
31
  secrets: getSecretsFromEnv(),
35
32
  });
36
33
  }
37
34
 
38
- export default getAuthConfig;
35
+ export default getAuthOptions;