diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 03f6a78..f7e6a95 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -3,7 +3,7 @@ name: Publish
on:
push:
branches:
- - master
+ - stable
jobs:
publish:
@@ -20,7 +20,7 @@ jobs:
- name: Install Node, NPM and Yarn
uses: actions/setup-node@v1
with:
- node-version: 15
+ node-version: 16
- name: Get yarn cache directory path
id: yarn-cache-dir-path
@@ -52,4 +52,4 @@ jobs:
# This is used for uploading release assets to github
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- yarn postinstall && yarn build && yarn electron-builder --publish always --win --mac --linux
+ yarn prep && yarn build && yarn electron-builder --publish always --win --mac --linux
diff --git a/package.json b/package.json
index d50d301..50f0db6 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"productName": "ElectronReact",
"description": "Electron application boilerplate based on React, React Router, Webpack, React Fast Refresh for rapid application development",
"scripts": {
- "postinstall": "node -r @babel/register .erb/scripts/CheckNativeDep.js && electron-builder install-app-deps && yarn cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.babel.js && opencollective-postinstall && yarn-deduplicate yarn.lock",
+ "prep": "node -r @babel/register .erb/scripts/CheckNativeDep.js && electron-builder install-app-deps && yarn cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.babel.js && opencollective-postinstall && yarn-deduplicate yarn.lock",
"build": "concurrently \"yarn build:main\" \"yarn build:renderer\"",
"build:main": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.main.prod.babel.js",
"build:renderer": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.renderer.prod.babel.js",
@@ -26,6 +26,7 @@
"start:main": "cross-env NODE_ENV=development electron -r ./.erb/scripts/BabelRegister ./src/main.dev.ts",
"start:renderer": "cross-env NODE_ENV=development webpack serve --config ./.erb/configs/webpack.config.renderer.dev.babel.js",
"test": "jest",
+ "supervisor": "supervisor",
"relay": "supervisor -w relay,src -n exit relay/index.mjs",
"relay:service": "supervisor -w relay,src -- relay/service.mjs",
"sloc": "find lib -type f | xargs wc -l"
@@ -251,6 +252,7 @@
"electron-debug": "^3.1.0",
"electron-log": "^4.2.4",
"electron-updater": "^4.3.4",
+ "express-ws": "^4.0.0",
"font-ascii": "^1.2.1",
"gradient-string": "^1.2.0",
"history": "^5.0.0",
@@ -275,7 +277,7 @@
"volatile": "^7.0.1"
},
"devEngines": {
- "node": ">=10.x",
+ "node": ">=16.x",
"npm": ">=6.x",
"yarn": ">=1.21.3"
},
diff --git a/relay/service.mjs b/relay/service.mjs
index 1089b8b..8d4e19d 100644
--- a/relay/service.mjs
+++ b/relay/service.mjs
@@ -1,230 +1,284 @@
-import Signale from 'signale';
+// imports that arent installed...
import { execSync, spawn } from 'child_process';
-import Datastore from 'nedb';
import { config } from '../src/lib/config/index.js';
-import express from 'express';
-import Volatile from 'volatile';
+import http from 'http';
+import os from 'os';
+import EventEmitter from 'events';
-const logLock = new Volatile({});
-
-(async () => {
-
-const log = Signale.scope('SRVC');
-const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
-let proc;
-const logs = new Datastore({
- filename: 'svc.log',
- autoload: true
-});
-const app = express();
-
-
-try {
- logp('Attempting yarn install...')
- appendLogs('yarn', execSync(`yarn`));
-} catch (e) {
- logp('failed to yarn install...')
+let external = {};
+async function doExternalImports() {
+ external.Signale = (await import('signale')).default;
+ external.Datastore = (await import('nedb')).default;
+ external.express = (await import('express')).default;
+ external.Volatile = (await import('volatile')).default;
+ external.expressWs = (await import('express-ws')).default;
}
-logp('==================================');
-logp('Starting Valnet Node as a Service!');
-logp('Syncing to branch: ' + branch);
-logp('==================================');
-
-setInterval(function update() {
- const remoteHash = execSync('git ls-remote https://github.com/marcus13345/valnet.git').toString()
- .split('\n')
- .filter(test => {
- return test.trim().endsWith(branch);
- })[0]
- .split('\t')[0]
- .trim();
- const localHash = execSync(`git rev-parse ${branch}`).toString().trim();
- if(remoteHash !== localHash) {
- logp(`remote hash: ${remoteHash}`);
- logp(`local hash: ${localHash}`);
-
- logp('killing relay...');
- try {
- proc.kill();
- } catch (e) {
- logp('failed to kill active relay...', 'error');
- logp(e, 'error');
- }
+(async function bootloader() {
+ let yarnOutput = "";
+ try {
+ // sanity install packages...
+ // happens if a package is installed
+ // and used in this script, without
+ // restarting the service entirely
+ // between updates from github.
+ // this is also why we dynamically
+ // load the dependencies...
+ yarnOutput += execSync(`yarn`);
+ } catch {
+ enterRecoveryMode(yarnOutput);
+ return;
}
-}, 5000);
-
-(function keepAlive() {
- proc = spawn('node', ['./relay/index.mjs'], {
- stdio: 'pipe'
- });
- appendLogs('relay', 'STARTED', 'event');
-
- proc.stdout.on('data', (data) => {
- process.stdout.write(data);
- appendLogs('relay', data.toString(), 'stdout');
- });
-
- proc.stderr.on('data', (data) => {
- process.stderr.write(data);
- appendLogs('relay', data.toString(), 'stderr');
- });
-
- proc.on('exit', () => {
- appendLogs('relay', 'STOPPED', 'event');
- logp('relay exitted');
- logp('attempting to fetch new version');
-
- appendLogs('fetch', execSync(`git fetch`));
- appendLogs('update', execSync(`git pull`));
- appendLogs('yarn', execSync(`yarn`));
-
- logp('restarting...')
- setTimeout(() => {
- keepAlive();
- }, 1000);
- })
+ try {
+ await doExternalImports();
+ } catch (e) {
+ enterRecoveryMode(e.toString());
+ return;
+ }
+ startService();
})();
-function logp(message, type = 'info') {
- log[type](message);
- appendLogs('service', message + '\n')
-}
-function appendLogs(source, data, type = 'output') {
- logLock.lock(function(lock) {
- return new Promise(res => {
- logs.insert({
+async function startService() {
+ const logLock = new external.Volatile({});
+ const log = external.Signale.scope('SRVC');
+ const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
+ let proc;
+ const logs = new external.Datastore({
+ filename: 'svc.log',
+ autoload: true
+ });
+ const app = external.express();
+ external.expressWs(app);
+ const logEvents = new EventEmitter();
+
+ logp('==================================');
+ logp('Starting Valnet Node as a Service!');
+ logp('Syncing to branch: ' + branch);
+ logp('===================================');
+ logp('= = = = = = = = = = = = = = = = = =');
+ logp('= = = = = = = = = = = = ');
+ logp('= = = = = = = = = ');
+ logp('= = = = = = = ');
+ logp('= = = = = = ');
+
+ setInterval(function update() {
+ const remoteHash = execSync('git ls-remote https://github.com/marcus13345/valnet.git').toString()
+ .split('\n')
+ .filter(test => {
+ return test.trim().endsWith(branch);
+ })[0]
+ .split('\t')[0]
+ .trim();
+ const localHash = execSync(`git rev-parse ${branch}`).toString().trim();
+ if(remoteHash !== localHash) {
+ logp(`remote hash: ${remoteHash}`);
+ logp(`local hash: ${localHash}`);
+
+ logp('killing relay...');
+ try {
+ proc.kill();
+ } catch (e) {
+ logp('failed to kill active relay...', 'error');
+ logp(e, 'error');
+ }
+ }
+ }, 5000);
+
+ (function keepAlive() {
+ proc = spawn('node', ['./relay/index.mjs'], {
+ stdio: 'pipe',
+ env: {
+ FORCE_COLOR: true
+ }
+ });
+ appendLogs('relay', 'STARTED', 'event');
+
+ proc.stdout.on('data', (data) => {
+ process.stdout.write(data);
+ appendLogs('relay', data.toString(), 'stdout');
+ });
+
+ proc.stderr.on('data', (data) => {
+ process.stderr.write(data);
+ appendLogs('relay', data.toString(), 'stderr');
+ });
+
+ proc.on('exit', () => {
+ appendLogs('relay', 'STOPPED', 'event');
+ logp('relay exitted');
+ logp('attempting to fetch new version');
+
+ appendLogs('fetch', execSync(`git fetch`));
+ appendLogs('update', execSync(`git pull`));
+ appendLogs('yarn', execSync(`yarn`));
+
+ logp('restarting...')
+ setTimeout(() => {
+ keepAlive();
+ }, 1000);
+ })
+ })();
+
+ function logp(message, type = 'info') {
+ log[type](message);
+ appendLogs('service', message + '\n')
+ }
+
+ function appendLogs(source, data, type = 'output') {
+ logLock.lock(function(lock) {
+ const newDoc = {
message: data.toString(),
type: type,
src: source,
timestamp: new Date().getTime()
- }, (err, doc) => {
- res(lock);
+ };
+ logEvents.emit('all', [newDoc]);
+ return new Promise(res => {
+ logs.insert(newDoc, (err, doc) => {
+ res(lock);
+ })
})
})
- })
-}
+ }
-function getSessions() {
- return new Promise(res => {
- logs.find({
- type: 'event',
- message: { $in: ['STARTED', 'STOPPED'] }
- }, {}, (err, docs) => {
- const sessions = [];
- let start = null;
- for(const event of docs) {
- if(event.message === 'STARTED') {
- if (start !== null) {
+ function getSessions() {
+ return new Promise(res => {
+ logs.find({
+ type: 'event',
+ message: { $in: ['STARTED', 'STOPPED'] }
+ }, {}, (err, docs) => {
+ const sessions = [];
+ let start = null;
+ for(const event of docs) {
+ if(event.message === 'STARTED') {
+ if (start !== null) {
+ sessions.push({
+ started: start,
+ stopped: event.timestamp
+ });
+ }
+ start = event.timestamp;
+ }
+ if(event.message === 'STOPPED' && start !== null) {
sessions.push({
started: start,
stopped: event.timestamp
});
+ start = null;
}
- start = event.timestamp;
}
- if(event.message === 'STOPPED' && start !== null) {
- sessions.push({
- started: start,
- stopped: event.timestamp
- });
- start = null;
- }
- }
- sessions.sort((a, b) => a.started > b.started);
- res(sessions);
+ sessions.sort((a, b) => a.started > b.started);
+ res(sessions);
+ });
});
+ }
+
+ app.get('/', (req, res) => {
+ res.end(`
+ Logs
+ Sessions
+ Restart
+ `);
+ })
+
+ app.get('/restart', async (req, res) => {
+ proc.kill();
+ res.redirect('/');
+ })
+
+ app.get('/logs', (req, res) => {
+ // res.redirect(`/logs/${Date.now() - (1000 * 60 * 60 * 24)}`)
+ res.end(Template.realtimeLogs());
+ })
+
+ app.get('/logs/:start/:end', (req, res) => {
+
+ logs.find({
+ timestamp: { $gt: parseInt(req.params.time) }
+ }, {}).sort({
+ timestamp: -1
+ }).limit(100).exec((err, docs) => {
+
+ res.end(Template.logs(docs.reverse().map(v => v.message)));
+
+ if(err) {
+ res.end(err.toString());
+ return;
+ }
+ // ${new Date(logItem.timestamp).toLocaleString().padStart(40)}:
+ res.end();
+ })
});
+
+
+ app.get('/api/sessions', async (req, res) => {
+ res.json(await getSessions());
+ })
+
+ app.ws('/api/logs', async (ws) => {
+ logEvents.on('all', broadcast);
+ function broadcast(docs) {
+ for(const doc of docs)
+ ws.send(doc.message);
+ }
+ ws.on('close', _ => {
+ logEvents.off('all', broadcast);
+ })
+ });
+
+ app.listen(config.ports.service);
+};
+
+function enterRecoveryMode(message) {
+ http.createServer((req, res) => {
+ res.end(Template.recoveryMode(message));
+ }).listen(config.ports.service);
}
-app.get('/', (req, res) => {
- res.end(`
- Logs
- Sessions
- Restart
- `);
-})
-app.get('/restart', async (req, res) => {
- proc.kill();
- res.redirect('/');
-})
-
-app.get('/api/sessions.json', async (req, res) => {
- res.json(await getSessions());
-})
-
-app.get('/logs', (req, res) => {
- res.redirect(`/logs/${Date.now() - (1000 * 60 * 60 * 24)}`)
-})
-
-app.get('/logs/:time', (req, res) => {
-
- logs.find({
- timestamp: { $gt: parseInt(req.params.time) }
- }, {}).sort({
- timestamp: -1
- }).limit(100).exec((err, docs) => {
-
- res.end(Template.logs(docs.reverse().map(v => v.message)));
-
- if(err) {
- res.end(err.toString());
- return;
- }
-// ${new Date(logItem.timestamp).toLocaleString().padStart(40)}:
- res.end();
- })
-});
const Template = {
logs(messages) {
- return `
-
+ return ` + ++${messages.join('').replace(/\u001B\[.*?[A-Za-z]/g, '')} --
- - - `; +
${JSON.stringify(obj, null, 2)}
`
+ },
+ recoveryMode(message) {
+ return `${message}`
}
-};
-
-app.listen(config.ports.service);
-
-
-
-
-})();
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/undefined/.local/share/valnet/relay/config.json b/undefined/.local/share/valnet/relay/config.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/undefined/.local/share/valnet/relay/config.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/undefined/.local/share/valnet/relay/default.json b/undefined/.local/share/valnet/relay/default.json
new file mode 100644
index 0000000..a328902
--- /dev/null
+++ b/undefined/.local/share/valnet/relay/default.json
@@ -0,0 +1 @@
+{"cache":[["keyv:name",{"value":"{\"value\":\"shy-fly-72\",\"expires\":null}"}],["keyv:private-key",{"value":"{\"value\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcN8eGTX54f26/\\nZD+hQz8xzY3DBMh/QEPymh7Hh4BLAMKtlbnvpZ12A7ugPiSsjhQsZhEpkdE+Uo0J\\nrA1GLO0XPxgPP3QLPTv6/L9ZKIzOFEiT30YE7GDSBflj9kyyRNVpJrrgUHxsKmmg\\nQx+HakJDuNynN8LX8KltxzPZO1+Cx0Zy3r6iozniBPustzq03+YceWRhKCwgf2gM\\nXWtUxMY8M++Y/nFWDJ9CQMAhUOduQN/HFSxeWnrGRutQlzuj92Zd2S7p29CNBYry\\nk1D4BYu1cfVHhh0QlgflF7G83qQi9WEpeNwLXyx1ocKqVH4juri5VUI4SCNCuVO2\\nSkAGPqeJAgMBAAECggEAQwzJ7cIbM1r2zN0ZVn0HhbfFTdwitkN+JoWyClAFZ6vW\\n4yxtlweNkxa9FGU31nxQ+lGAskfs+IP0Fx+qvuEPjje9euXwR9arhOmws3LtJJKe\\nKCHf6sMON3bq+NXBS46xzqUZ9qd1D/QQTAIjaTrZYDnbM0aCsa6Q+hZTEb0jHH0B\\nzx0pzalljPo7y146WEAUjzC8PW0aGY80DTrxYYUXjvLEXzHygzLJR9GS///6E2mQ\\nZBmYGgOcbIqb54Fky4hkUSFClHkmpN9QH47+buh5jNnE9WOoWBrDmqzk68mUK7c9\\ns2DV3DUplO1Py1kFYuuGQNf7AK4l2HoRuUpJe6l40QKBgQDRM1tr8hrOtzXxKYOK\\nftvHV2ynUXAVblR6Be4iUo0GlipeZ8o6ijb21Hks9L81vnjB2c2zo80HYZvfYn7Y\\nbLFWpYtuZTO19HEb2Z3qruVJz2bFXRS9fdURSTSVufuBZ0gYFDtGFXvjUpPlv4ww\\nvXEtr4DqoOLIlRcmui806we+BQKBgQC/KivrH2O0G5W5uimGc5t4aVGemWBqJTyw\\ncb5phaYpDh8pJpbhPwW3L13jMX4wqxkW8xOc2EK1vyiLWeJJ9iVO/B5bZnQAAL2G\\nUwDUlKfLGeqEPlkKNW6Om89POZ/xo9jPub565NnG8oUWcCYr9pn8EY3UXkJIlsp7\\nXiiwD6N2tQKBgEhqfLULI5h29yc59ZzVeQKyEpyApknk3T04HEypQsQK6zOuveQx\\nwAEFX8TeG+pgurBv0rLierCZazmSgNIuHd0ehPt78MCFkznOxMleLWS1dJ/RLsLB\\nciX/r0I9FQCgXeZn6nTCLxZrmWKoQcEFcs4buIZ/lsFUSqVPQdQRn6Z5AoGAdUkZ\\ncwNqN6mo/i+CpLQvUfxEEGuH5Pf9uT/AFJvkK1I3uhasAXyaNB8Cmo7WHmQLW7I9\\neUCSBVJIPN8j4D79+uziby93wjyyC0THwKWIIStAYGykUogf0a00zyXKxQXC0wfi\\nHyJjnxVSpEaglN6S8T2P6BkAz+p8Rp6plgOyRfUCgYEAq8miCbC2EDNYbLH8+ViM\\nwsNyHBIFaGXSoY2uWfQTwnt1gWEplGRayJVnc0U4UsUv7jnALZH4aN2yrEK5aOqN\\nMPvVgeOrUTnf+Kltb06vbaCCqhQp4mqmkTFvApkOnnPMf+dAw8w614/ZEEs1wluo\\nzNEFNRrI+iD4kTxeUAszUPI=\\n-----END PRIVATE KEY-----\",\"expires\":null}"}],["keyv:public-key",{"value":"{\"value\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnDfHhk1+eH9uv2Q/oUM/\\nMc2NwwTIf0BD8poex4eASwDCrZW576WddgO7oD4krI4ULGYRKZHRPlKNCawNRizt\\nFz8YDz90Cz07+vy/WSiMzhRIk99GBOxg0gX5Y/ZMskTVaSa64FB8bCppoEMfh2pC\\nQ7jcpzfC1/Cpbccz2TtfgsdGct6+oqM54gT7rLc6tN/mHHlkYSgsIH9oDF1rVMTG\\nPDPvmP5xVgyfQkDAIVDnbkDfxxUsXlp6xkbrUJc7o/dmXdku6dvQjQWK8pNQ+AWL\\ntXH1R4YdEJYH5RexvN6kIvVhKXjcC18sdaHCqlR+I7q4uVVCOEgjQrlTtkpABj6n\\niQIDAQAB\\n-----END PUBLIC KEY-----\",\"expires\":null}"}]],"lastExpire":1619217000188}
\ No newline at end of file
diff --git a/undefined/.local/share/valnet/relay/shy-fly-72-endpoints.json b/undefined/.local/share/valnet/relay/shy-fly-72-endpoints.json
new file mode 100644
index 0000000..fd6259e
--- /dev/null
+++ b/undefined/.local/share/valnet/relay/shy-fly-72-endpoints.json
@@ -0,0 +1 @@
+{"cache":[["keyv:cache",{"value":"{\"value\":[\"valnet.xyz:5500\",\"nightly.valnet.xyz:5600\",\"canary.valnet.xyz:5600\",\"stable.valnet.xyz:5600\"],\"expires\":null}"}],["keyv:valnet.xyz:5500",{"value":"{\"value\":{\"host\":\"valnet.xyz\",\"port\":\"5500\",\"lastPing\":null,\"status\":\"unknown\"},\"expires\":null}"}],["keyv:nightly.valnet.xyz:5600",{"value":"{\"value\":{\"host\":\"nightly.valnet.xyz\",\"port\":\"5600\",\"lastPing\":null,\"status\":\"unknown\"},\"expires\":null}"}],["keyv:canary.valnet.xyz:5600",{"value":"{\"value\":{\"host\":\"canary.valnet.xyz\",\"port\":\"5600\",\"lastPing\":null,\"status\":\"unknown\"},\"expires\":null}"}],["keyv:stable.valnet.xyz:5600",{"value":"{\"value\":{\"host\":\"stable.valnet.xyz\",\"port\":\"5600\",\"lastPing\":null,\"status\":\"unknown\"},\"expires\":null}"}]],"lastExpire":1619217003576}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index bad6d46..4097dc7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4550,6 +4550,12 @@ expect@^26.6.2:
jest-message-util "^26.6.2"
jest-regex-util "^26.0.0"
+express-ws@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/express-ws/-/express-ws-4.0.0.tgz#dabd8dc974516418902a41fe6e30ed949b4d36c4"
+ dependencies:
+ ws "^5.2.0"
+
express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
@@ -10616,6 +10622,12 @@ write@1.0.3:
dependencies:
mkdirp "^0.5.1"
+ws@^5.2.0:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
+ dependencies:
+ async-limiter "~1.0.0"
+
ws@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"