@lowdefy/server-dev 0.0.0-experimental-20260608135213 → 0.0.0-experimental-20260610101734
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} +16 -32
- package/{lib/client/Page.js → client/Page.jsx} +5 -5
- package/{lib/client/Reload.js → client/Reload.jsx} +5 -7
- package/{lib/client/App.js → client/Routing.jsx} +34 -23
- package/client/main.jsx +42 -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/usePageConfig.js +0 -5
- package/lib/server/auth/{getAuthOptions.js → getAuthConfig.js} +6 -4
- package/lib/server/auth/{getServerSession.js → session.js} +9 -8
- package/lib/server/jitPageBuilder.js +17 -7
- package/lib/server/readBuildApiArtifacts.mjs +53 -0
- package/lib/server/readBuildApiArtifacts.test.mjs +106 -0
- package/manager/getContext.mjs +2 -6
- package/manager/processes/initialBuild.mjs +0 -2
- package/manager/processes/shutdownServer.mjs +6 -6
- package/manager/processes/startServer.mjs +7 -7
- package/manager/processes/startWatchers.mjs +2 -2
- package/manager/run.mjs +10 -0
- package/manager/utils/{getNextBin.mjs → getViteBin.mjs} +7 -10
- package/manager/utils/updatePageTailwindCss.mjs +7 -1
- 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 +47 -41
- package/package.original.json +50 -44
- package/postcss.config.cjs +1 -0
- package/src/app.js +93 -0
- package/src/html/renderDevPage.js +86 -0
- package/src/lib/getPathSegments.js +25 -0
- package/src/lib/safeScriptJson.js +38 -0
- package/{pages/404.js → src/lib/serveBuildJs.js} +13 -2
- package/{lib/server/apiWrapper.js → src/middleware/apiContext.js} +35 -42
- package/src/middleware/errorHandler.js +44 -0
- package/src/routes/agent.js +64 -0
- package/src/routes/apiPage.js +35 -0
- package/src/routes/auth.js +38 -0
- package/{pages/api/client-error.js → src/routes/clientError.js} +13 -15
- package/{pages/[[...pageId]].js → src/routes/devTools.js} +4 -2
- package/{pages/api/endpoints/[...endpointId].js → src/routes/endpoints.js} +8 -7
- package/{pages/api/dev-tools.js → src/routes/iconsDynamic.js} +7 -4
- package/{pages/api/page/[...pageId].js → src/routes/jitPage.js} +28 -22
- package/src/routes/jsEnv.js +30 -0
- package/{pages/api → src/routes}/ping.js +4 -2
- package/src/routes/reload.js +54 -0
- package/{pages/api/request/[...path].js → src/routes/request.js} +11 -14
- package/{pages/api → src/routes}/root.js +4 -4
- package/src/routes/usage.js +48 -0
- package/vite.config.js +58 -0
- 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/icons/dynamic.js +0 -34
- package/pages/api/js/[env].js +0 -42
- package/pages/api/reload.js +0 -53
- /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
|
@@ -14,14 +14,7 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
// CSS layer order — MUST be the first CSS import. Turbopack treats this as critical
|
|
18
|
-
// CSS that loads before hydration, locking the cascade priority (antd > base/preflight)
|
|
19
|
-
// before antd's StyleProvider injects @layer antd {} at runtime.
|
|
20
|
-
import '../build/layer-order.css';
|
|
21
|
-
|
|
22
17
|
import React, { Suspense, useCallback, useEffect, useRef, useState } from 'react';
|
|
23
|
-
import dynamic from 'next/dynamic';
|
|
24
|
-
import { useRouter } from 'next/router';
|
|
25
18
|
import useSWR from 'swr';
|
|
26
19
|
|
|
27
20
|
import { ErrorBoundary } from '@lowdefy/block-utils';
|
|
@@ -33,13 +26,10 @@ import { XProvider } from '@ant-design/x';
|
|
|
33
26
|
import antdLocaleLoaders from '../build/i18n/antdLocales.js';
|
|
34
27
|
import antdXLocaleLoaders from '../build/i18n/antdXLocales.js';
|
|
35
28
|
import dayjsLocaleMap from '../build/i18n/dayjsLocales.js';
|
|
36
|
-
import Auth from '../lib/client/auth/Auth.
|
|
37
|
-
import ErrorBar from '../lib/client/ErrorBar.
|
|
29
|
+
import Auth from '../lib/client/auth/Auth.jsx';
|
|
30
|
+
import ErrorBar from '../lib/client/ErrorBar.jsx';
|
|
38
31
|
import request from '../lib/client/utils/request.js';
|
|
39
|
-
|
|
40
|
-
// Full Tailwind CSS — also loaded via <link href="tailwind-jit.css"> in _document.js
|
|
41
|
-
// for hot-reloading. The Turbopack chunk provides layer ordering guarantee on initial load.
|
|
42
|
-
import '../build/globals.css';
|
|
32
|
+
import Routing from './Routing.jsx';
|
|
43
33
|
|
|
44
34
|
function ThemeTokenResolver({ lowdefyRef, children }) {
|
|
45
35
|
const { token } = antdTheme.useToken();
|
|
@@ -50,12 +40,11 @@ function ThemeTokenResolver({ lowdefyRef, children }) {
|
|
|
50
40
|
return children;
|
|
51
41
|
}
|
|
52
42
|
|
|
53
|
-
function App({
|
|
54
|
-
const router = useRouter();
|
|
43
|
+
function App({ config, router }) {
|
|
55
44
|
const lowdefyRef = useRef({});
|
|
56
45
|
const [runtimeErrors, setRuntimeErrors] = useState([]);
|
|
57
|
-
// Subscribe to rootConfig SWR cache — deduplicates with
|
|
58
|
-
// Without suspense so
|
|
46
|
+
// Subscribe to rootConfig SWR cache — deduplicates with Routing's fetch.
|
|
47
|
+
// Without suspense so App doesn't suspend — just re-renders when data arrives.
|
|
59
48
|
const { data: rootConfig } = useSWR(`${router.basePath}/api/root`, (url) => request({ url }));
|
|
60
49
|
if (rootConfig?.theme) {
|
|
61
50
|
lowdefyRef.current.theme = rootConfig.theme;
|
|
@@ -99,12 +88,10 @@ function App({ Component }) {
|
|
|
99
88
|
]);
|
|
100
89
|
}, []);
|
|
101
90
|
|
|
102
|
-
// Clear runtime errors on
|
|
91
|
+
// Clear runtime errors on navigation
|
|
103
92
|
useEffect(() => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return () => router.events.off('routeChangeStart', clearErrors);
|
|
107
|
-
}, [router.events]);
|
|
93
|
+
return router.subscribe(() => setRuntimeErrors([]));
|
|
94
|
+
}, [router]);
|
|
108
95
|
|
|
109
96
|
const handleError = useCallback((error) => {
|
|
110
97
|
if (lowdefyRef.current?._internal?.handleError) {
|
|
@@ -115,10 +102,11 @@ function App({ Component }) {
|
|
|
115
102
|
}, []);
|
|
116
103
|
|
|
117
104
|
// XProvider extends antd's ConfigProvider; merging antd + antd-X locale packs
|
|
118
|
-
// gives X components their built-in strings
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
105
|
+
// gives X components (Bubble, Sender, Conversations, ...) their built-in strings
|
|
106
|
+
// alongside antd's. antd X ships only en_US + zh_CN; other locales fall back
|
|
107
|
+
// to en_US for X-native strings.
|
|
108
|
+
const mergedLocale =
|
|
109
|
+
antdLocale || antdXLocale ? { ...(antdLocale ?? {}), ...(antdXLocale ?? {}) } : undefined;
|
|
122
110
|
|
|
123
111
|
return (
|
|
124
112
|
<StyleProvider layer>
|
|
@@ -153,7 +141,7 @@ function App({ Component }) {
|
|
|
153
141
|
>
|
|
154
142
|
<Auth>
|
|
155
143
|
{(auth) => {
|
|
156
|
-
return <
|
|
144
|
+
return <Routing auth={auth} lowdefy={lowdefyRef.current} router={router} />;
|
|
157
145
|
}}
|
|
158
146
|
</Auth>
|
|
159
147
|
</Suspense>
|
|
@@ -166,8 +154,4 @@ function App({ Component }) {
|
|
|
166
154
|
);
|
|
167
155
|
}
|
|
168
156
|
|
|
169
|
-
|
|
170
|
-
ssr: false,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
export default DynamicApp;
|
|
157
|
+
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 '
|
|
22
|
-
import InstallingPluginsPage from '
|
|
23
|
-
import RestartingPage from '
|
|
24
|
-
import usePageConfig from '
|
|
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';
|
|
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(
|
|
51
|
+
router.replace({ pathname: '/404' });
|
|
52
52
|
return '';
|
|
53
53
|
}
|
|
54
54
|
if (pageConfig.buildError) {
|
|
@@ -16,9 +16,12 @@
|
|
|
16
16
|
|
|
17
17
|
import React, { useEffect, useState } from 'react';
|
|
18
18
|
|
|
19
|
-
import useMutateCache from '
|
|
20
|
-
import waitForRestartedServer from '
|
|
19
|
+
import useMutateCache from '../lib/client/utils/useMutateCache.js';
|
|
20
|
+
import waitForRestartedServer from '../lib/client/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.
|
|
22
25
|
const Reload = ({ children, basePath, lowdefy }) => {
|
|
23
26
|
const [reset, setReset] = useState(false);
|
|
24
27
|
const [restarting, setRestarting] = useState(false);
|
|
@@ -34,11 +37,6 @@ const Reload = ({ children, basePath, lowdefy }) => {
|
|
|
34
37
|
if (lowdefy._internal?.initialised) {
|
|
35
38
|
lowdefy._internal.initialised = false;
|
|
36
39
|
}
|
|
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
|
-
}
|
|
42
40
|
setReset(true);
|
|
43
41
|
console.log('Reloaded config.');
|
|
44
42
|
}, 600);
|
|
@@ -14,40 +14,51 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import React, { Suspense } from 'react';
|
|
17
|
+
import React, { Suspense, useEffect, useState } from 'react';
|
|
18
18
|
|
|
19
|
-
import
|
|
19
|
+
import Head from '@lowdefy/client/adapters/Head.js';
|
|
20
|
+
import createLinkComponent from '@lowdefy/client/adapters/Link.js';
|
|
20
21
|
|
|
21
|
-
import
|
|
22
|
-
import
|
|
22
|
+
import BuildingPage from '../lib/client/BuildingPage.jsx';
|
|
23
|
+
import Reload from './Reload.jsx';
|
|
24
|
+
import Page from './Page.jsx';
|
|
25
|
+
import setPageId from '../lib/client/setPageId.js';
|
|
26
|
+
import { getReloadVersion } from '../lib/client/utils/useMutateCache.js';
|
|
27
|
+
import useRootConfig from '../lib/client/utils/useRootConfig.js';
|
|
23
28
|
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import
|
|
29
|
+
import actions from '../build/plugins/actions.js';
|
|
30
|
+
import blockMetas from '../build/plugins/blockMetas.json';
|
|
31
|
+
import blocks from '../build/plugins/blocks.js';
|
|
32
|
+
import icons from '../build/plugins/icons.js';
|
|
33
|
+
import operators from '../build/plugins/operators/client.js';
|
|
34
|
+
import staticJsMap from '../build/plugins/operators/clientJsMap.js';
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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();
|
|
36
|
+
// Replaces lib/client/App.js — page resolution driven by the custom router
|
|
37
|
+
// instead of next/router, everything else preserved.
|
|
38
|
+
function Routing({ auth, lowdefy, router }) {
|
|
40
39
|
const { data: rootConfig } = useRootConfig(router.basePath);
|
|
40
|
+
const [location, setLocation] = useState(() => router.getLocation());
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
return router.subscribe(setLocation);
|
|
44
|
+
}, [router]);
|
|
45
|
+
|
|
46
|
+
const [Link] = useState(() => createLinkComponent({ router }));
|
|
41
47
|
|
|
42
48
|
if (rootConfig?.theme) {
|
|
43
49
|
lowdefy.theme = rootConfig.theme;
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
const { redirect, pageId } = setPageId(
|
|
52
|
+
const { redirect, pageId } = setPageId(location, rootConfig);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (redirect) {
|
|
55
|
+
router.replace({ pathname: `/${pageId}` });
|
|
56
|
+
}
|
|
57
|
+
}, [redirect, pageId, router]);
|
|
47
58
|
if (redirect) {
|
|
48
|
-
router.push(`/${pageId}`);
|
|
49
59
|
return '';
|
|
50
60
|
}
|
|
61
|
+
|
|
51
62
|
return (
|
|
52
63
|
<Reload basePath={router.basePath} lowdefy={lowdefy}>
|
|
53
64
|
{(resetContext) => (
|
|
@@ -75,6 +86,6 @@ const App = ({ auth, lowdefy }) => {
|
|
|
75
86
|
)}
|
|
76
87
|
</Reload>
|
|
77
88
|
);
|
|
78
|
-
}
|
|
89
|
+
}
|
|
79
90
|
|
|
80
|
-
export default
|
|
91
|
+
export default Routing;
|
package/client/main.jsx
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
// CSS layer order — MUST be the first CSS import. This locks the cascade
|
|
18
|
+
// priority (antd > base/preflight) before antd's StyleProvider injects
|
|
19
|
+
// @layer antd {} at runtime. Vite's PostCSS pipeline compiles globals.css
|
|
20
|
+
// (Tailwind) on the fly and hot-replaces it — the old tailwind-jit.css
|
|
21
|
+
// side-channel is gone.
|
|
22
|
+
import '../build/layer-order.css';
|
|
23
|
+
|
|
24
|
+
import React from 'react';
|
|
25
|
+
import { createRoot } from 'react-dom/client';
|
|
26
|
+
import createRouter from '@lowdefy/client/adapters/createRouter.js';
|
|
27
|
+
|
|
28
|
+
import App from './App.jsx';
|
|
29
|
+
|
|
30
|
+
import '../build/globals.css';
|
|
31
|
+
|
|
32
|
+
const config = JSON.parse(document.getElementById('__LOWDEFY_CONFIG__').textContent);
|
|
33
|
+
const router = createRouter({ basePath: config.basePath ?? '', window });
|
|
34
|
+
const container = document.getElementById('root');
|
|
35
|
+
|
|
36
|
+
// Keep one React root across Vite HMR updates.
|
|
37
|
+
const root = import.meta.hot?.data.root ?? createRoot(container);
|
|
38
|
+
if (import.meta.hot) {
|
|
39
|
+
import.meta.hot.data.root = root;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
root.render(<App config={config} router={router} />);
|
package/lib/build/app.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/app.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/appMeta.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/appMeta.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/auth.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/auth.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/config.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/config.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/i18n.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/i18n.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/logger.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/logger.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
package/lib/build/theme.js
CHANGED
|
@@ -13,7 +13,14 @@
|
|
|
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';
|
|
16
22
|
import { serializer } from '@lowdefy/helpers';
|
|
17
|
-
|
|
23
|
+
|
|
24
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'build/theme.json'), 'utf8'));
|
|
18
25
|
|
|
19
26
|
export default serializer.deserialize(raw);
|
|
@@ -13,13 +13,22 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
|
|
16
17
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
17
18
|
|
|
18
19
|
import React from 'react';
|
|
19
|
-
import AuthConfigured from './AuthConfigured.
|
|
20
|
+
import AuthConfigured from './AuthConfigured.jsx';
|
|
20
21
|
import AuthNotConfigured from './AuthNotConfigured.js';
|
|
21
22
|
|
|
22
|
-
import
|
|
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);
|
|
23
32
|
|
|
24
33
|
function Auth({ children, session }) {
|
|
25
34
|
if (authConfig.configured === true) {
|
|
@@ -13,12 +13,30 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
|
|
16
17
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
17
18
|
|
|
18
19
|
import React, { useEffect, useRef } from 'react';
|
|
19
|
-
import {
|
|
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';
|
|
20
32
|
|
|
21
|
-
|
|
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
|
+
}
|
|
22
40
|
|
|
23
41
|
function Session({ children }) {
|
|
24
42
|
const wasAuthenticated = useRef(false);
|
|
@@ -31,9 +49,8 @@ function Session({ children }) {
|
|
|
31
49
|
}
|
|
32
50
|
}, [status]);
|
|
33
51
|
|
|
34
|
-
// If session is passed to SessionProvider from
|
|
35
|
-
// we won't have a loading state here.
|
|
36
|
-
// But 404 uses getStaticProps so we have this for 404.
|
|
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.
|
|
37
54
|
if (status === 'loading') {
|
|
38
55
|
return '';
|
|
39
56
|
}
|
|
@@ -42,12 +59,8 @@ function Session({ children }) {
|
|
|
42
59
|
|
|
43
60
|
function AuthConfigured({ authConfig, children, serverSession }) {
|
|
44
61
|
const auth = { authConfig, getSession, signIn, signOut };
|
|
45
|
-
let basePath = lowdefyConfig.basePath;
|
|
46
|
-
if (basePath) {
|
|
47
|
-
basePath = `${basePath}/api/auth`;
|
|
48
|
-
}
|
|
49
62
|
return (
|
|
50
|
-
<SessionProvider session={serverSession}
|
|
63
|
+
<SessionProvider session={serverSession}>
|
|
51
64
|
<Session>
|
|
52
65
|
{(session) => {
|
|
53
66
|
auth.session = session;
|
package/lib/client/setPageId.js
CHANGED
|
@@ -14,18 +14,19 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
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') {
|
|
19
21
|
return { redirect: false, pageId: '404' };
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
if (!segments || segments.length === 0) {
|
|
23
|
+
if (!location.pageId) {
|
|
23
24
|
if (rootConfig.home.configured === false) {
|
|
24
25
|
return { redirect: true, pageId: rootConfig.home.pageId };
|
|
25
26
|
}
|
|
26
27
|
return { redirect: false, pageId: rootConfig.home.pageId };
|
|
27
28
|
}
|
|
28
|
-
return { redirect: false, pageId:
|
|
29
|
+
return { redirect: false, pageId: location.pageId };
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export default setPageId;
|
|
@@ -71,11 +71,6 @@ async function fetchPageConfig(url) {
|
|
|
71
71
|
data._jsEntries = jsEntries;
|
|
72
72
|
data._dynamicIcons = dynamicIcons;
|
|
73
73
|
|
|
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()}`;
|
|
78
|
-
}
|
|
79
74
|
|
|
80
75
|
return data;
|
|
81
76
|
}
|
|
@@ -14,17 +14,19 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { getAuthConfig as getApiAuthConfig } 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';
|
|
21
22
|
import authJson from '../../build/auth.js';
|
|
22
23
|
import callbacks from '../../../build/plugins/auth/callbacks.js';
|
|
23
24
|
import events from '../../../build/plugins/auth/events.js';
|
|
24
25
|
import providers from '../../../build/plugins/auth/providers.js';
|
|
25
26
|
|
|
26
|
-
function
|
|
27
|
-
return
|
|
27
|
+
function getAuthConfig({ logger }) {
|
|
28
|
+
return getApiAuthConfig({
|
|
29
|
+
appMeta,
|
|
28
30
|
authJson,
|
|
29
31
|
logger,
|
|
30
32
|
plugins: { adapters, callbacks, events, providers },
|
|
@@ -32,4 +34,4 @@ function getAuthOptions({ logger }) {
|
|
|
32
34
|
});
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
export default
|
|
37
|
+
export default getAuthConfig;
|
|
@@ -14,22 +14,23 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { getAuthUser } from '@hono/auth-js';
|
|
18
18
|
|
|
19
19
|
import authJson from '../../build/auth.js';
|
|
20
20
|
import getMockSession from './getMockSession.js';
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// Replaces getServerSession.js — mock user first (dev only), then the
|
|
23
|
+
// session from the Hono context populated by initAuthConfig.
|
|
24
|
+
async function getSession(c) {
|
|
24
25
|
const mockSession = await getMockSession();
|
|
25
26
|
if (mockSession) {
|
|
26
27
|
return mockSession;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return getNextAuthServerSession(req, res, authOptions);
|
|
29
|
+
if (authJson.configured !== true) {
|
|
30
|
+
return undefined;
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
const authUser = await getAuthUser(c);
|
|
33
|
+
return authUser?.session ?? undefined;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
export default
|
|
36
|
+
export default getSession;
|
|
@@ -19,9 +19,9 @@ import path from 'path';
|
|
|
19
19
|
import { serializer } from '@lowdefy/helpers';
|
|
20
20
|
import { buildPageJit, createContext, makeId } from '@lowdefy/build/dev';
|
|
21
21
|
|
|
22
|
-
import compileCss from './compileCss.js';
|
|
23
22
|
import createLogger from './log/createLogger.js';
|
|
24
23
|
import PageCache from './pageCache.mjs';
|
|
24
|
+
import readBuildApiArtifacts from './readBuildApiArtifacts.mjs';
|
|
25
25
|
|
|
26
26
|
const jitLogger = createLogger({ name: 'jit-build' });
|
|
27
27
|
|
|
@@ -35,10 +35,10 @@ let cachedRegistry = null;
|
|
|
35
35
|
let cachedBuildContext = null;
|
|
36
36
|
let lastInvalidationMtime = null;
|
|
37
37
|
|
|
38
|
-
// Frozen snapshot of icon imports from the initial build (what's actually in the
|
|
38
|
+
// Frozen snapshot of icon imports from the initial build (what's actually in the client bundle).
|
|
39
39
|
// Module-level so it persists across context resets (skeleton rebuilds update iconImports.json
|
|
40
|
-
// with newly discovered icons, but those aren't in the bundle until
|
|
41
|
-
// Only resets when the server process restarts
|
|
40
|
+
// with newly discovered icons, but those aren't in the bundle until a server restart).
|
|
41
|
+
// Only resets when the server process restarts.
|
|
42
42
|
let bundledIconImports = null;
|
|
43
43
|
|
|
44
44
|
function readJsonFile(filePath) {
|
|
@@ -128,10 +128,15 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
128
128
|
Object.assign(cachedBuildContext.modules, modules);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
// Restore api endpoint configs so JIT CallAPI validation (validateCallApiRefs in
|
|
132
|
+
// buildPageJit) can resolve endpointIds. Without this the dev context has no
|
|
133
|
+
// components.api and every CallAPI action is flagged as a non-existent endpoint.
|
|
134
|
+
cachedBuildContext.components = { api: readBuildApiArtifacts(buildDirectory) };
|
|
135
|
+
|
|
131
136
|
// Use the frozen icon imports from the initial build for JIT detection.
|
|
132
|
-
// This represents what's actually in the
|
|
137
|
+
// This represents what's actually in the client bundle — not what shallowBuild
|
|
133
138
|
// discovers on subsequent rebuilds (those icons aren't bundled yet).
|
|
134
|
-
// bundledIconImports is module-level and only resets on server restart
|
|
139
|
+
// bundledIconImports is module-level and only resets on server restart.
|
|
135
140
|
if (!bundledIconImports) {
|
|
136
141
|
bundledIconImports = readJsonFile(path.join(buildDirectory, 'iconImports.json')) ?? [];
|
|
137
142
|
}
|
|
@@ -184,7 +189,12 @@ async function buildPageIfNeeded({ pageId, buildDirectory, configDirectory }) {
|
|
|
184
189
|
return result;
|
|
185
190
|
}
|
|
186
191
|
pageCache.markCompiled(pageId);
|
|
187
|
-
|
|
192
|
+
// Touch the candidates file so Vite's CSS pipeline re-runs Tailwind for
|
|
193
|
+
// classes the JIT build discovered — globals.css imports it.
|
|
194
|
+
fs.writeFileSync(
|
|
195
|
+
path.join(buildDirectory, 'tailwind-candidates.css'),
|
|
196
|
+
`/* Generated by Lowdefy build — rewritten on page changes to trigger CSS recompilation */\n/* ${Date.now()} */\n`
|
|
197
|
+
);
|
|
188
198
|
jitLogger.info(
|
|
189
199
|
{ spin: 'succeed', color: 'white' },
|
|
190
200
|
`Built page "${pageId}" in ${formatDuration(Date.now() - startTime)}.`
|