@lowdefy/server-dev 0.0.0-experimental-20260223144039 → 0.0.0-experimental-20260304101313
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/lib/client/App.js +23 -19
- package/lib/client/BuildErrorPage.js +4 -3
- package/lib/client/BuildingPage.js +74 -0
- package/lib/client/InstallingPluginsPage.js +50 -0
- package/lib/client/Page.js +4 -0
- package/lib/client/RestartingPage.js +2 -0
- package/lib/client/utils/request.js +1 -3
- package/lib/client/utils/usePageConfig.js +3 -0
- package/lib/server/apiWrapper.js +15 -11
- package/lib/server/auth/getMockSession.js +1 -1
- package/lib/server/jitPageBuilder.js +33 -14
- package/lib/server/log/createHandleError.js +47 -0
- package/lib/server/log/createLogger.js +3 -3
- package/lib/server/pageCache.mjs +0 -43
- package/lib/server/pageCache.test.mjs +0 -100
- package/manager/getContext.mjs +8 -6
- package/manager/processes/installPlugins.mjs +2 -2
- package/manager/processes/lowdefyBuild.mjs +20 -23
- package/manager/processes/nextBuild.mjs +10 -6
- package/manager/processes/restartServer.mjs +2 -2
- package/manager/processes/shutdownServer.mjs +1 -1
- package/manager/utils/checkPortAvailable.mjs +5 -4
- package/manager/utils/getLowdefyVersion.mjs +6 -12
- package/manager/watchers/lowdefyBuildWatcher.mjs +8 -25
- package/manager/watchers/nextBuildWatcher.mjs +12 -2
- package/next.config.js +1 -10
- package/package.json +31 -31
- package/package.original.json +30 -30
- package/pages/_app.js +3 -17
- package/pages/api/client-error.js +15 -10
- package/pages/api/page/[pageId].js +11 -3
- package/pages/api/reload.js +4 -1
- package/pages/api/request/[pageId]/[requestId].js +4 -1
- package/lib/client/sentry/captureSentryError.js +0 -43
- package/lib/client/sentry/initSentryClient.js +0 -55
- package/lib/client/sentry/setSentryUser.js +0 -41
- package/lib/server/log/logError.js +0 -56
- package/lib/server/sentry/captureSentryError.js +0 -57
- package/lib/server/sentry/initSentry.js +0 -44
- package/lib/server/sentry/setSentryUser.js +0 -46
package/lib/client/App.js
CHANGED
|
@@ -14,16 +14,18 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import React from 'react';
|
|
17
|
+
import React, { Suspense } from 'react';
|
|
18
18
|
|
|
19
19
|
import { useRouter } from 'next/router';
|
|
20
20
|
|
|
21
21
|
import Head from 'next/head';
|
|
22
22
|
import Link from 'next/link';
|
|
23
23
|
|
|
24
|
+
import BuildingPage from './BuildingPage.js';
|
|
24
25
|
import Reload from './Reload.js';
|
|
25
26
|
import Page from './Page.js';
|
|
26
27
|
import setPageId from './setPageId.js';
|
|
28
|
+
import { getReloadVersion } from './utils/useMutateCache.js';
|
|
27
29
|
import useRootConfig from './utils/useRootConfig.js';
|
|
28
30
|
|
|
29
31
|
import actions from '../../build/plugins/actions.js';
|
|
@@ -44,24 +46,26 @@ const App = ({ auth, lowdefy }) => {
|
|
|
44
46
|
return (
|
|
45
47
|
<Reload basePath={router.basePath} lowdefy={lowdefy}>
|
|
46
48
|
{(resetContext) => (
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
<Suspense key={`${pageId}_${getReloadVersion()}`} fallback={<BuildingPage />}>
|
|
50
|
+
<Page
|
|
51
|
+
auth={auth}
|
|
52
|
+
Components={{ Head, Link }}
|
|
53
|
+
config={{
|
|
54
|
+
rootConfig,
|
|
55
|
+
}}
|
|
56
|
+
jsMap={staticJsMap}
|
|
57
|
+
lowdefy={lowdefy}
|
|
58
|
+
pageId={pageId}
|
|
59
|
+
resetContext={resetContext}
|
|
60
|
+
router={router}
|
|
61
|
+
types={{
|
|
62
|
+
actions,
|
|
63
|
+
blocks,
|
|
64
|
+
icons,
|
|
65
|
+
operators,
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
</Suspense>
|
|
65
69
|
)}
|
|
66
70
|
</Reload>
|
|
67
71
|
);
|
|
@@ -21,7 +21,7 @@ const typeColors = {
|
|
|
21
21
|
ConfigWarning: '#d48806',
|
|
22
22
|
PluginError: '#531dab',
|
|
23
23
|
ServiceError: '#096dd9',
|
|
24
|
-
|
|
24
|
+
LowdefyInternalError: '#cf1322',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
function getTypeColor(type) {
|
|
@@ -49,7 +49,7 @@ const ErrorItem = ({ type, message, source }) => {
|
|
|
49
49
|
>
|
|
50
50
|
{type}
|
|
51
51
|
</span>
|
|
52
|
-
<p style={{ fontSize: 14, margin: '4px 0' }}>{message}</p>
|
|
52
|
+
<p style={{ fontSize: 14, margin: '4px 0', fontFamily: 'monospace' }}>{message}</p>
|
|
53
53
|
{source && <p style={{ fontSize: 13, color: '#8c8c8c', margin: 0 }}>{source}</p>}
|
|
54
54
|
</div>
|
|
55
55
|
);
|
|
@@ -67,7 +67,8 @@ const BuildErrorPage = ({ errors, message, source }) => {
|
|
|
67
67
|
flexDirection: 'column',
|
|
68
68
|
alignItems: 'center',
|
|
69
69
|
justifyContent: 'center',
|
|
70
|
-
fontFamily:
|
|
70
|
+
fontFamily:
|
|
71
|
+
"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
|
|
71
72
|
padding: '0 24px',
|
|
72
73
|
}}
|
|
73
74
|
>
|
|
@@ -0,0 +1,74 @@
|
|
|
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 from 'react';
|
|
18
|
+
|
|
19
|
+
const BuildingPage = () => {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
style={{
|
|
23
|
+
height: '100vh',
|
|
24
|
+
textAlign: 'center',
|
|
25
|
+
display: 'flex',
|
|
26
|
+
flexDirection: 'column',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
fontFamily:
|
|
30
|
+
"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<style>
|
|
34
|
+
{`
|
|
35
|
+
@keyframes building-progress {
|
|
36
|
+
0% { transform: translateX(-100%); }
|
|
37
|
+
100% { transform: translateX(100%); }
|
|
38
|
+
}
|
|
39
|
+
`}
|
|
40
|
+
</style>
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
position: 'fixed',
|
|
44
|
+
top: 0,
|
|
45
|
+
left: 0,
|
|
46
|
+
width: '100%',
|
|
47
|
+
height: 3,
|
|
48
|
+
backgroundColor: '#f0f0f0',
|
|
49
|
+
overflow: 'hidden',
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<div
|
|
53
|
+
style={{
|
|
54
|
+
width: '40%',
|
|
55
|
+
height: '100%',
|
|
56
|
+
backgroundColor: '#1890ff',
|
|
57
|
+
animation: 'building-progress 1.5s ease-in-out infinite',
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
<div
|
|
62
|
+
style={{
|
|
63
|
+
verticalAlign: 'middle',
|
|
64
|
+
display: 'inline-block',
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<h3>Building page...</h3>
|
|
68
|
+
<p>The page will appear when the build completes.</p>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default BuildingPage;
|
|
@@ -0,0 +1,50 @@
|
|
|
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 from 'react';
|
|
18
|
+
|
|
19
|
+
const InstallingPluginsPage = ({ packages }) => {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
style={{
|
|
23
|
+
height: '100vh',
|
|
24
|
+
textAlign: 'center',
|
|
25
|
+
display: 'flex',
|
|
26
|
+
flexDirection: 'column',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
fontFamily:
|
|
30
|
+
"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<div
|
|
34
|
+
style={{
|
|
35
|
+
verticalAlign: 'middle',
|
|
36
|
+
display: 'inline-block',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
<h3>Installing Plugin Packages</h3>
|
|
40
|
+
<p>
|
|
41
|
+
This page requires packages that are not yet installed:{' '}
|
|
42
|
+
<strong>{(packages ?? []).join(', ')}</strong>.
|
|
43
|
+
</p>
|
|
44
|
+
<p>The server will restart automatically. The page will reload when ready.</p>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default InstallingPluginsPage;
|
package/lib/client/Page.js
CHANGED
|
@@ -18,6 +18,7 @@ import React from 'react';
|
|
|
18
18
|
import Client from '@lowdefy/client';
|
|
19
19
|
|
|
20
20
|
import BuildErrorPage from './BuildErrorPage.js';
|
|
21
|
+
import InstallingPluginsPage from './InstallingPluginsPage.js';
|
|
21
22
|
import RestartingPage from './RestartingPage.js';
|
|
22
23
|
import usePageConfig from './utils/usePageConfig.js';
|
|
23
24
|
|
|
@@ -47,6 +48,9 @@ const Page = ({
|
|
|
47
48
|
/>
|
|
48
49
|
);
|
|
49
50
|
}
|
|
51
|
+
if (pageConfig.installing) {
|
|
52
|
+
return <InstallingPluginsPage packages={pageConfig.packages} />;
|
|
53
|
+
}
|
|
50
54
|
if (resetContext.restarting) {
|
|
51
55
|
return <RestartingPage />;
|
|
52
56
|
}
|
|
@@ -27,9 +27,7 @@ async function request({ url, method = 'GET', body }) {
|
|
|
27
27
|
}
|
|
28
28
|
if (!res.ok) {
|
|
29
29
|
const body = await res.json();
|
|
30
|
-
|
|
31
|
-
console.log(body);
|
|
32
|
-
throw new Error(body.message || 'Request error');
|
|
30
|
+
throw new Error(body?.['~e']?.message ?? body?.message ?? 'Request error');
|
|
33
31
|
}
|
|
34
32
|
return res.json();
|
|
35
33
|
}
|
package/lib/server/apiWrapper.js
CHANGED
|
@@ -17,6 +17,7 @@ import fs from 'fs';
|
|
|
17
17
|
import path from 'path';
|
|
18
18
|
import { createApiContext } from '@lowdefy/api';
|
|
19
19
|
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
|
20
|
+
import { serializer } from '@lowdefy/helpers';
|
|
20
21
|
import { v4 as uuid } from 'uuid';
|
|
21
22
|
|
|
22
23
|
import config from '../build/config.js';
|
|
@@ -24,13 +25,11 @@ import connections from '../../build/plugins/connections.js';
|
|
|
24
25
|
import createLogger from './log/createLogger.js';
|
|
25
26
|
import fileCache from './fileCache.js';
|
|
26
27
|
import getServerSession from './auth/getServerSession.js';
|
|
27
|
-
import
|
|
28
|
+
import createHandleError from './log/createHandleError.js';
|
|
28
29
|
import logRequest from './log/logRequest.js';
|
|
29
30
|
import operators from '../../build/plugins/operators/server.js';
|
|
30
31
|
import staticJsMap from '../../build/plugins/operators/serverJsMap.js';
|
|
31
32
|
import getAuthOptions from './auth/getAuthOptions.js';
|
|
32
|
-
import loggerConfig from '../build/logger.js';
|
|
33
|
-
import setSentryUser from './sentry/setSentryUser.js';
|
|
34
33
|
|
|
35
34
|
const secrets = getSecretsFromEnv();
|
|
36
35
|
|
|
@@ -73,6 +72,9 @@ function apiWrapper(handler) {
|
|
|
73
72
|
fileCache,
|
|
74
73
|
headers: req?.headers,
|
|
75
74
|
jsMap,
|
|
75
|
+
handleError: async (err) => {
|
|
76
|
+
console.error(err);
|
|
77
|
+
},
|
|
76
78
|
logger: console,
|
|
77
79
|
operators,
|
|
78
80
|
req,
|
|
@@ -80,15 +82,11 @@ function apiWrapper(handler) {
|
|
|
80
82
|
secrets,
|
|
81
83
|
};
|
|
82
84
|
try {
|
|
83
|
-
context.logger = createLogger(
|
|
85
|
+
context.logger = createLogger();
|
|
86
|
+
context.handleError = createHandleError({ context });
|
|
84
87
|
context.authOptions = getAuthOptions(context);
|
|
85
88
|
if (!req.url.startsWith('/api/auth')) {
|
|
86
89
|
context.session = await getServerSession(context);
|
|
87
|
-
// Set Sentry user context for authenticated requests
|
|
88
|
-
setSentryUser({
|
|
89
|
-
user: context.session?.user,
|
|
90
|
-
sentryConfig: loggerConfig.sentry,
|
|
91
|
-
});
|
|
92
90
|
}
|
|
93
91
|
createApiContext(context);
|
|
94
92
|
logRequest({ context });
|
|
@@ -97,8 +95,14 @@ function apiWrapper(handler) {
|
|
|
97
95
|
// TODO: Log response time?
|
|
98
96
|
return response;
|
|
99
97
|
} catch (error) {
|
|
100
|
-
await
|
|
101
|
-
|
|
98
|
+
await context.handleError(error);
|
|
99
|
+
const serialized = serializer.serialize(error);
|
|
100
|
+
if (serialized?.['~e']) {
|
|
101
|
+
delete serialized['~e'].received;
|
|
102
|
+
delete serialized['~e'].stack;
|
|
103
|
+
delete serialized['~e'].configKey;
|
|
104
|
+
}
|
|
105
|
+
res.status(500).json(serialized);
|
|
102
106
|
}
|
|
103
107
|
};
|
|
104
108
|
}
|
|
@@ -28,7 +28,7 @@ async function getMockSession() {
|
|
|
28
28
|
try {
|
|
29
29
|
mockUser = JSON.parse(mockUserJson);
|
|
30
30
|
} catch (error) {
|
|
31
|
-
throw new Error(
|
|
31
|
+
throw new Error('Invalid JSON in LOWDEFY_DEV_USER environment variable.', { cause: error });
|
|
32
32
|
}
|
|
33
33
|
} else {
|
|
34
34
|
mockUser = authJson.dev?.mockUser;
|
|
@@ -22,8 +22,12 @@ import { buildPageJit, createContext } from '@lowdefy/build/dev';
|
|
|
22
22
|
import createLogger from './log/createLogger.js';
|
|
23
23
|
import PageCache from './pageCache.mjs';
|
|
24
24
|
|
|
25
|
-
const jitLogger = createLogger({
|
|
25
|
+
const jitLogger = createLogger({ name: 'jit-build' });
|
|
26
26
|
|
|
27
|
+
function formatDuration(ms) {
|
|
28
|
+
if (ms < 1000) return `${ms}ms`;
|
|
29
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
30
|
+
}
|
|
27
31
|
const pageCache = new PageCache();
|
|
28
32
|
let cachedRegistryMtime = null;
|
|
29
33
|
let cachedRegistry = null;
|
|
@@ -40,21 +44,17 @@ function readJsonFile(filePath) {
|
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
function checkPageInvalidations(buildDirectory) {
|
|
43
|
-
const
|
|
47
|
+
const invalidatePath = path.join(buildDirectory, 'invalidatePages');
|
|
44
48
|
try {
|
|
45
|
-
const stat = fs.statSync(
|
|
49
|
+
const stat = fs.statSync(invalidatePath);
|
|
46
50
|
if (lastInvalidationMtime && stat.mtimeMs === lastInvalidationMtime) {
|
|
47
51
|
return;
|
|
48
52
|
}
|
|
49
53
|
lastInvalidationMtime = stat.mtimeMs;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (Array.isArray(pageIds) && pageIds.length > 0) {
|
|
53
|
-
pageCache.invalidatePages(pageIds);
|
|
54
|
-
cachedBuildContext = null;
|
|
55
|
-
}
|
|
54
|
+
pageCache.invalidateAll();
|
|
55
|
+
cachedBuildContext = null;
|
|
56
56
|
} catch {
|
|
57
|
-
// File doesn't exist yet
|
|
57
|
+
// File doesn't exist yet — nothing to invalidate
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -85,10 +85,14 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
85
85
|
const jsMap = readJsonFile(path.join(buildDirectory, 'jsMap.json')) ?? { client: {}, server: {} };
|
|
86
86
|
const connectionIds = readJsonFile(path.join(buildDirectory, 'connectionIds.json')) ?? [];
|
|
87
87
|
|
|
88
|
+
const customTypesMap = readJsonFile(path.join(buildDirectory, 'customTypesMap.json')) ?? {};
|
|
89
|
+
|
|
88
90
|
cachedBuildContext = createContext({
|
|
91
|
+
customTypesMap,
|
|
89
92
|
directories: {
|
|
90
93
|
build: buildDirectory,
|
|
91
94
|
config: configDirectory,
|
|
95
|
+
server: path.resolve(buildDirectory, '..'),
|
|
92
96
|
},
|
|
93
97
|
logger: jitLogger,
|
|
94
98
|
stage: 'dev',
|
|
@@ -103,6 +107,11 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
103
107
|
cachedBuildContext.connectionIds.add(id);
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
// Load installed packages snapshot from skeleton build for missing-package detection
|
|
111
|
+
const installedPluginPackages =
|
|
112
|
+
readJsonFile(path.join(buildDirectory, 'installedPluginPackages.json')) ?? [];
|
|
113
|
+
cachedBuildContext.installedPluginPackages = new Set(installedPluginPackages);
|
|
114
|
+
|
|
106
115
|
return cachedBuildContext;
|
|
107
116
|
}
|
|
108
117
|
|
|
@@ -123,16 +132,27 @@ async function buildPageIfNeeded({ pageId, buildDirectory, configDirectory }) {
|
|
|
123
132
|
return true;
|
|
124
133
|
}
|
|
125
134
|
|
|
135
|
+
jitLogger.info({ spin: true }, `Building page "${pageId}"...`);
|
|
136
|
+
const startTime = Date.now();
|
|
126
137
|
try {
|
|
127
138
|
const context = getBuildContext(buildDirectory, configDirectory);
|
|
128
|
-
const
|
|
129
|
-
await buildPageJit({
|
|
139
|
+
const result = await buildPageJit({
|
|
130
140
|
pageId,
|
|
131
141
|
pageRegistry: registry,
|
|
132
142
|
context,
|
|
133
143
|
});
|
|
144
|
+
if (result && result.installing) {
|
|
145
|
+
jitLogger.info(
|
|
146
|
+
`Installing plugin packages for page "${pageId}": ${result.packages.join(', ')}. ` +
|
|
147
|
+
'The page will be available after the server restarts.'
|
|
148
|
+
);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
134
151
|
pageCache.markCompiled(pageId);
|
|
135
|
-
jitLogger.info(
|
|
152
|
+
jitLogger.info(
|
|
153
|
+
{ succeed: true, color: 'white' },
|
|
154
|
+
`Built page "${pageId}" in ${formatDuration(Date.now() - startTime)}.`
|
|
155
|
+
);
|
|
136
156
|
return true;
|
|
137
157
|
} finally {
|
|
138
158
|
pageCache.releaseBuildLock(pageId);
|
|
@@ -140,4 +160,3 @@ async function buildPageIfNeeded({ pageId, buildDirectory, configDirectory }) {
|
|
|
140
160
|
}
|
|
141
161
|
|
|
142
162
|
export default buildPageIfNeeded;
|
|
143
|
-
export { pageCache };
|
|
@@ -0,0 +1,47 @@
|
|
|
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 { LowdefyInternalError, loadAndResolveErrorLocation } from '@lowdefy/errors';
|
|
18
|
+
|
|
19
|
+
function createHandleError({ context }) {
|
|
20
|
+
return async function handleError(error) {
|
|
21
|
+
try {
|
|
22
|
+
// For internal lowdefy errors, don't resolve config location
|
|
23
|
+
const location =
|
|
24
|
+
error instanceof LowdefyInternalError
|
|
25
|
+
? null
|
|
26
|
+
: await loadAndResolveErrorLocation({
|
|
27
|
+
error,
|
|
28
|
+
readConfigFile: context.readConfigFile,
|
|
29
|
+
configDirectory: context.configDirectory,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Attach resolved location to error for display layer
|
|
33
|
+
if (location) {
|
|
34
|
+
error.source = location.source;
|
|
35
|
+
error.config = location.config;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
context.logger.error(error);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error(error);
|
|
41
|
+
console.error('An error occurred while logging the error.');
|
|
42
|
+
console.error(e);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default createHandleError;
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { createNodeLogger
|
|
17
|
+
import { createNodeLogger } from '@lowdefy/logger/node';
|
|
18
18
|
|
|
19
19
|
const logger = createNodeLogger({
|
|
20
|
-
name: '
|
|
20
|
+
name: 'lowdefy_server_dev',
|
|
21
21
|
level: process.env.LOWDEFY_LOG_LEVEL ?? 'info',
|
|
22
22
|
base: { pid: undefined, hostname: undefined },
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
function createLogger(metadata = {}) {
|
|
26
|
-
return
|
|
26
|
+
return logger.child(metadata);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export default createLogger;
|
package/lib/server/pageCache.mjs
CHANGED
|
@@ -18,7 +18,6 @@ class PageCache {
|
|
|
18
18
|
constructor() {
|
|
19
19
|
this.compiledPages = new Set();
|
|
20
20
|
this.buildLocks = new Map();
|
|
21
|
-
this.skeletonLock = null;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
isCompiled(pageId) {
|
|
@@ -30,11 +29,6 @@ class PageCache {
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
async acquireBuildLock(pageId) {
|
|
33
|
-
// Wait for any skeleton rebuild first
|
|
34
|
-
if (this.skeletonLock) {
|
|
35
|
-
await this.skeletonLock;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
32
|
// If page build already in progress, wait for it
|
|
39
33
|
if (this.buildLocks.has(pageId)) {
|
|
40
34
|
await this.buildLocks.get(pageId);
|
|
@@ -59,46 +53,9 @@ class PageCache {
|
|
|
59
53
|
}
|
|
60
54
|
}
|
|
61
55
|
|
|
62
|
-
async acquireSkeletonLock() {
|
|
63
|
-
// Wait for all in-progress page builds to complete
|
|
64
|
-
await Promise.all(this.buildLocks.values());
|
|
65
|
-
let resolve;
|
|
66
|
-
this.skeletonLock = new Promise((r) => {
|
|
67
|
-
resolve = r;
|
|
68
|
-
});
|
|
69
|
-
this.skeletonLock.resolve = resolve;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
releaseSkeletonLock() {
|
|
73
|
-
if (this.skeletonLock) {
|
|
74
|
-
this.skeletonLock.resolve();
|
|
75
|
-
this.skeletonLock = null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
56
|
invalidateAll() {
|
|
80
57
|
this.compiledPages.clear();
|
|
81
58
|
}
|
|
82
|
-
|
|
83
|
-
invalidatePages(pageIds) {
|
|
84
|
-
for (const pageId of pageIds) {
|
|
85
|
-
this.compiledPages.delete(pageId);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
invalidateByFiles(changedFiles, fileDependencyMap) {
|
|
90
|
-
const affectedPages = new Set();
|
|
91
|
-
for (const filePath of changedFiles) {
|
|
92
|
-
const pageIds = fileDependencyMap.get(filePath);
|
|
93
|
-
if (pageIds) {
|
|
94
|
-
for (const pageId of pageIds) {
|
|
95
|
-
affectedPages.add(pageId);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
this.invalidatePages(affectedPages);
|
|
100
|
-
return affectedPages;
|
|
101
|
-
}
|
|
102
59
|
}
|
|
103
60
|
|
|
104
61
|
export default PageCache;
|