Skip to content

Commit

Permalink
Restore changes from other PR
Browse files Browse the repository at this point in the history
  • Loading branch information
simonhamp committed Dec 9, 2024
1 parent 9a02339 commit 8b0e43d
Showing 1 changed file with 128 additions and 87 deletions.
215 changes: 128 additions & 87 deletions resources/js/electron-plugin/src/server/php.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {mkdirSync, statSync, writeFileSync, existsSync} from 'fs'
import {copySync} from 'fs-extra'
import Store from 'electron-store'
import {promisify} from 'util'
import {join} from 'path'
import {app} from 'electron'
import {exec, execFile, spawn} from 'child_process'
import { mkdirSync, statSync, writeFileSync, existsSync } from 'fs';
import { copySync } from 'fs-extra';
import Store from 'electron-store';
import { promisify } from 'util';
import { join } from 'path';
import { app } from 'electron';
import { exec, execFile, spawn } from 'child_process';
import state from "./state";
import getPort from 'get-port';
import { ProcessResult } from "./ProcessResult";

const storagePath = join(app.getPath('userData'), 'storage')
const databasePath = join(app.getPath('userData'), 'database')
const databaseFile = join(databasePath, 'database.sqlite')
const storagePath = join(app.getPath('userData'), 'storage');
const databasePath = join(app.getPath('userData'), 'database');
const databaseFile = join(databasePath, 'database.sqlite');
const argumentEnv = getArgumentEnv();
const appPath = getAppPath();

Expand All @@ -23,18 +23,24 @@ async function getPhpPort() {
}

async function retrievePhpIniSettings() {
const env = {
NATIVEPHP_RUNNING: 'true',
NATIVEPHP_STORAGE_PATH: storagePath,
NATIVEPHP_DATABASE_PATH: databaseFile,
};

const phpOptions = {
cwd: appPath,
env
};

return await promisify(execFile)(state.php, ['artisan', 'native:php-ini'], phpOptions);
const env = {
NATIVEPHP_RUNNING: 'true',
NATIVEPHP_STORAGE_PATH: storagePath,
NATIVEPHP_DATABASE_PATH: databaseFile,
};

const phpOptions = {
cwd: appPath,
env,
};

let command = ['artisan', 'native:php-ini'];

if (runningSecureBuild()) {
command.unshift(join(appPath, 'build', '__nativephp_app_bundle'));
}

return await promisify(execFile)(state.php, command, phpOptions);
}

