From f2454642ca1d4dc350465e1a44de98864a264a70 Mon Sep 17 00:00:00 2001 From: Alex Standiford Date: Tue, 26 May 2026 15:21:18 -0400 Subject: [PATCH] feat(plugin): allow non-Laravel guest frameworks via env-var overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three opt-in env vars in resources/js/electron-plugin/src/server/php.ts: NATIVEPHP_PHP_BOOT_BIN — replaces the hardcoded 'artisan' bin name in command arrays. Default: 'artisan'. NATIVEPHP_SERVER_SCRIPT — replaces the Laravel server.php router path. Default: Laravel's bundled router. NATIVEPHP_SKIP_LARAVEL_SETUP — skips `artisan optimize` and `artisan migrate` in serveApp. Default: off. Optional NATIVEPHP_SERVER_CWD override accompanies SERVER_SCRIPT. All defaults preserve existing Laravel behavior. The runningSecureBuild phar-bundle codepath is unaffected. The motivation is enabling external integration packages (built and verified end-to-end against phpnomad/db: windows open, notifications fire, events flow Electron→PHP through real Electron) without forking the plugin or shipping local patches. The set of overrides is the minimum required to swap the Laravel-specific CLI commands and router script; everything above that layer (the /api/* HTTP surface, the state module, the wire format) is already framework-agnostic. Acknowledges Discussion #141: this is a smallest-possible patch that unblocks downstream integration work without committing the project to maintain non-Laravel frameworks first-class. --- .../js/electron-plugin/dist/server/php.js | 20 ++++++++---- .../js/electron-plugin/src/server/php.ts | 31 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/resources/js/electron-plugin/dist/server/php.js b/resources/js/electron-plugin/dist/server/php.js index 50123a6..f9b478d 100644 --- a/resources/js/electron-plugin/dist/server/php.js +++ b/resources/js/electron-plugin/dist/server/php.js @@ -24,6 +24,9 @@ const databaseFile = join(databasePath, 'database.sqlite'); const bootstrapCache = join(app.getPath('userData'), 'bootstrap', 'cache'); const argumentEnv = getArgumentEnv(); const appPath = getAppPath(); +const BOOT_BIN = process.env.NATIVEPHP_PHP_BOOT_BIN || 'artisan'; +const SERVER_SCRIPT = process.env.NATIVEPHP_SERVER_SCRIPT || ''; +const SKIP_LARAVEL_SETUP = process.env.NATIVEPHP_SKIP_LARAVEL_SETUP === '1'; mkdirpSync(bootstrapCache); mkdirpSync(join(storagePath, 'logs')); mkdirpSync(join(storagePath, 'framework', 'cache')); @@ -77,7 +80,7 @@ function retrievePhpIniSettings() { cwd: appPath, env }; - let command = ['artisan', 'native:php-ini']; + let command = [BOOT_BIN, 'native:php-ini']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } @@ -91,7 +94,7 @@ function retrieveNativePHPConfig() { cwd: appPath, env }; - let command = ['artisan', 'native:config']; + let command = [BOOT_BIN, 'native:config']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } @@ -99,7 +102,7 @@ function retrieveNativePHPConfig() { }); } function callPhp(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { + if (args[0] === BOOT_BIN && runningSecureBuild()) { args.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } let iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); @@ -115,7 +118,7 @@ function callPhp(args, options, phpIniSettings = {}) { }); } function callPhpSync(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { + if (args[0] === BOOT_BIN && runningSecureBuild()) { args.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } let iniSettings = Object.assign(getDefaultPhpIniSettings(), phpIniSettings); @@ -233,7 +236,7 @@ function serveApp(secret, apiPort, phpIniSettings) { const store = new Store({ name: 'nativephp', }); - if (shouldOptimize(store)) { + if (!SKIP_LARAVEL_SETUP && shouldOptimize(store)) { console.log('Caching view and routes...'); let result = callPhpSync(['artisan', 'optimize'], phpOptions, phpIniSettings); if (result.status !== 0) { @@ -243,7 +246,7 @@ function serveApp(secret, apiPort, phpIniSettings) { store.set('optimized_version', app.getVersion()); } } - if (shouldMigrateDatabase(store)) { + if (!SKIP_LARAVEL_SETUP && shouldMigrateDatabase(store)) { console.log('Migrating database...'); if (parseInt(process.env.SHELL_VERBOSITY) > 0) { console.log('Database path:', databaseFile); @@ -265,6 +268,11 @@ function serveApp(secret, apiPort, phpIniSettings) { if (runningSecureBuild()) { serverPath = join(appPath, 'build', '__nativephp_app_bundle'); } + else if (SERVER_SCRIPT !== '') { + console.log('* * * Running from source (custom server script) * * *'); + serverPath = SERVER_SCRIPT; + cwd = process.env.NATIVEPHP_SERVER_CWD || join(appPath, 'public'); + } else { console.log('* * * Running from source * * *'); serverPath = join(appPath, 'vendor', 'laravel', 'framework', 'src', 'Illuminate', 'Foundation', 'resources', 'server.php'); diff --git a/resources/js/electron-plugin/src/server/php.ts b/resources/js/electron-plugin/src/server/php.ts index e66ef85..30ad7a1 100644 --- a/resources/js/electron-plugin/src/server/php.ts +++ b/resources/js/electron-plugin/src/server/php.ts @@ -21,6 +21,13 @@ const bootstrapCache = join(app.getPath('userData'), 'bootstrap', 'cache') const argumentEnv = getArgumentEnv(); const appPath = getAppPath(); +// Optional overrides for non-Laravel guest frameworks. Defaults preserve +// the existing Laravel-targeted behavior in every code path; any framework +// that ships its own CLI + dev-server router can opt in by setting these. +const BOOT_BIN = process.env.NATIVEPHP_PHP_BOOT_BIN || 'artisan'; +const SERVER_SCRIPT = process.env.NATIVEPHP_SERVER_SCRIPT || ''; +const SKIP_LARAVEL_SETUP = process.env.NATIVEPHP_SKIP_LARAVEL_SETUP === '1'; + mkdirpSync(bootstrapCache); mkdirpSync(join(storagePath, 'logs')); mkdirpSync(join(storagePath, 'framework', 'cache')); @@ -96,7 +103,7 @@ async function retrievePhpIniSettings() { env }; - let command = ['artisan', 'native:php-ini']; + let command = [BOOT_BIN, 'native:php-ini']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); @@ -113,7 +120,7 @@ async function retrieveNativePHPConfig() { env }; - let command = ['artisan', 'native:config']; + let command = [BOOT_BIN, 'native:config']; if (runningSecureBuild()) { command.unshift(join(appPath, 'build', '__nativephp_app_bundle')); @@ -124,7 +131,7 @@ async function retrieveNativePHPConfig() { function callPhp(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { + if (args[0] === BOOT_BIN && runningSecureBuild()) { args.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } @@ -153,7 +160,7 @@ function callPhp(args, options, phpIniSettings = {}) { function callPhpSync(args, options, phpIniSettings = {}) { - if (args[0] === 'artisan' && runningSecureBuild()) { + if (args[0] === BOOT_BIN && runningSecureBuild()) { args.unshift(join(appPath, 'build', '__nativephp_app_bundle')); } @@ -347,8 +354,9 @@ function serveApp(secret, apiPort, phpIniSettings): Promise { name: 'nativephp', // So it doesn't conflict with settings of the app }); - // Cache the project - if (shouldOptimize(store)) { + // Cache the project — Laravel-specific (artisan optimize). Skip + // when the guest framework manages its own caching/optimization. + if (!SKIP_LARAVEL_SETUP && shouldOptimize(store)) { console.log('Caching view and routes...'); let result = callPhpSync(['artisan', 'optimize'], phpOptions, phpIniSettings); @@ -360,8 +368,10 @@ function serveApp(secret, apiPort, phpIniSettings): Promise { } } - // Migrate the database - if (shouldMigrateDatabase(store)) { + // Migrate the database — Laravel-specific (artisan migrate). Skip + // when the guest framework owns its own migration story (e.g. a + // non-Laravel app handling SQLite schema on its own). + if (!SKIP_LARAVEL_SETUP && shouldMigrateDatabase(store)) { console.log('Migrating database...'); if(parseInt(process.env.SHELL_VERBOSITY) > 0) { @@ -387,6 +397,11 @@ function serveApp(secret, apiPort, phpIniSettings): Promise { if (runningSecureBuild()) { serverPath = join(appPath, 'build', '__nativephp_app_bundle'); + } else if (SERVER_SCRIPT !== '') { + // Guest framework supplies its own front-controller / router. + console.log('* * * Running from source (custom server script) * * *'); + serverPath = SERVER_SCRIPT; + cwd = process.env.NATIVEPHP_SERVER_CWD || join(appPath, 'public'); } else { console.log('* * * Running from source * * *'); serverPath = join(appPath, 'vendor', 'laravel', 'framework', 'src', 'Illuminate', 'Foundation', 'resources', 'server.php');