mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-03-19 15:01:06 +08:00
feat: Add server manager and file watcher in reload event stream.
This commit is contained in:
parent
a556eabdbb
commit
8474aaf63c
26
.pnp.cjs
generated
26
.pnp.cjs
generated
@ -5659,6 +5659,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["@lowdefy/engine", "workspace:packages/engine"],
|
||||
["@lowdefy/helpers", "workspace:packages/utils/helpers"],
|
||||
["@lowdefy/layout", "workspace:packages/layout"],
|
||||
["@lowdefy/node-utils", "workspace:packages/utils/node-utils"],
|
||||
["@lowdefy/operators-change-case", "workspace:packages/plugins/operators/operators-change-case"],
|
||||
["@lowdefy/operators-diff", "workspace:packages/plugins/operators/operators-diff"],
|
||||
["@lowdefy/operators-js", "workspace:packages/plugins/operators/operators-js"],
|
||||
@ -5667,6 +5668,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["@lowdefy/operators-uuid", "workspace:packages/plugins/operators/operators-uuid"],
|
||||
["@lowdefy/operators-yaml", "workspace:packages/plugins/operators/operators-yaml"],
|
||||
["@next/eslint-plugin-next", "npm:12.0.4"],
|
||||
["chokidar", "npm:3.5.2"],
|
||||
["less", "npm:4.1.2"],
|
||||
["less-loader", "virtual:003bebd8b7a948d12b44e2c11a621884feb1891eea3645171e827971487f79396db9f7422bc411ccf3f90877e94ec86f5c3da70b96efb5daddb2ee3b35eae5c6#npm:10.2.0"],
|
||||
["next", "virtual:003bebd8b7a948d12b44e2c11a621884feb1891eea3645171e827971487f79396db9f7422bc411ccf3f90877e94ec86f5c3da70b96efb5daddb2ee3b35eae5c6#npm:12.0.3"],
|
||||
@ -5675,7 +5677,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["react", "npm:18.0.0-alpha-327d5c484-20211106"],
|
||||
["react-dom", "virtual:573fe255dffc9c89f4f7aa60da718603753ee98acc55d6772bbd0ebdcf07f9183fb8e54b4f3f2246c538a14ead402db8d2e076039c667d1538702638a0cc87b8#npm:18.0.0-alpha-327d5c484-20211106"],
|
||||
["react-icons", "virtual:003bebd8b7a948d12b44e2c11a621884feb1891eea3645171e827971487f79396db9f7422bc411ccf3f90877e94ec86f5c3da70b96efb5daddb2ee3b35eae5c6#npm:4.3.1"],
|
||||
["swr", "virtual:b951ea20ab6cada5f665e8389a50d828047e6b6f10e6ebaddde1e74a94868ec6ec703ff140742f295ef663cf92da1bc80fe9bbeaab30196cba0e992f38cd19ea#npm:1.0.1"]
|
||||
["swr", "virtual:b951ea20ab6cada5f665e8389a50d828047e6b6f10e6ebaddde1e74a94868ec6ec703ff140742f295ef663cf92da1bc80fe9bbeaab30196cba0e992f38cd19ea#npm:1.0.1"],
|
||||
["yargs", "npm:17.3.0"]
|
||||
],
|
||||
"linkType": "SOFT",
|
||||
}]
|
||||
@ -22916,6 +22919,20 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["yargs-parser", "npm:20.2.9"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}],
|
||||
["npm:17.3.0", {
|
||||
"packageLocation": "./.yarn/cache/yargs-npm-17.3.0-d4a72039e2-2b68733868.zip/node_modules/yargs/",
|
||||
"packageDependencies": [
|
||||
["yargs", "npm:17.3.0"],
|
||||
["cliui", "npm:7.0.4"],
|
||||
["escalade", "npm:3.1.1"],
|
||||
["get-caller-file", "npm:2.0.5"],
|
||||
["require-directory", "npm:2.1.1"],
|
||||
["string-width", "npm:4.2.3"],
|
||||
["y18n", "npm:5.0.8"],
|
||||
["yargs-parser", "npm:21.0.0"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["yargs-parser", [
|
||||
@ -22932,6 +22949,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
||||
["yargs-parser", "npm:20.2.9"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}],
|
||||
["npm:21.0.0", {
|
||||
"packageLocation": "./.yarn/cache/yargs-parser-npm-21.0.0-d564c0a5d4-1e205fca1c.zip/node_modules/yargs-parser/",
|
||||
"packageDependencies": [
|
||||
["yargs-parser", "npm:21.0.0"]
|
||||
],
|
||||
"linkType": "HARD",
|
||||
}]
|
||||
]],
|
||||
["yauzl", [
|
||||
|
BIN
.yarn/cache/yargs-npm-17.3.0-d4a72039e2-2b68733868.zip
vendored
Normal file
BIN
.yarn/cache/yargs-npm-17.3.0-d4a72039e2-2b68733868.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/yargs-parser-npm-21.0.0-d564c0a5d4-1e205fca1c.zip
vendored
Normal file
BIN
.yarn/cache/yargs-parser-npm-21.0.0-d564c0a5d4-1e205fca1c.zip
vendored
Normal file
Binary file not shown.
@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import spawnProcess from '../../utils/spawnProcess.js';
|
||||
import { spawnProcess } from '@lowdefy/node-utils';
|
||||
|
||||
const args = {
|
||||
npm: ['install', '--legacy-peer-deps'],
|
||||
@ -25,7 +25,7 @@ async function installServer({ context }) {
|
||||
context.print.spin(`Running ${context.packageManager} install.`);
|
||||
try {
|
||||
await spawnProcess({
|
||||
context,
|
||||
logger: context.print,
|
||||
command: context.packageManager, // npm or yarn
|
||||
args: args[context.packageManager],
|
||||
processOptions: {
|
||||
|
@ -14,13 +14,13 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import spawnProcess from '../../utils/spawnProcess.js';
|
||||
import { spawnProcess } from '@lowdefy/node-utils';
|
||||
|
||||
async function runLowdefyBuild({ context }) {
|
||||
context.print.log('Running Lowdefy build.');
|
||||
try {
|
||||
await spawnProcess({
|
||||
context,
|
||||
logger: context.print,
|
||||
command: context.packageManager, // npm or yarn
|
||||
args: ['run', 'build:lowdefy'],
|
||||
processOptions: {
|
||||
|
@ -14,13 +14,13 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import spawnProcess from '../../utils/spawnProcess.js';
|
||||
import { spawnProcess } from '@lowdefy/node-utils';
|
||||
|
||||
async function runNextBuild({ context }) {
|
||||
context.print.log('Running Next build.');
|
||||
try {
|
||||
await spawnProcess({
|
||||
context,
|
||||
logger: context.print,
|
||||
command: context.packageManager, // npm or yarn
|
||||
args: ['run', 'build:next'],
|
||||
processOptions: {
|
||||
|
@ -14,17 +14,15 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import spawnProcess from '../../utils/spawnProcess.js';
|
||||
import { spawnProcess } from '@lowdefy/node-utils';
|
||||
|
||||
async function runStart({ context }) {
|
||||
context.print.spin(`Running "${context.packageManager} run start".`);
|
||||
await spawnProcess({
|
||||
context,
|
||||
command: context.packageManager, // npm or yarn
|
||||
logger: context.print,
|
||||
args: ['run', 'start'],
|
||||
processOptions: {
|
||||
cwd: context.directories.server,
|
||||
},
|
||||
command: context.packageManager, // npm or yarn
|
||||
processOptions: { cwd: context.directories.server },
|
||||
silent: false,
|
||||
});
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
},
|
||||
"files": [
|
||||
"src/*",
|
||||
"public/*",
|
||||
"next.config.js",
|
||||
".eslintrc.yaml"
|
||||
],
|
||||
@ -34,7 +35,7 @@
|
||||
"build:lowdefy": "lowdefy-build",
|
||||
"build:next": "next build",
|
||||
"dev": "next dev",
|
||||
"start": "next start",
|
||||
"start": "node src/manager/run.mjs",
|
||||
"lint": "next lint",
|
||||
"next": "next"
|
||||
},
|
||||
@ -52,6 +53,7 @@
|
||||
"@lowdefy/engine": "4.0.0-alpha.5",
|
||||
"@lowdefy/helpers": "4.0.0-alpha.5",
|
||||
"@lowdefy/layout": "4.0.0-alpha.5",
|
||||
"@lowdefy/node-utils": "4.0.0-alpha.5",
|
||||
"@lowdefy/operators-change-case": "4.0.0-alpha.5",
|
||||
"@lowdefy/operators-diff": "4.0.0-alpha.5",
|
||||
"@lowdefy/operators-js": "4.0.0-alpha.5",
|
||||
@ -59,12 +61,14 @@
|
||||
"@lowdefy/operators-nunjucks": "4.0.0-alpha.5",
|
||||
"@lowdefy/operators-uuid": "4.0.0-alpha.5",
|
||||
"@lowdefy/operators-yaml": "4.0.0-alpha.5",
|
||||
"chokidar": "3.5.2",
|
||||
"next": "12.0.3",
|
||||
"next-auth": "4.0.0-beta.6",
|
||||
"react": "18.0.0-alpha-327d5c484-20211106",
|
||||
"react-dom": "18.0.0-alpha-327d5c484-20211106",
|
||||
"react-icons": "4.3.1",
|
||||
"swr": "1.0.1"
|
||||
"swr": "1.0.1",
|
||||
"yargs": "17.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/eslint-plugin-next": "12.0.4",
|
||||
|
@ -42,6 +42,11 @@ const Reload = ({ children }) => {
|
||||
console.log(event);
|
||||
mutateCache();
|
||||
};
|
||||
sse.addEventListener('tick', (event) => {
|
||||
console.log('tick event listener');
|
||||
console.log(event);
|
||||
mutateCache();
|
||||
});
|
||||
sse.onerror = (error) => {
|
||||
console.log('ERROR');
|
||||
console.error(error);
|
||||
|
50
packages/server-dev/src/manager/BatchChanges.mjs
Normal file
50
packages/server-dev/src/manager/BatchChanges.mjs
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2020-2021 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.
|
||||
*/
|
||||
|
||||
class BatchChanges {
|
||||
constructor({ fn, context, minDelay }) {
|
||||
this.fn = fn;
|
||||
this.context = context;
|
||||
this.delay = minDelay || 500;
|
||||
this.minDelay = minDelay || 500;
|
||||
this._call = this._call.bind(this);
|
||||
}
|
||||
|
||||
newChange() {
|
||||
this.delay = this.minDelay;
|
||||
this._startTimer();
|
||||
}
|
||||
|
||||
_startTimer() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
this.timer = setTimeout(this._call, this.delay);
|
||||
}
|
||||
|
||||
async _call() {
|
||||
try {
|
||||
await this.fn();
|
||||
} catch (error) {
|
||||
this.context.print.error(error.message, { timestamp: true });
|
||||
this.delay *= 2;
|
||||
this.context.print.warn(`Retrying in ${this.delay / 1000}s.`, { timestamp: true });
|
||||
this._startTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BatchChanges;
|
50
packages/server-dev/src/manager/run.mjs
Normal file
50
packages/server-dev/src/manager/run.mjs
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Copyright 2020-2021 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 path from 'path';
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
|
||||
import { writeFile } from '@lowdefy/node-utils';
|
||||
|
||||
import startServer from './startServer.mjs';
|
||||
|
||||
const argv = yargs(hideBin(process.argv)).argv;
|
||||
|
||||
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
const tick = async () => {
|
||||
const filePath = path.resolve('./build/tick.json');
|
||||
console.log(filePath);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await sleep(5000);
|
||||
console.log('tick', i);
|
||||
await writeFile({
|
||||
filePath,
|
||||
content: JSON.stringify({ tick: i }),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async function run() {
|
||||
tick();
|
||||
await startServer({
|
||||
packageManager: argv.packageManager || 'npm',
|
||||
});
|
||||
}
|
||||
|
||||
run();
|
28
packages/server-dev/src/manager/startServer.mjs
Normal file
28
packages/server-dev/src/manager/startServer.mjs
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2020-2021 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 { spawnProcess } from '@lowdefy/node-utils';
|
||||
|
||||
async function startServer({ packageManager }) {
|
||||
await spawnProcess({
|
||||
logger: console,
|
||||
args: ['run', 'next', 'start'],
|
||||
command: packageManager || 'npm',
|
||||
silent: false,
|
||||
});
|
||||
}
|
||||
|
||||
export default startServer;
|
@ -14,21 +14,47 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO: Send keep-alive comment event: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#examples
|
||||
|
||||
import chokidar from 'chokidar';
|
||||
|
||||
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
const handler = async (req, res) => {
|
||||
console.log('Update');
|
||||
res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
|
||||
res.setHeader('Cache-Control', 'no-cache, no-transform');
|
||||
res.setHeader('X-Accel-Buffering', 'no');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
console.log('Sending event', i);
|
||||
res.write(`data: Hello seq ${i}\n\n`);
|
||||
await sleep(1500);
|
||||
}
|
||||
res.end('done\n');
|
||||
const watcher = chokidar.watch(['./build/tick.json'], {
|
||||
ignored: [
|
||||
/(^|[/\\])\../, // ignore dotfiles
|
||||
],
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
try {
|
||||
console.log('reload');
|
||||
res.write(`event: tick\ndata: ${JSON.stringify({ hello: true })}\n\n`);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
watcher.on('add', () => reload());
|
||||
watcher.on('change', () => reload());
|
||||
watcher.on('unlink', () => reload());
|
||||
|
||||
// TODO: This isn't working.
|
||||
req.on('close', () => {
|
||||
console.log('req closed');
|
||||
watcher.close().then(() => {
|
||||
console.log('watcher closed');
|
||||
});
|
||||
});
|
||||
|
||||
await sleep(7000);
|
||||
};
|
||||
|
||||
export default handler;
|
||||
|
@ -27,6 +27,7 @@
|
||||
},
|
||||
"files": [
|
||||
"src/*",
|
||||
"public/*",
|
||||
"next.config.js",
|
||||
".eslintrc.yaml"
|
||||
],
|
||||
|
@ -18,6 +18,7 @@ import cleanDirectory from './cleanDirectory.js';
|
||||
import getConfigFromEnv from './getConfigFromEnv.js';
|
||||
import getFileExtension, { getFileSubExtension } from './getFileExtension.js';
|
||||
import getSecretsFromEnv from './getSecretsFromEnv.js';
|
||||
import spawnProcess from './spawnProcess.js';
|
||||
import readFile from './readFile.js';
|
||||
import writeFile from './writeFile.js';
|
||||
|
||||
@ -27,6 +28,7 @@ export {
|
||||
getFileExtension,
|
||||
getFileSubExtension,
|
||||
getSecretsFromEnv,
|
||||
spawnProcess,
|
||||
readFile,
|
||||
writeFile,
|
||||
};
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
|
||||
async function spawnProcess({ context, command, args, processOptions, silent }) {
|
||||
async function spawnProcess({ logger, command, args, processOptions, silent }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const process = spawn(command, args, processOptions);
|
||||
|
||||
@ -27,7 +27,7 @@ async function spawnProcess({ context, command, args, processOptions, silent })
|
||||
.split('\n')
|
||||
.forEach((line) => {
|
||||
if (line) {
|
||||
context.print.log(line);
|
||||
logger.log(line);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -40,7 +40,7 @@ async function spawnProcess({ context, command, args, processOptions, silent })
|
||||
.split('\n')
|
||||
.forEach((line) => {
|
||||
if (line) {
|
||||
context.print.warn(line);
|
||||
logger.warn(line);
|
||||
}
|
||||
});
|
||||
}
|
27
yarn.lock
27
yarn.lock
@ -3884,6 +3884,7 @@ __metadata:
|
||||
"@lowdefy/engine": 4.0.0-alpha.5
|
||||
"@lowdefy/helpers": 4.0.0-alpha.5
|
||||
"@lowdefy/layout": 4.0.0-alpha.5
|
||||
"@lowdefy/node-utils": 4.0.0-alpha.5
|
||||
"@lowdefy/operators-change-case": 4.0.0-alpha.5
|
||||
"@lowdefy/operators-diff": 4.0.0-alpha.5
|
||||
"@lowdefy/operators-js": 4.0.0-alpha.5
|
||||
@ -3892,6 +3893,7 @@ __metadata:
|
||||
"@lowdefy/operators-uuid": 4.0.0-alpha.5
|
||||
"@lowdefy/operators-yaml": 4.0.0-alpha.5
|
||||
"@next/eslint-plugin-next": 12.0.4
|
||||
chokidar: 3.5.2
|
||||
less: 4.1.2
|
||||
less-loader: 10.2.0
|
||||
next: 12.0.3
|
||||
@ -3901,6 +3903,7 @@ __metadata:
|
||||
react-dom: 18.0.0-alpha-327d5c484-20211106
|
||||
react-icons: 4.3.1
|
||||
swr: 1.0.1
|
||||
yargs: 17.3.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -16829,7 +16832,7 @@ resolve@^2.0.0-next.3:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0":
|
||||
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
|
||||
version: 4.2.3
|
||||
resolution: "string-width@npm:4.2.3"
|
||||
dependencies:
|
||||
@ -18485,6 +18488,28 @@ resolve@^2.0.0-next.3:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs-parser@npm:^21.0.0":
|
||||
version: 21.0.0
|
||||
resolution: "yargs-parser@npm:21.0.0"
|
||||
checksum: 1e205fca1cb7a36a1585e2b94a64e641c12741b53627d338e12747f4dca3c3610cdd9bb235040621120548dd74c3ef03a8168d52a1eabfedccbe4a62462b6731
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs@npm:17.3.0":
|
||||
version: 17.3.0
|
||||
resolution: "yargs@npm:17.3.0"
|
||||
dependencies:
|
||||
cliui: ^7.0.2
|
||||
escalade: ^3.1.1
|
||||
get-caller-file: ^2.0.5
|
||||
require-directory: ^2.1.1
|
||||
string-width: ^4.2.3
|
||||
y18n: ^5.0.5
|
||||
yargs-parser: ^21.0.0
|
||||
checksum: 2b687338684bf9645e9389ffdbe813fc5a2ddfede299d46fbe5ac80eb9a391e558b97861ba44d2256936ebe9d7f8135f6a38af1c76a5685eac4061008b2df57a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs@npm:^16.1.0, yargs@npm:^16.2.0":
|
||||
version: 16.2.0
|
||||
resolution: "yargs@npm:16.2.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user