packaging with scripthaus-server and mshell binaries, separate dev/prod builds. emain to launch local server from package

This commit is contained in:
sawka 2022-11-01 21:18:40 -07:00
parent 56a91a9601
commit d9cd211149
12 changed files with 139 additions and 30 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
dist/ dist/
dist-dev/
node_modules/ node_modules/
*~ *~
*.log *.log

View File

@ -3,6 +3,7 @@ var AllowedFirstParts = {
"dist": true, "dist": true,
"static": true, "static": true,
"node_modules": true, "node_modules": true,
"bin": true,
}; };
var AllowedNodeModules = { var AllowedNodeModules = {

View File

@ -1,7 +1,7 @@
{ {
"name": "ScriptHaus", "name": "ScriptHaus",
"version": "1.0.0", "version": "1.0.0",
"main": "dist/emain-dev.js", "main": "dist/emain.js",
"license": "Proprietary", "license": "Proprietary",
"dependencies": { "dependencies": {
"autobind-decorator": "^2.4.0", "autobind-decorator": "^2.4.0",

View File

@ -34,7 +34,7 @@ node_modules/.bin/electron-rebuild
```bash ```bash
# @scripthaus command electron # @scripthaus command electron
# @scripthaus cd :playbook # @scripthaus cd :playbook
SH_DEV=1 node_modules/.bin/electron dist/emain-dev.js SH_DEV=1 node_modules/.bin/electron dist-dev/emain.js
``` ```
```bash ```bash
@ -52,7 +52,20 @@ node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --e
```bash ```bash
# @scripthaus command build-package # @scripthaus command build-package
# @scripthaus cd :playbook # @scripthaus cd :playbook
node_modules/.bin/webpack --config webpack.dev.js rm -rf dist/
node_modules/.bin/webpack --config webpack.electron.js rm -rf bin/
node_modules/.bin/webpack --config webpack.prod.js
node_modules/.bin/webpack --config webpack.electron.prod.js
(cd ../mshell; GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o ../sh2/bin/mshell/mshell-v0.2-darwin.amd64 main-mshell.go)
(cd ../mshell; GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o ../sh2/bin/mshell/mshell-v0.2-darwin.arm64 main-mshell.go)
(cd ../mshell; GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../sh2/bin/mshell/mshell-v0.2-linux.amd64 main-mshell.go)
(cd ../mshell; GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ../sh2/bin/mshell/mshell-v0.2-linux.arm64 main-mshell.go)
(cd ../sh2-server; GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o ../sh2/bin/scripthaus-local-server cmd/main-server.go)
node_modules/.bin/electron-forge make node_modules/.bin/electron-forge make
``` ```
```bash
# @scripthaus command open-electron-package
# @scripthaus cd :playbook
open out/ScriptHaus-darwin-x64/ScriptHaus.app
```

View File

@ -10,10 +10,19 @@ import * as winston from "winston";
import * as util from "util"; import * as util from "util";
import {sprintf} from "sprintf-js"; import {sprintf} from "sprintf-js";
const ScriptHausAppPathVarName = "SCRIPTHAUS_APP_PATH";
let isDev = (process.env.SH_DEV != null); let isDev = (process.env.SH_DEV != null);
let scHome = getScHomeDir(); let scHome = getScHomeDir();
ensureDir(scHome); ensureDir(scHome);
// these are either "darwin/amd64" or "darwin/arm64"
// normalize darwin/x64 to darwin/amd64 for GOARCH compatibility
let unamePlatform = process.platform;
let unameArch = process.arch;
if (unameArch == "x64") {
unameArch = "amd64"
}
let logger; let logger;
let loggerConfig = { let loggerConfig = {
level: "info", level: "info",
@ -33,14 +42,9 @@ function log(...msg) {
logger.info(util.format(...msg)); logger.info(util.format(...msg));
} }
console.log = log; console.log = log;
console.log(sprintf("scripthaus-app starting, SCRIPTHAUS_HOME=%s, dirname=%s", scHome, __dirname)); console.log(sprintf("scripthaus-app starting, SCRIPTHAUS_HOME=%s, apppath=%s arch=%s/%s", scHome, getAppBasePath(), unamePlatform, unameArch));
// TODO fix these paths
const LocalServerPath = "/Users/mike/scripthaus/local-server";
const LocalServerCmd = `${LocalServerPath} > ~/scripthaus/local-server.log 2>&1`;
// const LocalServerCwd = "/Users/mike/scripthaus/";
const LocalServerCwd = "/Users/mike/work/gopath/src/github.com/scripthaus-dev/sh2-server";
const DevLocalServerPath = "/Users/mike/scripthaus/local-server";
let localServerProc = null; let localServerProc = null;
let localServerShouldRestart = false; let localServerShouldRestart = false;
@ -57,6 +61,31 @@ function getScHomeDir() {
return scHome; return scHome;
} }
// for dev, this is just the github.com/scripthaus-dev/sh2 directory
// for prod, this is .../ScriptHaus.app/Contents/Resources/app
function getAppBasePath() {
return path.dirname(__dirname);
}
function getLocalServerPath() {
if (isDev) {
return DevLocalServerPath
}
return path.join(getAppBasePath(), "bin", "scripthaus-local-server");
}
function getLocalServerCmd() {
let localServerPath = getLocalServerPath();
let scHome = getScHomeDir();
let logFile = path.join(scHome, "local-server.log");
return `${localServerPath} > ${logFile} 2>&1`;
}
function getLocalServerCwd() {
let scHome = getScHomeDir();
return scHome;
}
function ensureDir(dir) { function ensureDir(dir) {
fs.mkdirSync(dir, {recursive: true, mode: 0o700}); fs.mkdirSync(dir, {recursive: true, mode: 0o700});
} }
@ -115,10 +144,10 @@ function createMainWindow(clientData) {
width: bounds.width, width: bounds.width,
height: bounds.height, height: bounds.height,
webPreferences: { webPreferences: {
preload: path.join(__dirname, "../dist/preload.js"), preload: path.join(getAppBasePath(), "dist", "preload.js"),
}, },
}); });
win.loadFile(path.join(__dirname, "../static/index.html")); win.loadFile(path.join(getAppBasePath(), "static", "index.html"));
win.webContents.on("before-input-event", (e, input) => { win.webContents.on("before-input-event", (e, input) => {
if (input.type != "keyDown") { if (input.type != "keyDown") {
return; return;
@ -308,14 +337,24 @@ function sendLSSC() {
} }
function runLocalServer() { function runLocalServer() {
console.log("trying to run local server"); let pResolve = null;
let proc = child_process.spawn("/bin/bash", ["-c", LocalServerCmd], { let pReject = null;
cwd: LocalServerCwd, let rtnPromise = new Promise((argResolve, argReject) => {
pResolve = argResolve;
pReject = argReject;
});
let envCopy = Object.assign({}, process.env);
envCopy[ScriptHausAppPathVarName] = getAppBasePath();
console.log("trying to run local server", getLocalServerPath());
let proc = child_process.spawn("/bin/bash", ["-c", getLocalServerCmd()], {
cwd: getLocalServerCwd(),
env: envCopy,
}); });
proc.on("exit", (e) => { proc.on("exit", (e) => {
console.log("local-server exit", e); console.log("local-server exit", e);
localServerProc = null; localServerProc = null;
sendLSSC(); sendLSSC();
pReject(new Error(sprintf("failed to start local server (%s)", getLocalServerPath())));
if (localServerShouldRestart) { if (localServerShouldRestart) {
localServerShouldRestart = false; localServerShouldRestart = false;
this.runLocalServer(); this.runLocalServer();
@ -324,6 +363,7 @@ function runLocalServer() {
proc.on("spawn", (e) => { proc.on("spawn", (e) => {
console.log("spawnned local-server"); console.log("spawnned local-server");
localServerProc = proc; localServerProc = proc;
pResolve(true);
setTimeout(() => { setTimeout(() => {
sendLSSC(); sendLSSC();
}, 100); }, 100);
@ -337,6 +377,7 @@ function runLocalServer() {
proc.stderr.on("data", output => { proc.stderr.on("data", output => {
return; return;
}); });
return rtnPromise;
} }
electron.ipcMain.on("context-screen", (event, {screenId}, {x, y}) => { electron.ipcMain.on("context-screen", (event, {screenId}, {x, y}) => {
@ -346,18 +387,34 @@ electron.ipcMain.on("context-screen", (event, {screenId}, {x, y}) => {
}); });
async function createMainWindowWrap() { async function createMainWindowWrap() {
let clientData = await getClientData(); let clientData = null;
try {
clientData = await getClientData();
}
catch (e) {
console.log("error getting local-server clientdata", e.toString());
}
MainWindow = createMainWindow(clientData); MainWindow = createMainWindow(clientData);
if (clientData && clientData.winsize.fullscreen) { if (clientData && clientData.winsize.fullscreen) {
MainWindow.setFullScreen(true); MainWindow.setFullScreen(true);
} }
} }
async function sleep(ms) {
return new Promise((resolve, reject) => setTimeout(resolve, ms));
}
// ====== MAIN ====== // // ====== MAIN ====== //
(async () => { (async () => {
runLocalServer(); try {
await runLocalServer();
}
catch (e) {
console.log(e.toString());
}
await sleep(500); // TODO remove this sleep, poll getClientData() in createMainWindow
await app.whenReady(); await app.whenReady();
await createMainWindowWrap(); await createMainWindowWrap();
app.on('activate', () => { app.on('activate', () => {

View File

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<base href="../"> <base href="../">
<script src="dist/sh2-dev.js"></script> <script src="dist/sh2.js"></script>
<link rel="stylesheet" href="static/bulma-0.9.4.min.css"> <link rel="stylesheet" href="static/bulma-0.9.4.min.css">
<link rel="stylesheet" href="static/font-awesome.min.css"> <link rel="stylesheet" href="static/font-awesome.min.css">
<link rel="stylesheet" href="static/xterm.css" /> <link rel="stylesheet" href="static/xterm.css" />

View File

@ -1 +0,0 @@
<h1>Remotes!</h1>

View File

@ -1,4 +1,5 @@
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const path = require("path"); const path = require("path");
module.exports = { module.exports = {
@ -8,7 +9,7 @@ module.exports = {
}, },
output: { output: {
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist"),
filename: "[name]-dev.js" filename: "[name].js",
}, },
module: { module: {
rules: [ rules: [
@ -58,6 +59,7 @@ module.exports = {
}, },
plugins: [ plugins: [
new MiniCssExtractPlugin({filename: "[name].css", ignoreOrder: true}), new MiniCssExtractPlugin({filename: "[name].css", ignoreOrder: true}),
new LodashModuleReplacementPlugin(),
], ],
resolve: { resolve: {
extensions: ['.ts', '.tsx', '.js', '.mjs', '.cjs', '.wasm', '.json', '.less', '.css'] extensions: ['.ts', '.tsx', '.js', '.mjs', '.cjs', '.wasm', '.json', '.less', '.css']

View File

@ -7,6 +7,10 @@ const VERSION = "v0.1.0";
var merged = merge.merge(common, { var merged = merge.merge(common, {
mode: "development", mode: "development",
output: {
path: path.resolve(__dirname, "dist-dev"),
filename: "[name].js",
},
devtool: "source-map", devtool: "source-map",
devServer: { devServer: {
static: { static: {
@ -23,6 +27,7 @@ var merged = merge.merge(common, {
}); });
var definePlugin = new webpack.DefinePlugin({ var definePlugin = new webpack.DefinePlugin({
__SHDEV__: "true",
__SHVERSION__: JSON.stringify(VERSION), __SHVERSION__: JSON.stringify(VERSION),
__SHBUILD__: JSON.stringify("devbuild"), __SHBUILD__: JSON.stringify("devbuild"),
}); });

View File

@ -8,8 +8,8 @@ module.exports = {
}, },
target: "electron-main", target: "electron-main",
output: { output: {
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist-dev"),
filename: "[name]-dev.js" filename: "[name].js"
}, },
externals: { externals: {
"fs": "require('fs')", "fs": "require('fs')",

34
webpack.electron.prod.js Normal file
View File

@ -0,0 +1,34 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.electron.js');
const moment = require("dayjs");
const VERSION = "v0.1.0";
const path = require("path");
function makeBuildStr() {
let buildStr = moment().format("YYYYMMDD-HHmmss");
console.log("ScriptHaus Electron " + VERSION + " build " + buildStr);
return buildStr;
}
const BUILD = makeBuildStr();
let merged = merge.merge(common, {
mode: "production",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js"
},
devtool: "source-map",
optimization: {
minimize: true,
},
});
merged.plugins.push(new webpack.DefinePlugin({
__SHDEV__: "false",
__SHVERSION__: JSON.stringify(VERSION),
__SHBUILD__: JSON.stringify(BUILD),
}));
module.exports = merged;

View File

@ -1,11 +1,9 @@
const webpack = require('webpack'); const webpack = require('webpack');
const merge = require('webpack-merge'); const merge = require('webpack-merge');
const common = require('./webpack.common.js'); const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const moment = require("dayjs"); const moment = require("dayjs");
const fs = require("fs");
const VERSION = "v0.1.0"; const VERSION = "v0.1.0";
const path = require("path");
function makeBuildStr() { function makeBuildStr() {
let buildStr = moment().format("YYYYMMDD-HHmmss"); let buildStr = moment().format("YYYYMMDD-HHmmss");
@ -23,8 +21,8 @@ if (process.env.WEBPACK_ANALYZE) {
let merged = merge.merge(common, { let merged = merge.merge(common, {
mode: "production", mode: "production",
output: { output: {
path: __dirname, path: path.resolve(__dirname, "dist"),
filename: "build/hibiki/latest/[name]-prod.min.js" filename: "[name].js",
}, },
devtool: "source-map", devtool: "source-map",
optimization: { optimization: {
@ -32,12 +30,11 @@ let merged = merge.merge(common, {
}, },
}); });
merged.plugins.push(new LodashModuleReplacementPlugin());
merged.plugins.push(new MiniCssExtractPlugin({filename: "dist/[name].css", ignoreOrder: true}));
if (BundleAnalyzerPlugin != null) { if (BundleAnalyzerPlugin != null) {
merged.plugins.push(new BundleAnalyzerPlugin()); merged.plugins.push(new BundleAnalyzerPlugin());
} }
merged.plugins.push(new webpack.DefinePlugin({ merged.plugins.push(new webpack.DefinePlugin({
__SHDEV__: "false",
__SHVERSION__: JSON.stringify(VERSION), __SHVERSION__: JSON.stringify(VERSION),
__SHBUILD__: JSON.stringify(BUILD), __SHBUILD__: JSON.stringify(BUILD),
})); }));