Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
Cleanup the bootstrapping file to make it easier to interpret (#31)
Browse files Browse the repository at this point in the history
* Commit changes after installing.

* Update eslint and remove yarn.

* Move processes and interval logic to be inside class.

* Change null values back to undefined.

* Consolidate event listeners.

* Consolidate event listeners.

* Add some utility functions.

* Store the Electron API port inside of state, and extract booting of Electron API to separate method.

* Extract configs and boot logic for scheduler to separate methods.

* Extract methods for starting PHP app and websockets.

* Move PHP app, queue worker, websockets, and scheduler to separate methods.

* Move auto updater to before PHP logic.

* Fix order of methods, and make killChildProcesses into a class method.

* Commit dist file.
  • Loading branch information
mitchdav authored Jul 18, 2024
1 parent a0a1766 commit 4d105bd
Show file tree
Hide file tree
Showing 11 changed files with 8,105 additions and 8,778 deletions.
228 changes: 135 additions & 93 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,137 +11,179 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const electron_1 = require("electron");
const electron_updater_1 = require("electron-updater");
const state_1 = __importDefault(require("./server/state"));
const utils_1 = require("@electron-toolkit/utils");
const server_1 = require("./server");
const utils_2 = require("./server/utils");
const electron_1 = require("electron");
const path_1 = require("path");
const ps_node_1 = __importDefault(require("ps-node"));
let phpProcesses = [];
let websocketProcess;
let schedulerInterval;
const killChildProcesses = () => {
let processes = [
...phpProcesses,
websocketProcess,
].filter((p) => p !== undefined);
processes.forEach((process) => {
try {
ps_node_1.default.kill(process.pid);
}
catch (err) {
console.error(err);
}
});
};
class NativePHP {
constructor() {
this.processes = [];
this.schedulerInterval = undefined;
}
bootstrap(app, icon, phpBinary, cert) {
require('@electron/remote/main').initialize();
require("@electron/remote/main").initialize();
state_1.default.icon = icon;
state_1.default.php = phpBinary;
state_1.default.caCert = cert;
this.bootstrapApp(app);
this.addEventListeners(app);
this.addTerminateListeners(app);
}
addEventListeners(app) {
app.on('open-url', (event, url) => {
(0, utils_2.notifyLaravel)('events', {
event: '\\Native\\Laravel\\Events\\App\\OpenedFromURL',
payload: [url]
app.on("open-url", (event, url) => {
(0, utils_2.notifyLaravel)("events", {
event: "\\Native\\Laravel\\Events\\App\\OpenedFromURL",
payload: [url],
});
});
app.on('open-file', (event, path) => {
(0, utils_2.notifyLaravel)('events', {
event: '\\Native\\Laravel\\Events\\App\\OpenFile',
payload: [path]
app.on("open-file", (event, path) => {
(0, utils_2.notifyLaravel)("events", {
event: "\\Native\\Laravel\\Events\\App\\OpenFile",
payload: [path],
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
}
addTerminateListeners(app) {
app.on('before-quit', (e) => {
if (schedulerInterval) {
clearInterval(schedulerInterval);
app.on("before-quit", () => {
if (this.schedulerInterval) {
clearInterval(this.schedulerInterval);
}
this.killChildProcesses();
});
app.on("browser-window-created", (_, window) => {
utils_1.optimizer.watchWindowShortcuts(window);
});
app.on("activate", function (event, hasVisibleWindows) {
if (!hasVisibleWindows) {
(0, utils_2.notifyLaravel)("booted");
}
killChildProcesses();
event.preventDefault();
});
}
bootstrapApp(app) {
let nativePHPConfig = {};
(0, server_1.retrieveNativePHPConfig)().then((result) => {
return __awaiter(this, void 0, void 0, function* () {
yield app.whenReady();
const config = yield this.loadConfig();
this.setDockIcon();
this.setAppUserModelId(config);
this.setDeepLinkHandler(config);
this.startAutoUpdater(config);
yield this.startElectronApi();
state_1.default.phpIni = yield this.loadPhpIni();
yield this.startPhpApp();
yield this.startQueueWorker();
yield this.startWebsockets();
this.startScheduler();
yield (0, utils_2.notifyLaravel)("booted");
});
}
loadConfig() {
return __awaiter(this, void 0, void 0, function* () {
let config = {};
try {
nativePHPConfig = JSON.parse(result.stdout);
const result = yield (0, server_1.retrieveNativePHPConfig)();
config = JSON.parse(result.stdout);
}
catch (e) {
console.error(e);
catch (error) {
console.error(error);
}
}).catch((err) => {
console.error(err);
}).finally(() => {
this.setupApp(nativePHPConfig);
return config;
});
}
setupApp(nativePHPConfig) {
electron_1.app.whenReady().then(() => __awaiter(this, void 0, void 0, function* () {
var _a;
if (process.platform === 'darwin' && process.env.NODE_ENV === 'development') {
electron_1.app.dock.setIcon(state_1.default.icon);
setDockIcon() {
if (process.platform === "darwin" &&
process.env.NODE_ENV === "development") {
electron_1.app.dock.setIcon(state_1.default.icon);
}
}
setAppUserModelId(config) {
utils_1.electronApp.setAppUserModelId(config === null || config === void 0 ? void 0 : config.app_id);
}
setDeepLinkHandler(config) {
const deepLinkProtocol = config === null || config === void 0 ? void 0 : config.deeplink_scheme;
if (deepLinkProtocol) {
if (process.defaultApp) {
if (process.argv.length >= 2) {
electron_1.app.setAsDefaultProtocolClient(deepLinkProtocol, process.execPath, [
(0, path_1.resolve)(process.argv[1]),
]);
}
}
electron_1.app.on('browser-window-created', (_, window) => {
utils_1.optimizer.watchWindowShortcuts(window);
});
let phpIniSettings = {};
else {
electron_1.app.setAsDefaultProtocolClient(deepLinkProtocol);
}
}
}
startAutoUpdater(config) {
var _a;
if (((_a = config === null || config === void 0 ? void 0 : config.updater) === null || _a === void 0 ? void 0 : _a.enabled) === true) {
electron_updater_1.autoUpdater.checkForUpdatesAndNotify();
}
}
startElectronApi() {
return __awaiter(this, void 0, void 0, function* () {
const electronApi = yield (0, server_1.startAPI)();
state_1.default.electronApiPort = electronApi.port;
console.log("Electron API server started on port", electronApi.port);
});
}
loadPhpIni() {
return __awaiter(this, void 0, void 0, function* () {
let config = {};
try {
let { stdout } = yield (0, server_1.retrievePhpIniSettings)();
phpIniSettings = JSON.parse(stdout);
const result = yield (0, server_1.retrievePhpIniSettings)();
config = JSON.parse(result.stdout);
}
catch (e) {
console.error(e);
catch (error) {
console.error(error);
}
utils_1.electronApp.setAppUserModelId(nativePHPConfig === null || nativePHPConfig === void 0 ? void 0 : nativePHPConfig.app_id);
const deepLinkProtocol = nativePHPConfig === null || nativePHPConfig === void 0 ? void 0 : nativePHPConfig.deeplink_scheme;
if (deepLinkProtocol) {
if (process.defaultApp) {
if (process.argv.length >= 2) {
electron_1.app.setAsDefaultProtocolClient(deepLinkProtocol, process.execPath, [(0, path_1.resolve)(process.argv[1])]);
}
}
else {
electron_1.app.setAsDefaultProtocolClient(deepLinkProtocol);
}
return config;
});
}
startPhpApp() {
return __awaiter(this, void 0, void 0, function* () {
this.processes.push(yield (0, server_1.startPhpApp)());
});
}
startQueueWorker() {
return __awaiter(this, void 0, void 0, function* () {
this.processes.push(yield (0, server_1.startQueue)());
});
}
startWebsockets() {
return __awaiter(this, void 0, void 0, function* () {
this.processes.push(yield (0, server_1.startWebsockets)());
});
}
startScheduler() {
const now = new Date();
const delay = (60 - now.getSeconds()) * 1000 + (1000 - now.getMilliseconds());
setTimeout(() => {
console.log("Running scheduler...");
(0, server_1.runScheduler)();
this.schedulerInterval = setInterval(() => {
console.log("Running scheduler...");
(0, server_1.runScheduler)();
}, 60 * 1000);
}, delay);
}
killChildProcesses() {
this.processes
.filter((p) => p !== undefined)
.forEach((process) => {
try {
ps_node_1.default.kill(process.pid);
}
const apiPort = yield (0, server_1.startAPI)();
console.log('API server started on port', apiPort.port);
phpProcesses = yield (0, server_1.servePhpApp)(apiPort.port, phpIniSettings);
websocketProcess = (0, server_1.serveWebsockets)();
yield (0, utils_2.notifyLaravel)('booted');
if (((_a = nativePHPConfig === null || nativePHPConfig === void 0 ? void 0 : nativePHPConfig.updater) === null || _a === void 0 ? void 0 : _a.enabled) === true) {
electron_updater_1.autoUpdater.checkForUpdatesAndNotify();
catch (err) {
console.error(err);
}
let now = new Date();
let delay = (60 - now.getSeconds()) * 1000 + (1000 - now.getMilliseconds());
setTimeout(() => {
console.log("Running scheduler...");
(0, server_1.runScheduler)(apiPort.port, phpIniSettings);
schedulerInterval = setInterval(() => {
console.log("Running scheduler...");
(0, server_1.runScheduler)(apiPort.port, phpIniSettings);
}, 60 * 1000);
}, delay);
electron_1.app.on('activate', function (event, hasVisibleWindows) {
if (!hasVisibleWindows) {
(0, utils_2.notifyLaravel)('booted');
}
event.preventDefault();
});
}));
});
}
}
module.exports = new NativePHP();
30 changes: 15 additions & 15 deletions dist/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.retrievePhpIniSettings = exports.retrieveNativePHPConfig = exports.serveWebsockets = exports.startAPI = exports.startQueue = exports.runScheduler = exports.servePhpApp = void 0;
exports.retrievePhpIniSettings = exports.retrieveNativePHPConfig = exports.startWebsockets = exports.startAPI = exports.runScheduler = exports.startQueue = exports.startPhpApp = void 0;
const websockets_1 = __importDefault(require("./websockets"));
exports.serveWebsockets = websockets_1.default;
exports.startWebsockets = websockets_1.default;
const api_1 = __importDefault(require("./api"));
const php_1 = require("./php");
Object.defineProperty(exports, "retrieveNativePHPConfig", { enumerable: true, get: function () { return php_1.retrieveNativePHPConfig; } });
Object.defineProperty(exports, "retrievePhpIniSettings", { enumerable: true, get: function () { return php_1.retrievePhpIniSettings; } });
const utils_1 = require("./utils");
const state_1 = __importDefault(require("./state"));
function servePhpApp(apiPort, phpIniSettings) {
function startPhpApp() {
return __awaiter(this, void 0, void 0, function* () {
const processes = [];
const result = yield (0, php_1.serveApp)(state_1.default.randomSecret, apiPort, phpIniSettings);
processes.push(result.process);
processes.push((0, php_1.startQueueWorker)(state_1.default.randomSecret, apiPort, phpIniSettings));
const result = yield (0, php_1.serveApp)(state_1.default.randomSecret, state_1.default.electronApiPort, state_1.default.phpIni);
state_1.default.phpPort = result.port;
yield (0, utils_1.appendCookie)();
return processes;
return result.process;
});
}
exports.servePhpApp = servePhpApp;
function runScheduler(apiPort, phpIniSettings) {
(0, php_1.startScheduler)(state_1.default.randomSecret, apiPort, phpIniSettings);
}
exports.runScheduler = runScheduler;
function startQueue(apiPort, phpIniSettings) {
exports.startPhpApp = startPhpApp;
function startQueue() {
if (!process.env.NATIVE_PHP_SKIP_QUEUE) {
return (0, php_1.startQueueWorker)(state_1.default.randomSecret, apiPort, phpIniSettings);
return (0, php_1.startQueueWorker)(state_1.default.randomSecret, state_1.default.electronApiPort, state_1.default.phpIni);
}
else {
return undefined;
}
}
exports.startQueue = startQueue;
function runScheduler() {
(0, php_1.startScheduler)(state_1.default.randomSecret, state_1.default.electronApiPort, state_1.default.phpIni);
}
exports.runScheduler = runScheduler;
function startAPI() {
return (0, api_1.default)(state_1.default.randomSecret);
}
Expand Down
21 changes: 11 additions & 10 deletions dist/server/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,38 @@ const electron_store_1 = __importDefault(require("electron-store"));
const utils_1 = require("./utils");
const settingsStore = new electron_store_1.default();
settingsStore.onDidAnyChange((newValue, oldValue) => {
const changedKey = Object.keys(newValue).find(key => newValue[key] !== oldValue[key]);
const changedKey = Object.keys(newValue).find((key) => newValue[key] !== oldValue[key]);
if (changedKey) {
(0, utils_1.notifyLaravel)('events', {
event: 'Native\\Laravel\\Events\\Settings\\SettingChanged',
(0, utils_1.notifyLaravel)("events", {
event: "Native\\Laravel\\Events\\Settings\\SettingChanged",
payload: {
key: changedKey,
value: newValue[changedKey] || null
}
value: newValue[changedKey] || null,
},
});
}
});
function generateRandomString(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = "";
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
for (let i = 0; i < length; i += 1) {
result += characters.charAt(Math.floor(Math.random() *
charactersLength));
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
exports.default = {
electronApiPort: null,
activeMenuBar: null,
php: null,
phpPort: null,
phpIni: null,
caCert: null,
icon: null,
store: settingsStore,
randomSecret: generateRandomString(32),
windows: {},
findWindow(id) {
return this.windows[id] || null;
}
},
};
14 changes: 6 additions & 8 deletions dist/server/websockets.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ const path_1 = require("path");
const child_process_1 = require("child_process");
const php_1 = require("./php");
const state_1 = __importDefault(require("./state"));
function serveWebsockets() {
if (!(0, fs_1.existsSync)((0, path_1.join)((0, php_1.getAppPath)(), 'vendor', 'beyondcode', 'laravel-websockets'))) {
function startWebsockets() {
if (!(0, fs_1.existsSync)((0, path_1.join)((0, php_1.getAppPath)(), "vendor", "beyondcode", "laravel-websockets"))) {
return;
}
const phpServer = (0, child_process_1.spawn)(state_1.default.php, ["artisan", "websockets:serve"], {
cwd: (0, php_1.getAppPath)()
});
phpServer.stdout.on("data", (data) => {
});
phpServer.stderr.on("data", (data) => {
cwd: (0, php_1.getAppPath)(),
});
phpServer.stdout.on("data", (data) => { });
phpServer.stderr.on("data", (data) => { });
return phpServer;
}
exports.default = serveWebsockets;
exports.default = startWebsockets;
Loading

0 comments on commit 4d105bd

Please sign in to comment.