mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-03-31 15:20:32 +08:00
Merge pull request #1187 from lowdefy/server-dev-fix
Client reload fixes and display message
This commit is contained in:
commit
440a1b21d1
1
.pnp.cjs
generated
1
.pnp.cjs
generated
@ -3522,6 +3522,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
"packageLocation": "./packages/server/",
|
||||
"packageDependencies": [
|
||||
["@lowdefy/server", "workspace:packages/server"],
|
||||
["@lowdefy/actions-core", "workspace:packages/plugins/actions/actions-core"],
|
||||
["@lowdefy/api", "workspace:packages/api"],
|
||||
["@lowdefy/blocks-antd", "workspace:packages/plugins/blocks/blocks-antd"],
|
||||
["@lowdefy/blocks-basic", "workspace:packages/plugins/blocks/blocks-basic"],
|
||||
|
@ -54,6 +54,7 @@
|
||||
"start:server:docs": "yarn workspace @lowdefy/server build:lowdefy --config-directory ../docs && yarn && yarn workspace @lowdefy/server build:next && yarn workspace @lowdefy/server start",
|
||||
"start:server:next-dev:app": "yarn start:cli:build:app && yarn && yarn workspace @lowdefy/server dev",
|
||||
"start:server:next-dev:docs": "yarn start:cli:build:docs && yarn && yarn workspace @lowdefy/server dev",
|
||||
"start:server-dev:next-dev:app": "yarn workspace lowdefy start build --config-directory ../../app --server-directory ../server-dev --output-directory ../ && yarn workspace @lowdefy/server-dev next dev",
|
||||
"test": "lerna run test",
|
||||
"test-ci": "yarn test --ignore='@lowdefy/engine' --ignore='@lowdefy/format' --ignore='@lowdefy/blocks-*' --ignore='@lowdefy/plugin-aws'"
|
||||
},
|
||||
|
@ -49,6 +49,7 @@ function buildTypes({ components, context }) {
|
||||
// Add loaders and basic
|
||||
basicTypes.blocks.forEach((block) => typeCounters.blocks.increment(block));
|
||||
loaderTypes.blocks.forEach((block) => typeCounters.blocks.increment(block));
|
||||
typeCounters.blocks.increment('Message'); // Used for DisplayMessage in @lowdefy/client
|
||||
|
||||
components.types = {
|
||||
actions: {},
|
||||
|
@ -18,47 +18,66 @@ import React from 'react';
|
||||
|
||||
import Block from './block/Block.js';
|
||||
import Context from './Context.js';
|
||||
import DisplayMessage from './DisplayMessage.js';
|
||||
import Head from './Head.js';
|
||||
import ProgressBarController from './ProgressBarController.js';
|
||||
|
||||
import initLowdefyContext from './initLowdefyContext.js';
|
||||
|
||||
const Client = ({ Components, config, router, stage, types, window }) => {
|
||||
const lowdefy = initLowdefyContext({ Components, config, router, types, stage, window });
|
||||
|
||||
const Client = ({
|
||||
Components,
|
||||
config,
|
||||
resetContext = { reset: false, setReset: () => undefined },
|
||||
router,
|
||||
stage,
|
||||
types,
|
||||
window,
|
||||
}) => {
|
||||
const lowdefy = initLowdefyContext({ Components, config, router, stage, types, window });
|
||||
return (
|
||||
<ProgressBarController
|
||||
id="page-loader"
|
||||
key={config.pageConfig.id}
|
||||
ProgressBar={lowdefy._internal.blockComponents.ProgressBar}
|
||||
lowdefy={lowdefy}
|
||||
content={{
|
||||
content: (progress) => (
|
||||
<Context config={config.pageConfig} lowdefy={lowdefy} progress={progress}>
|
||||
{(context) => {
|
||||
return (
|
||||
<>
|
||||
<Head
|
||||
Component={Components.Head}
|
||||
properties={
|
||||
context._internal.RootBlocks.map[config.pageConfig.id].eval.properties
|
||||
}
|
||||
/>
|
||||
<Block
|
||||
block={context._internal.RootBlocks.map[config.pageConfig.id]}
|
||||
Blocks={context._internal.RootBlocks}
|
||||
context={context}
|
||||
lowdefy={lowdefy}
|
||||
progress={progress}
|
||||
parentLoading={false}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Context>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
<ProgressBarController
|
||||
id="lowdefy-progress-bar"
|
||||
key={`${config.pageConfig.id}-progress-bar`}
|
||||
lowdefy={lowdefy}
|
||||
resetContext={resetContext}
|
||||
/>
|
||||
<DisplayMessage
|
||||
id="lowdefy-display-message"
|
||||
key={`${config.pageConfig.id}-display-message`}
|
||||
Component={lowdefy._internal.blockComponents.Message}
|
||||
methods={{
|
||||
registerMethod: (_, method) => {
|
||||
lowdefy._internal.displayMessage = method;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Context
|
||||
key={config.pageConfig.id}
|
||||
config={config.pageConfig}
|
||||
lowdefy={lowdefy}
|
||||
resetContext={resetContext}
|
||||
>
|
||||
{(context) => {
|
||||
if (!context._internal.onInitDone) return '';
|
||||
return (
|
||||
<>
|
||||
<Head
|
||||
Component={Components.Head}
|
||||
properties={context._internal.RootBlocks.map[config.pageConfig.id].eval.properties}
|
||||
/>
|
||||
<Block
|
||||
block={context._internal.RootBlocks.map[config.pageConfig.id]}
|
||||
Blocks={context._internal.RootBlocks}
|
||||
context={context}
|
||||
lowdefy={lowdefy}
|
||||
parentLoading={false}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Context>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -19,21 +19,21 @@ import getContext from '@lowdefy/engine';
|
||||
|
||||
import MountEvents from './MountEvents.js';
|
||||
|
||||
const Context = ({ children, config, lowdefy, progress }) => {
|
||||
const context = getContext({ config, lowdefy });
|
||||
const Context = ({ children, config, lowdefy, resetContext }) => {
|
||||
const context = getContext({ config, lowdefy, resetContext });
|
||||
return (
|
||||
<MountEvents
|
||||
context={context}
|
||||
triggerEvent={async () => {
|
||||
await context._internal.runOnInit(() => {
|
||||
progress.dispatch({
|
||||
lowdefy._internal.progress.dispatch({
|
||||
type: 'increment',
|
||||
});
|
||||
});
|
||||
}}
|
||||
triggerEventAsync={() => {
|
||||
context._internal.runOnInitAsync(() => {
|
||||
progress.dispatch({
|
||||
lowdefy._internal.progress.dispatch({
|
||||
type: 'increment',
|
||||
});
|
||||
});
|
||||
|
35
packages/client/src/DisplayMessage.js
Normal file
35
packages/client/src/DisplayMessage.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2020-2022 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { makeCssClass } from '@lowdefy/block-utils';
|
||||
|
||||
const DisplayMessage = ({ Component, id, methods }) => {
|
||||
return (
|
||||
<Component
|
||||
blockId={id}
|
||||
key={id}
|
||||
methods={{
|
||||
makeCssClass,
|
||||
registerMethod: methods.registerMethod,
|
||||
triggerEvent: () => undefined,
|
||||
}}
|
||||
properties={{}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DisplayMessage;
|
@ -21,6 +21,7 @@ const MountEvents = ({ children, context, triggerEvent, triggerEventAsync }) =>
|
||||
const [error, setError] = useState(null);
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
setLoading(true);
|
||||
const mount = async () => {
|
||||
try {
|
||||
await triggerEvent();
|
||||
|
@ -19,28 +19,54 @@ import { makeCssClass } from '@lowdefy/block-utils';
|
||||
|
||||
const initialState = {
|
||||
progress: 0,
|
||||
onMounts: 0,
|
||||
};
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case 'increment':
|
||||
return { progress: state.progress + (100 - state.progress) / 3 };
|
||||
return {
|
||||
...state,
|
||||
progress: state.progress + (100 - state.progress) / 3,
|
||||
};
|
||||
case 'increment-on-mount':
|
||||
return {
|
||||
...state,
|
||||
onMounts: state.onMounts + 1,
|
||||
};
|
||||
case 'auto-increment':
|
||||
return { progress: state.progress + (100 - state.progress) / 200 };
|
||||
return {
|
||||
...state,
|
||||
progress: state.progress + (100 - state.progress) / 200,
|
||||
};
|
||||
case 'done':
|
||||
return { progress: 100 };
|
||||
return {
|
||||
progress: state.onMounts - 1 === 0 ? 100 : state.progress,
|
||||
onMounts: state.onMounts - 1,
|
||||
};
|
||||
case 'reset':
|
||||
return {
|
||||
progress: 0,
|
||||
onMounts: 0,
|
||||
};
|
||||
default:
|
||||
throw new Error('Invalid action type for ProgressBarController reducer.');
|
||||
}
|
||||
}
|
||||
|
||||
const ProgressBarController = ({ id, ProgressBar, content, lowdefy }) => {
|
||||
const ProgressBarController = ({ id, lowdefy, resetContext }) => {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
const ProgressBar = lowdefy._internal.blockComponents.ProgressBar;
|
||||
lowdefy._internal.progress.state = state;
|
||||
lowdefy._internal.progress.dispatch = dispatch;
|
||||
useEffect(() => {
|
||||
const timer =
|
||||
state.progress < 95 && setInterval(() => dispatch({ type: 'auto-increment' }), 500);
|
||||
return () => clearInterval(timer);
|
||||
}, [state]);
|
||||
if (resetContext.reset && state.progress === 100) {
|
||||
dispatch({ type: 'reset' });
|
||||
}
|
||||
return (
|
||||
<ProgressBar
|
||||
basePath={lowdefy.basePath}
|
||||
@ -51,9 +77,6 @@ const ProgressBarController = ({ id, ProgressBar, content, lowdefy }) => {
|
||||
pageId={lowdefy.pageId}
|
||||
properties={state}
|
||||
user={lowdefy.user}
|
||||
content={{
|
||||
content: () => content.content({ state, dispatch }),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -20,14 +20,7 @@ import CategorySwitch from './CategorySwitch.js';
|
||||
import ErrorBoundary from '../ErrorBoundary.js';
|
||||
import MountEvents from '../MountEvents.js';
|
||||
|
||||
const Block = ({
|
||||
block,
|
||||
Blocks,
|
||||
context,
|
||||
lowdefy,
|
||||
parentLoading,
|
||||
progress = { dispatch: () => {} },
|
||||
}) => {
|
||||
const Block = ({ block, Blocks, context, lowdefy, parentLoading }) => {
|
||||
const [updates, setUpdate] = useState(0);
|
||||
lowdefy._internal.updaters[block.id] = () => setUpdate(updates + 1);
|
||||
|
||||
@ -36,10 +29,14 @@ const Block = ({
|
||||
<MountEvents
|
||||
context={context}
|
||||
triggerEvent={async () => {
|
||||
context._internal.lowdefy._internal.progress.dispatch({
|
||||
type: 'increment-on-mount',
|
||||
id: block.id,
|
||||
});
|
||||
await block.triggerEvent({
|
||||
name: 'onMount',
|
||||
progress: () => {
|
||||
progress.dispatch({
|
||||
lowdefy._internal.progress.dispatch({
|
||||
type: 'increment',
|
||||
});
|
||||
},
|
||||
@ -49,12 +46,12 @@ const Block = ({
|
||||
block.triggerEvent({
|
||||
name: 'onMountAsync',
|
||||
progress: () => {
|
||||
progress.dispatch({
|
||||
lowdefy._internal.progress.dispatch({
|
||||
type: 'increment',
|
||||
});
|
||||
},
|
||||
});
|
||||
progress.dispatch({
|
||||
lowdefy._internal.progress.dispatch({
|
||||
type: 'done',
|
||||
});
|
||||
}}
|
||||
|
@ -17,9 +17,9 @@
|
||||
import { urlQuery } from '@lowdefy/helpers';
|
||||
|
||||
import callRequest from './callRequest.js';
|
||||
import setupLink from './setupLink.js';
|
||||
import createLinkComponent from './createLinkComponent.js';
|
||||
import createIcon from './createIcon.js';
|
||||
import createLinkComponent from './createLinkComponent.js';
|
||||
import setupLink from './setupLink.js';
|
||||
|
||||
const lowdefy = {
|
||||
_internal: {
|
||||
@ -31,6 +31,12 @@ const lowdefy = {
|
||||
return () => undefined;
|
||||
},
|
||||
link: () => undefined,
|
||||
progress: {
|
||||
state: {
|
||||
progress: 0,
|
||||
},
|
||||
dispatch: () => undefined,
|
||||
},
|
||||
},
|
||||
contexts: {},
|
||||
inputs: {},
|
||||
|
@ -91,8 +91,13 @@ class Blocks {
|
||||
block.styleEval = {};
|
||||
block.validationEval = {};
|
||||
block.visibleEval = {};
|
||||
|
||||
block.meta = this.context._internal.lowdefy._internal.blockComponents[block.type].meta;
|
||||
try {
|
||||
block.meta = this.context._internal.lowdefy._internal.blockComponents[block.type].meta;
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Block type ${block.type} not found at ${block.blockId}. Check your plugins to make sure the block is installed. For more info, see https://docs.lowdefy.com/plugins.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!type.isNone(block.areas)) {
|
||||
block.areasLayout = {};
|
||||
|
@ -55,16 +55,21 @@ const blockData = ({
|
||||
visible,
|
||||
});
|
||||
|
||||
function getContext({ config, lowdefy, development = false }) {
|
||||
function getContext({
|
||||
config,
|
||||
lowdefy,
|
||||
resetContext = { reset: false, setReset: () => undefined },
|
||||
}) {
|
||||
if (!config) {
|
||||
throw new Error('A page must be provided to get context.');
|
||||
}
|
||||
const { id } = config;
|
||||
if (lowdefy.contexts[id] && !development) {
|
||||
if (lowdefy.contexts[id] && !resetContext.reset) {
|
||||
// memoize context if already created, eg between page transitions, unless the reset flag is raised
|
||||
lowdefy.contexts[id]._internal.update();
|
||||
return lowdefy.contexts[id];
|
||||
}
|
||||
|
||||
resetContext.setReset(false); // lower context reset flag.
|
||||
if (!lowdefy.inputs[id]) {
|
||||
lowdefy.inputs[id] = {};
|
||||
}
|
||||
@ -100,6 +105,7 @@ function getContext({ config, lowdefy, development = false }) {
|
||||
name: 'onInit',
|
||||
progress,
|
||||
});
|
||||
_internal.update();
|
||||
_internal.State.freezeState();
|
||||
_internal.onInitDone = true;
|
||||
}
|
||||
@ -113,6 +119,7 @@ function getContext({ config, lowdefy, development = false }) {
|
||||
_internal.onInitAsyncDone = true;
|
||||
}
|
||||
};
|
||||
ctx._internal.update();
|
||||
lowdefy.contexts[id] = ctx;
|
||||
return ctx;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
import React from 'react';
|
||||
import { blockDefaultProps } from '@lowdefy/block-utils';
|
||||
|
||||
const ProgressBar = ({ blockId, methods, style, properties, content }) => {
|
||||
const ProgressBar = ({ blockId, methods, style, properties }) => {
|
||||
const {
|
||||
progress = 30,
|
||||
height = 4,
|
||||
@ -28,31 +28,28 @@ const ProgressBar = ({ blockId, methods, style, properties, content }) => {
|
||||
} = properties;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
id={blockId}
|
||||
className={methods.makeCssClass(style)}
|
||||
style={{
|
||||
'--height': height + 'px',
|
||||
'--progress': progress + '%',
|
||||
'--transition': 'all ' + transitionTime + 'ms ease',
|
||||
'--opacity': progress < 100 ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<div className="progress-bar-container">
|
||||
<div className="progress-bar-loader">
|
||||
{shadow ? <div className="progress-bar-shadow" /> : null}
|
||||
</div>
|
||||
<div
|
||||
id={blockId}
|
||||
className={methods.makeCssClass(style)}
|
||||
style={{
|
||||
'--height': height + 'px',
|
||||
'--progress': progress + '%',
|
||||
'--transition': 'all ' + transitionTime + 'ms ease',
|
||||
'--opacity': progress < 100 ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<div className="progress-bar-container">
|
||||
<div className="progress-bar-loader">
|
||||
{shadow ? <div className="progress-bar-shadow" /> : null}
|
||||
</div>
|
||||
</div>
|
||||
{content.content && content.content()}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProgressBar.defaultProps = blockDefaultProps;
|
||||
ProgressBar.meta = {
|
||||
category: 'container',
|
||||
category: 'display',
|
||||
icons: [],
|
||||
styles: ['blocks/ProgressBar/style.less'],
|
||||
};
|
||||
|
@ -38,23 +38,27 @@ const App = () => {
|
||||
const { redirect, pageId } = setPageId(router, rootConfig);
|
||||
if (redirect) {
|
||||
router.push(`/${pageId}`);
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
<Reload basePath={router.basePath}>
|
||||
<Page
|
||||
Components={{ Head, Link }}
|
||||
config={{
|
||||
rootConfig,
|
||||
}}
|
||||
pageId={pageId}
|
||||
router={router}
|
||||
types={{
|
||||
actions,
|
||||
blocks,
|
||||
icons,
|
||||
operators,
|
||||
}}
|
||||
/>
|
||||
{(resetContext) => (
|
||||
<Page
|
||||
Components={{ Head, Link }}
|
||||
config={{
|
||||
rootConfig,
|
||||
}}
|
||||
pageId={pageId}
|
||||
resetContext={resetContext}
|
||||
router={router}
|
||||
types={{
|
||||
actions,
|
||||
blocks,
|
||||
icons,
|
||||
operators,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Reload>
|
||||
);
|
||||
};
|
||||
|
@ -15,16 +15,20 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Client from '@lowdefy/client';
|
||||
|
||||
import RestartingPage from './RestartingPage.js';
|
||||
import usePageConfig from './utils/usePageConfig.js';
|
||||
|
||||
const Page = ({ Components, config, pageId, router, types }) => {
|
||||
const Page = ({ Components, config, pageId, resetContext, router, types }) => {
|
||||
const { data: pageConfig } = usePageConfig(pageId, router.basePath);
|
||||
if (!pageConfig) {
|
||||
router.replace(`/404`);
|
||||
return '';
|
||||
}
|
||||
if (resetContext.restarting) {
|
||||
return <RestartingPage />;
|
||||
}
|
||||
return (
|
||||
<Client
|
||||
Components={Components}
|
||||
@ -32,6 +36,7 @@ const Page = ({ Components, config, pageId, router, types }) => {
|
||||
...config,
|
||||
pageConfig,
|
||||
}}
|
||||
resetContext={resetContext}
|
||||
router={router}
|
||||
stage="dev"
|
||||
types={types}
|
||||
|
@ -14,22 +14,31 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import useMutateCache from './utils/useMutateCache.js';
|
||||
import waitForRestartedServer from './utils/waitForRestartedServer.js';
|
||||
|
||||
const Reload = ({ children, basePath }) => {
|
||||
const [reset, setReset] = useState(false);
|
||||
const [restarting, setRestarting] = useState(false);
|
||||
const mutateCache = useMutateCache(basePath);
|
||||
useEffect(() => {
|
||||
const sse = new EventSource(`${basePath}/api/reload`);
|
||||
|
||||
sse.addEventListener('reload', () => {
|
||||
mutateCache();
|
||||
console.log('Reloaded config.');
|
||||
// add a update delay to prevent rerender before server is shut down for rebuild, ideally we don't want to do this.
|
||||
// TODO: We need to pass a flag when a rebuild will happen so that client does not trigger render.
|
||||
setTimeout(async () => {
|
||||
await mutateCache();
|
||||
setReset(true);
|
||||
console.log('Reloaded config.');
|
||||
}, 600);
|
||||
});
|
||||
|
||||
sse.onerror = () => {
|
||||
setRestarting(true);
|
||||
console.log('Rebuilding Lowdefy App.');
|
||||
sse.close();
|
||||
waitForRestartedServer(basePath);
|
||||
};
|
||||
@ -37,7 +46,7 @@ const Reload = ({ children, basePath }) => {
|
||||
sse.close();
|
||||
};
|
||||
}, []);
|
||||
return <>{children}</>;
|
||||
return <>{children({ reset, setReset, restarting })}</>;
|
||||
};
|
||||
|
||||
export default Reload;
|
||||
|
47
packages/server-dev/lib/RestartingPage.js
Normal file
47
packages/server-dev/lib/RestartingPage.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2020-2022 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const RestartingPage = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '100vh',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
verticalAlign: 'middle',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<h3>Rebuilding Lowdefy App</h3>
|
||||
<p>
|
||||
The server is restarting because your configuration changed. The page will reload when
|
||||
ready.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RestartingPage;
|
@ -26,7 +26,7 @@ function waitForRestartedServer(basePath) {
|
||||
} catch (error) {
|
||||
waitForRestartedServer(basePath);
|
||||
}
|
||||
}, 1500);
|
||||
}, 500); // TODO: this ping should be shorter than rerender delay until we can pass a rebuild flag to reload.
|
||||
}
|
||||
|
||||
export default waitForRestartedServer;
|
||||
|
@ -24,6 +24,7 @@ const hashes = {};
|
||||
|
||||
const watchedFiles = [
|
||||
'build/config.json',
|
||||
'build/plugins/actions.js',
|
||||
'build/plugins/blocks.js',
|
||||
'build/plugins/connections.js',
|
||||
'build/plugins/icons.js',
|
||||
|
@ -40,6 +40,7 @@
|
||||
"next": "next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lowdefy/actions-core": "4.0.0-alpha.8",
|
||||
"@lowdefy/api": "4.0.0-alpha.8",
|
||||
"@lowdefy/blocks-antd": "4.0.0-alpha.8",
|
||||
"@lowdefy/blocks-basic": "4.0.0-alpha.8",
|
||||
|
Loading…
x
Reference in New Issue
Block a user