feat: 增加 cert:generate 和 arduino:install 脚本
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import MString from './mstring';
|
||||
import { ARDUINO } from './config';
|
||||
import MString from './mstring.js';
|
||||
import { ARDUINO } from './config.js';
|
||||
|
||||
|
||||
const Boards = {};
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import os from 'node:os';
|
||||
import CONFIG from '../user/config.json';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
|
||||
|
||||
function processConfig(data) {
|
||||
for (let i in data.path) {
|
||||
if (data.path[i] instanceof String) {
|
||||
data.path[i] = path.resolve(process.cwd(), data.path[i]);
|
||||
} else if (data.path[i] instanceof Array) {
|
||||
for (let j in data.path[i]) {
|
||||
if (!(data.path[i][j] instanceof String)) {
|
||||
continue;
|
||||
}
|
||||
data.path[i][j] = path.resolve(process.cwd(), data.path[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
const CONFIG = fsExtra.readJSONSync(path.resolve(process.cwd(), 'config.json'));
|
||||
export const DEBUG = CONFIG.debug;
|
||||
export const ARDUINO = CONFIG.arduino;
|
||||
export const MICROPYTHON = CONFIG.micropython;
|
||||
export const PYTHON = CONFIG.python;
|
||||
export const ARDUINO = processConfig(CONFIG.arduino);
|
||||
export const MICROPYTHON = processConfig(CONFIG.micropython);
|
||||
export const PYTHON = processConfig(CONFIG.python);
|
||||
export const CURRENT_PLANTFORM = os.platform();
|
||||
export const TEMP_PATH = CONFIG.tempPath;
|
||||
export const CLIENT_PATH = CONFIG.clientPath;
|
||||
export const TEMP_PATH = path.resolve(process.cwd(), CONFIG.tempPath);
|
||||
export const CLIENT_PATH = path.resolve(process.cwd(), CONFIG.clientPath);
|
||||
export const CERTS_PATH = path.resolve(process.cwd(), 'certs');
|
||||
export const PORT = CONFIG.port;
|
||||
export const MODE = CONFIG.mode;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DEBUG } from './config';
|
||||
import { DEBUG } from './config.js';
|
||||
|
||||
const Debug = {};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Events from './events';
|
||||
import Events from './events.js';
|
||||
|
||||
|
||||
export default class EventsBase {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// import mitt from 'mitt';
|
||||
import _ from 'lodash';
|
||||
import shortid from 'shortid';
|
||||
import Debug from './debug';
|
||||
import Registry from './registry';
|
||||
import Debug from './debug.js';
|
||||
import Registry from './registry.js';
|
||||
|
||||
|
||||
export default class Events {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Debug from './debug';
|
||||
import Debug from './debug.js';
|
||||
|
||||
|
||||
export default class Registry {
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
ByteLengthParser
|
||||
} from 'serialport';
|
||||
import _ from 'lodash';
|
||||
import EventsBase from './events-base';
|
||||
import { CURRENT_PLANTFORM } from './config';
|
||||
import EventsBase from './events-base.js';
|
||||
import { CURRENT_PLANTFORM } from './config.js';
|
||||
|
||||
|
||||
export default class Serial extends EventsBase {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mustache from 'mustache';
|
||||
import Shell from './shell';
|
||||
import { MICROPYTHON, PYTHON } from './config';
|
||||
import Shell from './shell.js';
|
||||
import { MICROPYTHON, PYTHON } from './config.js';
|
||||
|
||||
|
||||
export default class ShellAmpy extends Shell {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import Shell from './shell';
|
||||
import { ARDUINO } from './config';
|
||||
import Shell from './shell.js';
|
||||
import { ARDUINO } from './config.js';
|
||||
|
||||
|
||||
export default class ShellArduino extends Shell {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from 'node:path';
|
||||
import Shell from './shell';
|
||||
import MString from './mstring';
|
||||
import { MICROPYTHON, PYTHON, CLIENT_PATH } from './config';
|
||||
import Shell from './shell.js';
|
||||
import MString from './mstring.js';
|
||||
import { MICROPYTHON, PYTHON, CLIENT_PATH } from './config.js';
|
||||
|
||||
|
||||
export default class ShellMicroPython extends Shell {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { execFile, exec } from 'node:child_process';
|
||||
import EventsBase from './events-base';
|
||||
import { CURRENT_PLANTFORM } from './config';
|
||||
import EventsBase from './events-base.js';
|
||||
import { CURRENT_PLANTFORM } from './config.js';
|
||||
|
||||
|
||||
export default class Shell extends EventsBase {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Server } from 'socket.io';
|
||||
import to from 'await-to-js';
|
||||
import { to } from 'await-to-js';
|
||||
import { usb } from 'usb';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import Serial from './serial';
|
||||
import Debug from './debug';
|
||||
import Registry from './registry';
|
||||
import ShellArduino from './shell-arduino';
|
||||
import ShellMicroPython from './shell-micropython';
|
||||
import ShellAmpy from './shell-ampy';
|
||||
import MString from './mstring';
|
||||
import Boards from './boards';
|
||||
import { TEMP_PATH, CLIENT_PATH } from './config';
|
||||
import Serial from './serial.js';
|
||||
import Debug from './debug.js';
|
||||
import Registry from './registry.js';
|
||||
import ShellArduino from './shell-arduino.js';
|
||||
import ShellMicroPython from './shell-micropython.js';
|
||||
import ShellAmpy from './shell-ampy.js';
|
||||
import MString from './mstring.js';
|
||||
import Boards from './boards.js';
|
||||
import { TEMP_PATH, CLIENT_PATH } from './config.js';
|
||||
|
||||
|
||||
export default class Socket {
|
||||
@@ -213,7 +213,6 @@ export default class Socket {
|
||||
});
|
||||
|
||||
socket.on('arduino.compile', async (config, callback) => {
|
||||
console.log(config)
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path = config?.path ?? {};
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
|
||||
76
src/common/utils.js
Normal file
76
src/common/utils.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import fsPlus from 'fs-plus';
|
||||
import forge from 'node-forge';
|
||||
import shell from 'shelljs';
|
||||
import _ from 'lodash';
|
||||
import { CERTS_PATH } from './config.js';
|
||||
|
||||
|
||||
export function getDefaultHosts() {
|
||||
const interfaceDict = os.networkInterfaces();
|
||||
const addresses = [];
|
||||
for (const key in interfaceDict) {
|
||||
const interfaces = interfaceDict[key];
|
||||
if (interfaces) {
|
||||
for (const item of interfaces) {
|
||||
const family = item.family;
|
||||
if (family === 'IPv4') {
|
||||
addresses.push(item.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['localhost', ...addresses];
|
||||
}
|
||||
|
||||
function generateCertificate() {
|
||||
fsExtra.ensureDirSync(CERTS_PATH);
|
||||
shell.cd(CERTS_PATH);
|
||||
shell.exec(`mkcert -key-file server.key -cert-file server.crt ${getDefaultHosts().join(' ')}`);
|
||||
console.log('new certificate generated successfully!');
|
||||
const certPem = fsExtra.readFileSync(path.resolve(CERTS_PATH, 'server.crt'));
|
||||
const keyPem = fsExtra.readFileSync(path.resolve(CERTS_PATH, 'server.key'));
|
||||
return {
|
||||
key: keyPem,
|
||||
cert: certPem
|
||||
};
|
||||
}
|
||||
|
||||
export function getCertificate() {
|
||||
const crtPath = path.resolve(CERTS_PATH, 'server.crt');
|
||||
const keyPath = path.resolve(CERTS_PATH, 'server.key');
|
||||
let data = {};
|
||||
if (!fsPlus.isFileSync(crtPath) || !fsPlus.isFileSync(keyPath)) {
|
||||
data = generateCertificate();
|
||||
} else {
|
||||
data.cert = fsExtra.readFileSync(crtPath);
|
||||
data.key = fsExtra.readFileSync(keyPath);
|
||||
}
|
||||
const cert = forge.pki.certificateFromPem(data.cert);
|
||||
const now = new Date();
|
||||
const notBefore = cert.validity.notBefore;
|
||||
const notAfter = cert.validity.notAfter;
|
||||
if (now < notBefore || now > notAfter) {
|
||||
data = generateCertificate();
|
||||
}
|
||||
const sanExt = cert.extensions.find(ext => ext.name === 'subjectAltName');
|
||||
if (sanExt && sanExt.altNames) {
|
||||
const hosts = [];
|
||||
for (let item of sanExt.altNames) {
|
||||
if (item.type === 2) {
|
||||
hosts.push(item.value);
|
||||
} else if (item.type === 7) {
|
||||
hosts.push(item.ip);
|
||||
}
|
||||
}
|
||||
const currentHosts = getDefaultHosts();
|
||||
if (_.xor(currentHosts, hosts).length !== 0) {
|
||||
data = generateCertificate();
|
||||
}
|
||||
} else {
|
||||
data = generateCertificate();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
92
src/index.js
92
src/index.js
@@ -1,44 +1,72 @@
|
||||
import express from 'express';
|
||||
import path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { createServer } from 'node:https';
|
||||
import Socket from './common/socket';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import express from 'express';
|
||||
import Socket from './common/socket.js';
|
||||
import { getCertificate } from './common/utils.js';
|
||||
import { CLIENT_PATH, PORT, MODE } from './common/config.js';
|
||||
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
const __dirname = path.dirname(url.fileURLToPath(new URL(import.meta.url)));
|
||||
const app = express();
|
||||
const httpsServer = createServer({
|
||||
key: readFileSync(path.resolve(__dirname, '../certs/server.key')),
|
||||
cert: readFileSync(path.resolve(__dirname, '../certs/server.crt'))
|
||||
}, app);
|
||||
if (CLIENT_PATH) {
|
||||
app.use(express.static(CLIENT_PATH));
|
||||
}
|
||||
const httpsServer = createServer(getCertificate(), app);
|
||||
|
||||
const socket = new Socket(httpsServer, {
|
||||
path: '/mixly-socket/',
|
||||
maxHttpBufferSize: 1e8,
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ['GET', 'POST'],
|
||||
transports: ['websocket', 'polling', 'flashsocket'],
|
||||
credentials: true
|
||||
}
|
||||
});
|
||||
if (MODE !== 'static') {
|
||||
const socket = new Socket(httpsServer, {
|
||||
path: '/mixly-socket/',
|
||||
maxHttpBufferSize: 1e8,
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ['GET', 'POST'],
|
||||
transports: ['websocket', 'polling', 'flashsocket'],
|
||||
credentials: true
|
||||
}
|
||||
});
|
||||
|
||||
const io = socket.getIO();
|
||||
const io = socket.getIO();
|
||||
|
||||
function close() {
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
process.on('SIGINT', () => {
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
close();
|
||||
const mixlyConfigPath = path.resolve(CLIENT_PATH, 'sw-config.json');
|
||||
const mixlyConfig = fsExtra.readJSONSync(mixlyConfigPath);
|
||||
|
||||
if (MODE === 'web-compiler') {
|
||||
mixlyConfig['webCompiler']['enabled'] = true;
|
||||
mixlyConfig['webCompiler']['url'] = `wss://127.0.0.1:${PORT}`;
|
||||
mixlyConfig['webSocket']['enabled'] = false;
|
||||
} else if (MODE === 'web-socket') {
|
||||
mixlyConfig['webCompiler']['enabled'] = false;
|
||||
mixlyConfig['webSocket']['url'] = `wss://127.0.0.1:${PORT}`;
|
||||
mixlyConfig['webSocket']['enabled'] = true;
|
||||
} else {
|
||||
mixlyConfig['webCompiler']['enabled'] = false;
|
||||
mixlyConfig['webSocket']['enabled'] = false;
|
||||
}
|
||||
|
||||
fsExtra.writeJSONSync(mixlyConfigPath, mixlyConfig, {
|
||||
spaces: ' '
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
close();
|
||||
});
|
||||
|
||||
httpsServer.listen(4000);
|
||||
httpsServer.listen(PORT);
|
||||
if (CLIENT_PATH) {
|
||||
console.log(`Static服务器正在运行: https://127.0.0.1:${PORT}`);
|
||||
}
|
||||
if (MODE !== 'static') {
|
||||
console.log(`Socket.io服务器正在运行: wss://127.0.0.1:${PORT}/mixly-socket`);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"debug": true,
|
||||
"arduino": {
|
||||
"path": {
|
||||
"folder": "D:/gitee/arduino-cli-win32/arduino-cli",
|
||||
"cli": "D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.exe",
|
||||
"libraries": [
|
||||
"D:/gitee/arduino-cli-win32/arduino-cli/libraries"
|
||||
],
|
||||
"cache": "D:/gitee/arduino-cli-win32/arduino-cli/cache",
|
||||
"config": "D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.json"
|
||||
}
|
||||
},
|
||||
"micropython": {
|
||||
"path": {
|
||||
"ampy": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/ampy_main.py",
|
||||
"esptool": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/esptool_main.py"
|
||||
}
|
||||
},
|
||||
"python": {
|
||||
"path": {
|
||||
"cli": "D:/gitee/mixly3.0-win32-x64/mixpyBuild/win_python3/python3.exe"
|
||||
}
|
||||
},
|
||||
"tempPath": "D:/gitee/mixly3-server/temp",
|
||||
"clientPath": "D:/gitee/mixly3.0-win32-x64/resources/app/src"
|
||||
}
|
||||
Reference in New Issue
Block a user