async function retrieveNativePHPConfig() {
Expand All @@ -46,33 +52,47 @@ async function retrieveNativePHPConfig() {

const phpOptions = {
cwd: appPath,
env
env,
};

return await promisify(execFile)(state.php, ['artisan', 'native:config'], phpOptions);
let command = ['artisan', 'native:config'];

if (runningSecureBuild()) {
command.unshift(join(appPath, 'build', '__nativephp_app_bundle'));
}

return await promisify(execFile)(state.php, command, phpOptions);
}

function callPhp(args, options, phpIniSettings = {}) {
let defaultIniSettings = {
'memory_limit': '512M',
'curl.cainfo': state.caCert,
'openssl.cafile': state.caCert
if (args[0] === 'artisan' && runningSecureBuild()) {
args.unshift(join(appPath, 'build', '__nativephp_app_bundle'));
}

let defaultIniSettings = {
'memory_limit': '512M',
'curl.cainfo': state.caCert,
'openssl.cafile': state.caCert,
};

let iniSettings = Object.assign(defaultIniSettings, phpIniSettings);

Object.keys(iniSettings).forEach(key => {
args.unshift('-d', `${key}=${iniSettings[key]}`);
args.unshift('-d', `${key}=${iniSettings[key]}`);
});

if (parseInt(process.env.SHELL_VERBOSITY) > 0) {
console.log('Calling PHP', state.php, args);
}

return spawn(
state.php,
args,
{
cwd: options.cwd,
env: {
...process.env,
...options.env
...options.env,
},
}
);
Expand All @@ -87,6 +107,7 @@ function getArgumentEnv() {
} = {

};

envArgs.forEach(arg => {
const [key, value] = arg.slice(6).split('=');
env[key] = value;
Expand All @@ -96,26 +117,27 @@ function getArgumentEnv() {
}

function getAppPath() {
let appPath = join(__dirname, '../../resources/app/').replace('app.asar', 'app.asar.unpacked')
let appPath = join(__dirname, '../../resources/app/').replace('app.asar', 'app.asar.unpacked');

if (process.env.NODE_ENV === 'development' || argumentEnv.TESTING == 1) {
appPath = process.env.APP_PATH || argumentEnv.APP_PATH;
}

return appPath;
}

function ensureAppFoldersAreAvailable() {
if (! existsSync(storagePath) || process.env.NODE_ENV === 'development') {
copySync(join(appPath, 'storage'), storagePath)
copySync(join(appPath, 'storage'), storagePath);
}

mkdirSync(databasePath, {recursive: true})
mkdirSync(databasePath, {recursive: true});

// Create a database file if it doesn't exist
try {
statSync(databaseFile)
statSync(databaseFile);
} catch (error) {
writeFileSync(databaseFile, '')
writeFileSync(databaseFile, '');
}
}

Expand All @@ -127,12 +149,12 @@ function startQueueWorker(secret, apiPort, phpIniSettings = {}) {
NATIVEPHP_DATABASE_PATH: databaseFile,
NATIVEPHP_API_URL: `http://localhost:${apiPort}/api/`,
NATIVEPHP_RUNNING: true,
NATIVEPHP_SECRET: secret
NATIVEPHP_SECRET: secret,
};

const phpOptions = {
cwd: appPath,
env
env,
};

return callPhp(['artisan', 'queue:work'], phpOptions, phpIniSettings);
Expand All @@ -143,99 +165,113 @@ function startScheduler(secret, apiPort, phpIniSettings = {}) {

const phpOptions = {
cwd: appPath,
env
env,
};

return callPhp(['artisan', 'schedule:run'], phpOptions, phpIniSettings);
}

function getPath(name: string) {
try {
// @ts-ignore
return app.getPath(name);
} catch (error) {
return '';
}
try {
// @ts-ignore
return app.getPath(name);
} catch (error) {
return '';
}
}

function getDefaultEnvironmentVariables(secret, apiPort) {
return {
APP_ENV: process.env.NODE_ENV === 'development' ? 'local' : 'production',
APP_DEBUG: process.env.NODE_ENV === 'development' ? 'true' : 'false',
NATIVEPHP_STORAGE_PATH: storagePath,
NATIVEPHP_DATABASE_PATH: databaseFile,
NATIVEPHP_API_URL: `http://localhost:${apiPort}/api/`,
NATIVEPHP_RUNNING: true,
NATIVEPHP_SECRET: secret,
NATIVEPHP_USER_HOME_PATH: getPath('home'),
NATIVEPHP_APP_DATA_PATH: getPath('appData'),
NATIVEPHP_USER_DATA_PATH: getPath('userData'),
NATIVEPHP_DESKTOP_PATH: getPath('desktop'),
NATIVEPHP_DOCUMENTS_PATH: getPath('documents'),
NATIVEPHP_DOWNLOADS_PATH: getPath('downloads'),
NATIVEPHP_MUSIC_PATH: getPath('music'),
NATIVEPHP_PICTURES_PATH: getPath('pictures'),
NATIVEPHP_VIDEOS_PATH: getPath('videos'),
NATIVEPHP_RECENT_PATH: getPath('recent'),
};
return {
APP_ENV: process.env.NODE_ENV === 'development' ? 'local' : 'production',
APP_DEBUG: process.env.NODE_ENV === 'development' ? 'true' : 'false',
LARAVEL_STORAGE_PATH: storagePath,
NATIVEPHP_STORAGE_PATH: storagePath,
NATIVEPHP_DATABASE_PATH: databaseFile,
NATIVEPHP_API_URL: `http://localhost:${apiPort}/api/`,
NATIVEPHP_RUNNING: true,
NATIVEPHP_SECRET: secret,
NATIVEPHP_USER_HOME_PATH: getPath('home'),
NATIVEPHP_APP_DATA_PATH: getPath('appData'),
NATIVEPHP_USER_DATA_PATH: getPath('userData'),
NATIVEPHP_DESKTOP_PATH: getPath('desktop'),
NATIVEPHP_DOCUMENTS_PATH: getPath('documents'),
NATIVEPHP_DOWNLOADS_PATH: getPath('downloads'),
NATIVEPHP_MUSIC_PATH: getPath('music'),
NATIVEPHP_PICTURES_PATH: getPath('pictures'),
NATIVEPHP_VIDEOS_PATH: getPath('videos'),
NATIVEPHP_RECENT_PATH: getPath('recent'),
};
}

function runningSecureBuild() {
return existsSync(join(appPath, 'build', '__nativephp_app_bundle'))
}

function serveApp(secret, apiPort, phpIniSettings): Promise<ProcessResult> {
return new Promise(async (resolve, reject) => {
const appPath = getAppPath();

console.log('Starting PHP server...', `${state.php} artisan serve`, appPath, phpIniSettings)
console.log('Starting PHP server...', `${state.php} artisan serve`, appPath, phpIniSettings);

ensureAppFoldersAreAvailable();

console.log('Making sure app folders are available')
console.log('Making sure app folders are available');

const env = getDefaultEnvironmentVariables(secret, apiPort);

const phpOptions = {
cwd: appPath,
env
env,
};

const store = new Store();

// Make sure the storage path is linked - as people can move the app around, we
// need to run this every time the app starts
callPhp(['artisan', 'storage:link', '--force'], phpOptions, phpIniSettings)
if (! runningSecureBuild()) {
callPhp(['artisan', 'storage:link', '--force'], phpOptions, phpIniSettings)
}

// Migrate the database
if (store.get('migrated_version') !== app.getVersion() && process.env.NODE_ENV !== 'development') {
console.log('Migrating database...')
callPhp(['artisan', 'migrate', '--force'], phpOptions, phpIniSettings)
store.set('migrated_version', app.getVersion())
if (shouldMigrateDatabase(store)) {
console.log('Migrating database...');
callPhp(['artisan', 'migrate', '--force'], phpOptions, phpIniSettings);
store.set('migrated_version', app.getVersion());
}

if (process.env.NODE_ENV === 'development') {
console.log('Skipping Database migration while in development.')
console.log('You may migrate manually by running: php artisan native:migrate')
console.log('Skipping Database migration while in development.');
console.log('You may migrate manually by running: php artisan native:migrate');
}

const phpPort = await getPhpPort();

const serverPath = join(appPath, 'vendor', 'laravel', 'framework', 'src', 'Illuminate', 'Foundation', 'resources', 'server.php')
let serverPath = join(appPath, 'build', '__nativephp_app_bundle');

if (! runningSecureBuild()) {
console.log('* * * Running from source * * *');
serverPath = join(appPath, 'vendor', 'laravel', 'framework', 'src', 'Illuminate', 'Foundation', 'resources', 'server.php');
}

const phpServer = callPhp(['-S', `127.0.0.1:${phpPort}`, serverPath], {
cwd: join(appPath, 'public'),
env
}, phpIniSettings)
env,
}, phpIniSettings);

const portRegex = /Development Server \(.*:([0-9]+)\) started/gm
const portRegex = /Development Server \(.*:([0-9]+)\) started/gm;

phpServer.stdout.on('data', (data) => {
const match = portRegex.exec(data.toString())
const match = portRegex.exec(data.toString());

if (match) {
console.log("PHP Server started on port: ", match[1])
const port = parseInt(match[1])
console.log("PHP Server started on port: ", match[1]);
const port = parseInt(match[1]);
resolve({
port,
process: phpServer
})
process: phpServer,
});
}
})
});

phpServer.stderr.on('data', (data) => {
const error = data.toString();
Expand All @@ -246,7 +282,7 @@ function serveApp(secret, apiPort, phpIniSettings): Promise<ProcessResult> {
console.log("PHP Server started on port: ", port);
resolve({
port,
process: phpServer
process: phpServer,
});
} else {
// 27 is the length of the php -S output preamble
Expand All @@ -262,9 +298,14 @@ function serveApp(secret, apiPort, phpIniSettings): Promise<ProcessResult> {
});

phpServer.on('error', (error) => {
reject(error)
})
reject(error);
});
})
}

export {startQueueWorker, startScheduler, serveApp, getAppPath, retrieveNativePHPConfig, retrievePhpIniSettings}
function shouldMigrateDatabase(store) {
return store.get('migrated_version') !== app.getVersion()
&& process.env.NODE_ENV !== 'development';
}

export { startQueueWorker, startScheduler, serveApp, getAppPath, retrieveNativePHPConfig, retrievePhpIniSettings };

0 comments on commit 8b0e43d

Please sign in to comment.