@lowdefy/server-dev 0.0.0-experimental-20260720072521 → 0.0.0-experimental-20260720135014

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) 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} +5 -12
  13. package/lib/client/auth/AuthConfigured.js +61 -0
  14. package/lib/client/auth/AuthNotConfigured.js +2 -22
  15. package/lib/client/setPageId.js +5 -6
  16. package/lib/client/utils/useMutateCache.js +1 -14
  17. package/lib/client/utils/usePageConfig.js +11 -31
  18. package/lib/server/apiWrapper.js +116 -0
  19. package/lib/server/auth/{getStrategies.js → getAuthOptions.js} +9 -14
  20. package/lib/server/auth/{getMockUser.js → getMockSession.js} +19 -10
  21. package/{src/routes/docs/checkpointsRevert.js → lib/server/auth/getServerSession.js} +13 -11
  22. package/lib/server/compileCss.js +39 -0
  23. package/lib/server/jitPageBuilder.js +11 -36
  24. package/lib/server/log/logRequest.js +3 -1
  25. package/manager/getContext.mjs +7 -3
  26. package/manager/processes/compileCss.mjs +54 -0
  27. package/manager/processes/initialBuild.mjs +2 -0
  28. package/manager/processes/installPlugins.mjs +11 -19
  29. package/manager/processes/lowdefyBuild.mjs +7 -29
  30. package/manager/processes/nextBuild.mjs +50 -0
  31. package/manager/processes/readDotEnv.mjs +1 -13
  32. package/manager/processes/shutdownServer.mjs +6 -6
  33. package/manager/processes/startServer.mjs +7 -8
  34. package/manager/processes/startWatchers.mjs +2 -2
  35. package/manager/run.mjs +0 -41
  36. package/manager/utils/createCustomPluginMessagesMap.mjs +1 -8
  37. package/manager/utils/createCustomPluginTypesMap.mjs +2 -3
  38. package/manager/utils/{getViteBin.mjs → getNextBin.mjs} +10 -7
  39. package/manager/utils/updatePageTailwindCss.mjs +1 -7
  40. package/manager/watchers/lowdefyBuildWatcher.mjs +1 -0
  41. package/manager/watchers/moduleBuildWatcher.mjs +1 -0
  42. package/manager/watchers/{serverArtifactWatcher.mjs → nextBuildWatcher.mjs} +22 -18
  43. package/next.config.js +25 -0
  44. package/package.json +47 -63
  45. package/package.original.json +55 -66
  46. package/{src/routes/devTools.js → pages/404.js} +2 -4
  47. package/{src/routes/docs/appMap.js → pages/[[...pageId]].js} +2 -6
  48. package/{client/App.jsx → pages/_app.js} +33 -21
  49. package/pages/_document.js +107 -0
  50. package/pages/api/agent/[...path].js +86 -0
  51. package/pages/api/auth/[...nextauth].js +48 -0
  52. package/pages/api/client-error.js +45 -0
  53. package/{src/routes/docs/buildStatus.js → pages/api/dev-tools.js} +4 -5
  54. package/{lib/docs/clientErrorStore.js → pages/api/endpoints/[...endpointId].js} +11 -15
  55. package/{src/lib/serveBuildJs.js → pages/api/icons/dynamic.js} +12 -8
  56. package/{src/routes/jsEnv.js → pages/api/js/[env].js} +20 -8
  57. package/pages/api/page/[...pageId].js +74 -0
  58. package/{src/routes → pages/api}/ping.js +2 -4
  59. package/pages/api/reload.js +53 -0
  60. package/pages/api/request/[...path].js +41 -0
  61. package/{src/routes → pages/api}/root.js +4 -4
  62. package/client/Inspector.jsx +0 -206
  63. package/client/Routing.jsx +0 -106
  64. package/client/feedback/FeedbackMount.jsx +0 -83
  65. package/client/feedback/FeedbackOverlay.jsx +0 -901
  66. package/client/feedback/captureTabScreenshot.js +0 -84
  67. package/client/feedback/copyToClipboard.js +0 -45
  68. package/client/feedback/drawAnnotationsSvg.js +0 -119
  69. package/client/feedback/elementInspect.js +0 -99
  70. package/client/feedback/feedbackStyles.js +0 -301
  71. package/client/feedback/pinResponsiveImages.js +0 -59
  72. package/client/feedback/sendFeedback.js +0 -39
  73. package/client/feedback/useFeedbackToggle.js +0 -70
  74. package/client/main.jsx +0 -42
  75. package/client/openInEditor/OpenInEditorListener.jsx +0 -261
  76. package/client/openInEditor/findBlockLocation.js +0 -51
  77. package/lib/client/auth/AuthConfigured.jsx +0 -155
  78. package/lib/docs/captureAnnotatedScreenshot.js +0 -88
  79. package/lib/docs/checkpointPaths.js +0 -91
  80. package/lib/docs/checkpointStore.js +0 -234
  81. package/lib/docs/checkpointToMocks.js +0 -65
  82. package/lib/docs/configCheckpoints.test.mjs +0 -156
  83. package/lib/docs/createConfigCheckpoint.js +0 -92
  84. package/lib/docs/createDocsMcpServer.js +0 -506
  85. package/lib/docs/createDocsMcpServer.test.mjs +0 -123
  86. package/lib/docs/devMockRegistry.js +0 -68
  87. package/lib/docs/docs.test.mjs +0 -448
  88. package/lib/docs/enrichFeedback.js +0 -71
  89. package/lib/docs/evalOperator.js +0 -39
  90. package/lib/docs/evalOperator.test.mjs +0 -112
  91. package/lib/docs/evalOperatorHeadless.js +0 -87
  92. package/lib/docs/evalOperatorHeadless.test.mjs +0 -72
  93. package/lib/docs/evalOperatorInTab.js +0 -48
  94. package/lib/docs/findConfig.js +0 -260
  95. package/lib/docs/formatFeedback.js +0 -121
  96. package/lib/docs/formatFeedback.test.mjs +0 -204
  97. package/lib/docs/getAppMap.js +0 -180
  98. package/lib/docs/getBrowser.js +0 -115
  99. package/lib/docs/getBuildStatus.js +0 -37
  100. package/lib/docs/getCoreDoc.js +0 -63
  101. package/lib/docs/getDocsManifest.js +0 -40
  102. package/lib/docs/getExamples.js +0 -58
  103. package/lib/docs/getOverview.js +0 -115
  104. package/lib/docs/getPageConfig.js +0 -53
  105. package/lib/docs/getPluginDoc.js +0 -55
  106. package/lib/docs/getSchema.js +0 -65
  107. package/lib/docs/inspectState.js +0 -41
  108. package/lib/docs/inspectState.test.mjs +0 -91
  109. package/lib/docs/inspectStateFromTab.js +0 -40
  110. package/lib/docs/inspectStateHeadless.js +0 -84
  111. package/lib/docs/inspectStateHeadless.test.mjs +0 -60
  112. package/lib/docs/isWriteRequestsAllowed.js +0 -50
  113. package/lib/docs/listConfigCheckpoints.js +0 -55
  114. package/lib/docs/listPlugins.js +0 -80
  115. package/lib/docs/listTypes.js +0 -105
  116. package/lib/docs/loadState.js +0 -139
  117. package/lib/docs/mapPageBuildErrors.js +0 -28
  118. package/lib/docs/normalizeTypeKind.js +0 -40
  119. package/lib/docs/readBuildArtifact.js +0 -35
  120. package/lib/docs/readPageArtifact.js +0 -26
  121. package/lib/docs/resolvePluginDir.js +0 -49
  122. package/lib/docs/revertConfigCheckpoint.js +0 -73
  123. package/lib/docs/runRequest.js +0 -141
  124. package/lib/docs/saveAnnotatedScreenshot.js +0 -43
  125. package/lib/docs/scaffoldPage.js +0 -75
  126. package/lib/docs/scaffoldPage.test.mjs +0 -97
  127. package/lib/docs/screenshotPage.js +0 -109
  128. package/lib/docs/screenshotPage.test.mjs +0 -59
  129. package/lib/docs/screenshotPageClip.test.mjs +0 -102
  130. package/lib/docs/searchDocs.js +0 -67
  131. package/lib/docs/setupTestFixtures.mjs +0 -335
  132. package/lib/docs/snapshotState.js +0 -59
  133. package/lib/docs/stateCheckpoints.test.mjs +0 -348
  134. package/lib/docs/tabAvailable.js +0 -28
  135. package/lib/docs/tabChannel.js +0 -119
  136. package/lib/docs/tabChannel.test.mjs +0 -130
  137. package/lib/server/auth/createSystemContext.js +0 -70
  138. package/lib/server/auth/getAuth.js +0 -46
  139. package/lib/server/auth/getHeadlessUser.js +0 -39
  140. package/lib/server/auth/headlessUser.js +0 -30
  141. package/lib/server/createLowdefyContext.js +0 -133
  142. package/lib/server/loadDynamicJsMap.js +0 -47
  143. package/manager/processes/lowdefyBuild.test.mjs +0 -102
  144. package/manager/utils/formatNoticeBox.mjs +0 -30
  145. package/manager/utils/writeBuildStatus.mjs +0 -39
  146. package/manager/utils/writeBuildStatus.test.mjs +0 -76
  147. package/postcss.config.cjs +0 -1
  148. package/src/app.js +0 -188
  149. package/src/html/renderDevPage.js +0 -86
  150. package/src/lib/getPathSegments.js +0 -25
  151. package/src/lib/safeScriptJson.js +0 -38
  152. package/src/middleware/apiContext.js +0 -32
  153. package/src/middleware/errorHandler.js +0 -55
  154. package/src/routes/agent.js +0 -64
  155. package/src/routes/auth.js +0 -43
  156. package/src/routes/clientError.js +0 -57
  157. package/src/routes/cron.js +0 -44
  158. package/src/routes/detached.js +0 -51
  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 -34
  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 -76
  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/jitPage.js +0 -99
  185. package/src/routes/reload.js +0 -81
  186. package/src/routes/request.js +0 -66
  187. package/src/routes/usage.js +0 -46
  188. package/src/routes/user.js +0 -27
  189. package/src/routes/websocket.js +0 -33
  190. package/src/websocket/devWebSocket.js +0 -78
  191. package/vite.config.js +0 -111
  192. /package/lib/client/{BuildErrorPage.jsx → BuildErrorPage.js} +0 -0
  193. /package/lib/client/{BuildingPage.jsx → BuildingPage.js} +0 -0
  194. /package/lib/client/{ErrorBar.jsx → ErrorBar.js} +0 -0
  195. /package/lib/client/{InstallingPluginsPage.jsx → InstallingPluginsPage.js} +0 -0
  196. /package/lib/client/{RestartingPage.jsx → RestartingPage.js} +0 -0
@@ -1,70 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import path from 'node:path';
18
- import { createSystemContext as buildSystemContext } from '@lowdefy/api';
19
- import { getSecretsFromEnv } from '@lowdefy/node-utils';
20
- import { v4 as uuid } from 'uuid';
21
-
22
- import agents from '../../../build/plugins/agents.js';
23
- import appMeta from '../../build/appMeta.js';
24
- import config from '../../build/config.js';
25
- import connections from '../../../build/plugins/connections.js';
26
- import createHandleError from '../log/createHandleError.js';
27
- import createLogger from '../log/createLogger.js';
28
- import fileCache from '../fileCache.js';
29
- import i18nConfig from '../../build/i18n.js';
30
- import loadDynamicJsMap from '../loadDynamicJsMap.js';
31
- import notifications from '../../../build/plugins/notifications.js';
32
- import operators from '../../../build/plugins/operators/server.js';
33
- import steps from '../../../build/plugins/steps.js';
34
- import websockets from '../../../build/plugins/websockets.js';
35
-
36
- const secrets = getSecretsFromEnv();
37
-
38
- // Builds a fresh system context per auth hook fire - the trusted internal
39
- // caller the BetterAuth engine uses to invoke hook endpoints. All fields are
40
- // startup singletons except the per-fire rid, logger, handleError, the
41
- // dynamic jsMap re-read (JIT rebuilds rewrite serverJsMap.js), and auth -
42
- // auth is threaded in by the caller (createHookDispatch) rather than
43
- // imported directly, since it comes from the same BetterAuth construction
44
- // that this factory is a dependency of (see createHookDispatch.js).
45
- function createSystemContext({ auth } = {}) {
46
- const rid = uuid();
47
- const buildDirectory = path.join(process.cwd(), 'build');
48
- return buildSystemContext({
49
- rid,
50
- agents,
51
- appMeta,
52
- auth,
53
- buildDirectory,
54
- config,
55
- configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
56
- connections,
57
- createHandleError,
58
- fileCache,
59
- i18n: i18nConfig,
60
- jsMap: loadDynamicJsMap(buildDirectory),
61
- logger: createLogger({ rid }),
62
- notifications,
63
- operators,
64
- secrets,
65
- steps,
66
- websockets,
67
- });
68
- }
69
-
70
- export default createSystemContext;
@@ -1,46 +0,0 @@
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 { getBetterAuth } from '@lowdefy/api';
18
- import { getSecretsFromEnv } from '@lowdefy/node-utils';
19
-
20
- import adapters from '../../../build/plugins/auth/adapters.js';
21
- import appMeta from '../../build/appMeta.js';
22
- import authJson from '../../build/auth.js';
23
- import createSystemContext from './createSystemContext.js';
24
- import lowdefyConfig from '../../build/config.js';
25
- import providers from '../../../build/plugins/auth/providers.js';
26
-
27
- // Returns the BetterAuth instance (memoized in @lowdefy/api), or null when
28
- // auth is not configured. dev: true relaxes cookies for plain-http localhost
29
- // and derives a per-app cookie prefix so parallel dev apps do not collide.
30
- function getAuth({ logger }) {
31
- if (authJson.configured !== true) {
32
- return null;
33
- }
34
- return getBetterAuth({
35
- appMeta,
36
- authJson,
37
- config: lowdefyConfig,
38
- createSystemContext,
39
- dev: true,
40
- logger,
41
- plugins: { adapters, providers },
42
- secrets: getSecretsFromEnv(),
43
- });
44
- }
45
-
46
- export default getAuth;
@@ -1,39 +0,0 @@
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 { HEADLESS_USER_COOKIE } from './headlessUser.js';
18
-
19
- // Mirrors the e2e user-injection pattern (server-e2e/lib/server/auth/getUser.js):
20
- // the headless renderer sets a base64-JSON user cookie on its own browser
21
- // context, so its /api/* fetches carry a pre-resolved caller while the
22
- // developer's real browser (no cookie) is unaffected. Returns the raw decoded
23
- // user, or null on miss - the caller floors the shape via normalizeInjectedCaller.
24
- function getHeadlessUser(c) {
25
- const cookieHeader = c.req.header('cookie') ?? '';
26
- const match = cookieHeader.match(new RegExp(`${HEADLESS_USER_COOKIE}=([^;]+)`));
27
- if (!match) {
28
- return null;
29
- }
30
-
31
- try {
32
- const decoded = Buffer.from(decodeURIComponent(match[1]), 'base64').toString();
33
- return JSON.parse(decoded);
34
- } catch {
35
- return null;
36
- }
37
- }
38
-
39
- export default getHeadlessUser;
@@ -1,30 +0,0 @@
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
- // Shared between the headless renderer (getBrowser.js, which sets the cookie on
18
- // its browser context) and the dev caller resolver (getHeadlessUser.js, which
19
- // decodes it) so the cookie name and injected user shape live in one place.
20
- const HEADLESS_USER_COOKIE = 'lowdefy_headless_user';
21
-
22
- // BetterAuth's session user carries `id`, never `sub`. attributes is floored to
23
- // {} by normalizeInjectedCaller at injection, so it is not spelled out here.
24
- const headlessUser = {
25
- id: 'lowdefy-headless',
26
- name: 'Lowdefy Headless',
27
- roles: [],
28
- };
29
-
30
- export { HEADLESS_USER_COOKIE, headlessUser };
@@ -1,133 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import path from 'node:path';
18
- import {
19
- createApiContext,
20
- normalizeInjectedCaller,
21
- resolveAuthentication,
22
- resolvePinnedOrganization,
23
- } from '@lowdefy/api';
24
- import { getSecretsFromEnv } from '@lowdefy/node-utils';
25
- import { v4 as uuid } from 'uuid';
26
-
27
- import agents from '../../build/plugins/agents.js';
28
- import appMeta from '../build/appMeta.js';
29
- import config from '../build/config.js';
30
- import connections from '../../build/plugins/connections.js';
31
- import createHandleError from './log/createHandleError.js';
32
- import createLogger from './log/createLogger.js';
33
- import fileCache from './fileCache.js';
34
- import getAuth from './auth/getAuth.js';
35
- import getHeadlessUser from './auth/getHeadlessUser.js';
36
- import getMockUser from './auth/getMockUser.js';
37
- import getStrategies from './auth/getStrategies.js';
38
- import i18nConfig from '../build/i18n.js';
39
- import loadDynamicJsMap from './loadDynamicJsMap.js';
40
- import logRequest from './log/logRequest.js';
41
- import notifications, {
42
- interpolateProperties,
43
- renderEmail,
44
- } from '../../build/plugins/notifications.js';
45
- import operators from '../../build/plugins/operators/server.js';
46
- import steps from '../../build/plugins/steps.js';
47
- import websockets from '../../build/plugins/websockets.js';
48
-
49
- const secrets = getSecretsFromEnv();
50
-
51
- // Builds the per-request lowdefy API context (connections, secrets,
52
- // operators, logger, resolved user, etc.). Factored out of the /api/*
53
- // middleware (src/middleware/apiContext.js) so run_request
54
- // (lib/docs/runRequest.js) can build an identical context outside the Hono
55
- // middleware chain, to call callRequest directly for agent-driven request
56
- // execution.
57
- async function createLowdefyContext({ c }) {
58
- const buildDirectory = path.join(process.cwd(), 'build');
59
- const jsMap = loadDynamicJsMap(buildDirectory);
60
-
61
- const rid = uuid();
62
- const context = {
63
- rid,
64
- agents,
65
- appMeta,
66
- buildDirectory,
67
- configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
68
- config,
69
- connections,
70
- fileCache,
71
- headers: c.req.header(),
72
- // The deployment's own origin — detached endpoint calls loop back
73
- // through it so the target runs in its own function invocation.
74
- origin: new URL(c.req.url).origin,
75
- i18n: i18nConfig,
76
- interpolateProperties,
77
- jsMap,
78
- logger: createLogger({ rid }),
79
- notifications,
80
- operators,
81
- renderEmail,
82
- req: {
83
- url: c.req.path,
84
- method: c.req.method,
85
- hostname: c.req.header('host'),
86
- },
87
- secrets,
88
- steps,
89
- websockets,
90
- };
91
- context.handleError = createHandleError({ context });
92
- const mockUser = getMockUser();
93
- const headlessUser = getHeadlessUser(c);
94
- if (mockUser) {
95
- // The mock user is a pre-resolved caller - it substitutes for the
96
- // whole resolveAuthentication step and its roles are authoritative.
97
- // No auth engine runs while dev.mockUser is active (see src/app.js),
98
- // so mock mode never touches the auth database. normalizeInjectedCaller
99
- // floors it to the resolved-caller shape.
100
- context.auth = null;
101
- context.user = normalizeInjectedCaller(mockUser);
102
- } else if (headlessUser) {
103
- // The headless renderer (docs/MCP screenshot and state tools) injects a
104
- // user cookie on its own browser context (getBrowser.js), so its /api/*
105
- // fetches carry a pre-resolved caller and auth-protected pages render.
106
- // The developer's real browser has no cookie and resolves through the
107
- // auth engine below, so it is unaffected.
108
- context.auth = null;
109
- context.user = normalizeInjectedCaller(headlessUser);
110
- } else {
111
- // Hoisted once per request - resolveAuthentication also needs it, and
112
- // getBetterAuth memoizes the instance, but this keeps the auth engine
113
- // construction to a single call site per request.
114
- context.auth = getAuth({ logger: context.logger });
115
- // The engine is constructed lazily on the first request, which would
116
- // otherwise race the startup pinned-org ensure - await the memoized
117
- // resolve so createApiContext reads a retained binding.
118
- await resolvePinnedOrganization({ auth: context.auth, logger: context.logger });
119
- if (!c.req.path.includes('/api/auth')) {
120
- // resolveAuthentication is the single writer of context.user.
121
- await resolveAuthentication(context, {
122
- auth: context.auth,
123
- headers: c.req.raw.headers,
124
- strategies: getStrategies({ logger: context.logger }),
125
- });
126
- }
127
- }
128
- createApiContext(context);
129
- logRequest({ context });
130
- return context;
131
- }
132
-
133
- export default createLowdefyContext;
@@ -1,47 +0,0 @@
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 staticJsMap from '../../build/plugins/operators/serverJsMap.js';
21
-
22
- // Dynamic JS map loading for JIT-built pages — the build rewrites
23
- // serverJsMap.js when a JIT page discovers new _js operators.
24
- let cachedJsMapMtime = null;
25
- let cachedJsMap = staticJsMap;
26
-
27
- function loadDynamicJsMap(buildDirectory) {
28
- const jsMapPath = path.join(buildDirectory, 'plugins', 'operators', 'serverJsMap.js');
29
- try {
30
- const stat = fs.statSync(jsMapPath);
31
- if (cachedJsMapMtime && stat.mtimeMs === cachedJsMapMtime) {
32
- return cachedJsMap;
33
- }
34
- cachedJsMapMtime = stat.mtimeMs;
35
- // For server-side, we can read and eval the JS file
36
- const content = fs.readFileSync(jsMapPath, 'utf8');
37
- const fn = new Function('exports', content.replace('export default', 'exports.default ='));
38
- const exports = {};
39
- fn(exports);
40
- cachedJsMap = { ...staticJsMap, ...(exports.default ?? {}) };
41
- return cachedJsMap;
42
- } catch {
43
- return cachedJsMap;
44
- }
45
- }
46
-
47
- export default loadDynamicJsMap;
@@ -1,102 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { jest } from '@jest/globals';
18
-
19
- const mockShallowBuild = jest.fn();
20
- const mockSerializeBuildException = jest.fn((exception) => ({ message: exception.message }));
21
- const mockWriteBuildStatus = jest.fn();
22
- const mockCreateCustomPluginTypesMap = jest.fn().mockResolvedValue({});
23
- const mockCreateCustomPluginMessagesMap = jest.fn().mockResolvedValue({});
24
-
25
- jest.unstable_mockModule('@lowdefy/build/dev', () => ({
26
- shallowBuild: mockShallowBuild,
27
- serializeBuildException: mockSerializeBuildException,
28
- }));
29
- jest.unstable_mockModule('../utils/writeBuildStatus.mjs', () => ({
30
- default: mockWriteBuildStatus,
31
- }));
32
- jest.unstable_mockModule('../utils/createCustomPluginTypesMap.mjs', () => ({
33
- default: mockCreateCustomPluginTypesMap,
34
- }));
35
- jest.unstable_mockModule('../utils/createCustomPluginMessagesMap.mjs', () => ({
36
- default: mockCreateCustomPluginMessagesMap,
37
- }));
38
-
39
- const { default: lowdefyBuild } = await import('./lowdefyBuild.mjs');
40
-
41
- function createContext() {
42
- return {
43
- directories: { build: '/app/build' },
44
- logger: { info: jest.fn() },
45
- options: { refResolver: undefined },
46
- };
47
- }
48
-
49
- test('lowdefyBuild writes an ok buildStatus.json after a successful build', async () => {
50
- const context = createContext();
51
- const warning = { message: 'Deprecated feature used' };
52
- mockShallowBuild.mockResolvedValue({
53
- components: {},
54
- pageRegistry: {},
55
- context: { warnings: [warning] },
56
- });
57
-
58
- const build = lowdefyBuild(context);
59
- await build();
60
-
61
- expect(mockWriteBuildStatus).toHaveBeenCalledWith({
62
- directories: context.directories,
63
- status: 'ok',
64
- errors: [],
65
- warnings: [{ message: 'Deprecated feature used' }],
66
- });
67
- expect(mockSerializeBuildException).toHaveBeenCalledWith(warning, 0, [warning]);
68
- });
69
-
70
- test('lowdefyBuild writes an error buildStatus.json and rethrows when the build fails', async () => {
71
- const context = createContext();
72
- const buildError = new Error('Build failed with 1 error(s). See above for details.');
73
- buildError.errors = [{ message: 'Bad config' }];
74
- buildError.warnings = [{ message: 'Deprecated feature used' }];
75
- mockShallowBuild.mockRejectedValue(buildError);
76
-
77
- const build = lowdefyBuild(context);
78
- await expect(build()).rejects.toBe(buildError);
79
-
80
- expect(mockWriteBuildStatus).toHaveBeenCalledWith({
81
- directories: context.directories,
82
- status: 'error',
83
- errors: [{ message: 'Bad config' }],
84
- warnings: [{ message: 'Deprecated feature used' }],
85
- });
86
- });
87
-
88
- test('lowdefyBuild falls back to the raw error message when the thrown error has no errors array', async () => {
89
- const context = createContext();
90
- const buildError = new Error('Build failed due to internal error. See above for details.');
91
- mockShallowBuild.mockRejectedValue(buildError);
92
-
93
- const build = lowdefyBuild(context);
94
- await expect(build()).rejects.toBe(buildError);
95
-
96
- expect(mockWriteBuildStatus).toHaveBeenCalledWith({
97
- directories: context.directories,
98
- status: 'error',
99
- errors: [{ message: 'Build failed due to internal error. See above for details.' }],
100
- warnings: [],
101
- });
102
- });
@@ -1,30 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- // Draws a rounded box around a title and body lines for CLI startup notices.
18
- // The border width is derived from the longest line so it's always aligned,
19
- // regardless of the content passed in. Returned with a leading newline so it
20
- // starts on its own line under the CLI logger's timestamp/symbol prefix.
21
- function formatNoticeBox({ title, lines }) {
22
- const inner = Math.max(title.length + 1, ...lines.map((line) => line.length));
23
- const pad = (line) => line + ' '.repeat(inner - line.length);
24
- const top = `╭─ ${title} ${'─'.repeat(inner - title.length - 1)}╮`;
25
- const bottom = `╰${'─'.repeat(inner + 2)}╯`;
26
- const body = lines.map((line) => `│ ${pad(line)} │`);
27
- return ['', top, ...body, bottom].join('\n');
28
- }
29
-
30
- export default formatNoticeBox;
@@ -1,39 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import path from 'path';
18
-
19
- import { writeFileIfChanged } from '@lowdefy/node-utils';
20
-
21
- // Written after every dev build attempt (success or failure) so the Hono
22
- // process - a separate process from this manager, sharing only the build
23
- // directory - can serve current build errors/warnings to AI coding agents.
24
- // writeFileIfChanged creates the build directory if it does not exist, which
25
- // covers the case where the build attempt cleaned it before failing.
26
- async function writeBuildStatus({ directories, status, errors, warnings }) {
27
- const buildStatus = {
28
- status,
29
- timestamp: new Date().toISOString(),
30
- errors,
31
- warnings,
32
- };
33
- await writeFileIfChanged(
34
- path.join(directories.build, 'buildStatus.json'),
35
- JSON.stringify(buildStatus)
36
- );
37
- }
38
-
39
- export default writeBuildStatus;
@@ -1,76 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import fs from 'fs';
18
- import os from 'os';
19
- import path from 'path';
20
-
21
- import writeBuildStatus from './writeBuildStatus.mjs';
22
-
23
- let buildDir;
24
-
25
- beforeEach(() => {
26
- buildDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lowdefy-build-status-test-'));
27
- });
28
-
29
- afterEach(() => {
30
- fs.rmSync(buildDir, { recursive: true, force: true });
31
- });
32
-
33
- function readBuildStatus() {
34
- return JSON.parse(fs.readFileSync(path.join(buildDir, 'buildStatus.json'), 'utf8'));
35
- }
36
-
37
- test('writeBuildStatus writes an ok status with a timestamp', async () => {
38
- await writeBuildStatus({
39
- directories: { build: buildDir },
40
- status: 'ok',
41
- errors: [],
42
- warnings: [{ message: 'Deprecated feature used' }],
43
- });
44
-
45
- const buildStatus = readBuildStatus();
46
- expect(buildStatus.status).toBe('ok');
47
- expect(buildStatus.errors).toEqual([]);
48
- expect(buildStatus.warnings).toEqual([{ message: 'Deprecated feature used' }]);
49
- expect(new Date(buildStatus.timestamp).toString()).not.toBe('Invalid Date');
50
- });
51
-
52
- test('writeBuildStatus writes an error status with the errors array', async () => {
53
- await writeBuildStatus({
54
- directories: { build: buildDir },
55
- status: 'error',
56
- errors: [{ message: 'Bad config' }],
57
- warnings: [],
58
- });
59
-
60
- const buildStatus = readBuildStatus();
61
- expect(buildStatus.status).toBe('error');
62
- expect(buildStatus.errors).toEqual([{ message: 'Bad config' }]);
63
- });
64
-
65
- test('writeBuildStatus creates the build directory when it does not exist', async () => {
66
- const missingDir = path.join(buildDir, 'nested', 'build');
67
-
68
- await writeBuildStatus({
69
- directories: { build: missingDir },
70
- status: 'error',
71
- errors: [{ message: 'Bad config' }],
72
- warnings: [],
73
- });
74
-
75
- expect(fs.existsSync(path.join(missingDir, 'buildStatus.json'))).toBe(true);
76
- });
@@ -1 +0,0 @@
1
- module.exports = { plugins: { '@tailwindcss/postcss': {} } };