Skip to content

feat(plugin): allow non-Laravel guest frameworks via three opt-in env vars#265

Open
alexstandiford wants to merge 1 commit into
NativePHP:mainfrom
alexstandiford:feat/non-laravel-framework-support
Open

feat(plugin): allow non-Laravel guest frameworks via three opt-in env vars#265
alexstandiford wants to merge 1 commit into
NativePHP:mainfrom
alexstandiford:feat/non-laravel-framework-support

Conversation

@alexstandiford
Copy link
Copy Markdown

Summary

Three opt-in env-var overrides in resources/js/electron-plugin/src/server/php.ts that let a guest framework other than Laravel use the existing Electron backend without forking the plugin. All defaults preserve existing Laravel behavior in every code path — there is no impact on current users.

Env var Replaces Default
NATIVEPHP_PHP_BOOT_BIN Hardcoded 'artisan' bin name in retrievePhpIniSettings, retrieveNativePHPConfig, and the callPhp / callPhpSync secure-build branch 'artisan'
NATIVEPHP_SERVER_SCRIPT Laravel's bundled router path (vendor/laravel/framework/src/Illuminate/Foundation/resources/server.php) in serveApp unset → Laravel router
NATIVEPHP_SKIP_LARAVEL_SETUP artisan optimize and artisan migrate --force calls in serveApp (gated when the guest framework manages its own caching/migrations) unset → Laravel behavior

Optional companion: NATIVEPHP_SERVER_CWD lets a guest framework set the working directory for the spawned PHP server when it isn't appPath/public. Honored only when NATIVEPHP_SERVER_SCRIPT is set.

Why

The plugin's PHP-side HTTP API (the /api/* surface in resources/js/electron-plugin/src/server/api/*.ts) is already wire-format-agnostic — it doesn't care what PHP framework is on the other end. The only Laravel coupling lives in three concrete places in php.ts:

  1. The hardcoded 'artisan' bin name when invoking the PHP-side CLI
  2. The hardcoded Laravel router script path when spawning the PHP dev server
  3. The hardcoded artisan optimize / artisan migrate calls inside serveApp

This PR makes those three points overridable. The set of overrides is the minimum surface required to swap the Laravel-specific bits; everything else (the API server, state, utils.notifyLaravel, the /_native/api/* callback convention, the env vars the plugin sets for the PHP process) is unchanged and already framework-agnostic.

Real-world validation

I built a working non-Laravel integration on top of phpnomad/db (https://github.com/phpnomad/sqlite-integration). With this patch applied to electron-plugin locally:

  • A composer require phpnomad/nativephp-integration style package can plug into the Electron backend without modifying the plugin
  • Window definitions register through a WindowManager and open at boot
  • Notification, Window, Dialog, Clipboard, Shell, Settings, Screen, System, Dock, MenuBar, Menu, ContextMenu, PowerMonitor, GlobalShortcut, ProgressBar, Process all work as drop-in feature classes that post to the same /api/* endpoints Laravel apps use
  • Events flow Electron→PHP via the same notifyLaravel('events', { event, payload }) mechanism — the plugin doesn't need to know about the receiving framework's event class names
  • Full bidirectional round trip works end-to-end: PHP fires a notification, Electron shows it; window focuses, Electron fires WindowFocused into PHP, PHP fires another notification back

Without this patch, every non-Laravel integration must ship a local fork of electron-plugin or apply runtime patches via patch-package — both of which are friction that this small change removes.

I'm aware of Discussion #141 where the maintainers noted "we're not actively working on supporting frameworks other than Laravel at this time." This PR doesn't ask the project to do that work; it just opens three doors so external maintainers can do it without depending on plugin forks. Laravel remains the only first-class supported framework; this is purely "don't actively block other people from doing the work."

Diff overview

8 net lines of new logic + a few comments. The full diff is +37 / -14 across php.ts and the matching compiled php.js (since dist/ is checked in). Touches one source file. No new dependencies, no API changes, no positional argument changes to bootstrap(), no changes to env vars the plugin sets for PHP.

// New module-level constants near the top of php.ts:
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';

retrievePhpIniSettings / retrieveNativePHPConfig: ['artisan', ...][BOOT_BIN, ...] (two occurrences).
callPhp / callPhpSync: if (args[0] === 'artisan' ...)if (args[0] === BOOT_BIN ...) (two occurrences).
serveApp: optimize and migrate calls gated by !SKIP_LARAVEL_SETUP; new else if (SERVER_SCRIPT !== '') branch for the server-script selection that sits between runningSecureBuild() and the Laravel default.

What this does NOT change

  • The state module, utils.notifyLaravel, the entire server/api/* surface
  • The bootstrap() signature in index.ts
  • The getDefaultEnvironmentVariables() env vars the plugin passes to the PHP process (NATIVEPHP_API_URL, NATIVEPHP_SECRET, etc.)
  • The runningSecureBuild() phar-bundle code path
  • Anything about how Electron itself starts, windows are opened, the API HTTP server listens, or auto-update works

A Laravel app with none of these env vars set behaves identically to today.

Test plan

  • npm run plugin:build from resources/js/ — compiles cleanly with no new TypeScript errors
  • npm run plugin:test — all 7 existing tests pass (api.test.ts × 3, mocking.test.ts × 3, utils.test.ts × 1)
  • Verified the patch against a non-Laravel integration end-to-end with real Electron + a real PHP server (see "Real-world validation" above)

I deliberately did not add new tests to tests/php.test.ts — there's no existing test coverage of php.ts to extend (the existing test files cover api, mocking, utils only), and introducing a mocking strategy for the heavily process-spawning / fs-touching code in php.ts is meaningfully more work than this patch itself. Happy to add tests in a follow-up if you'd prefer that to land separately, or in this PR if you want it co-located — let me know.

Compatibility / risk

  • Default-preserving: every new branch is guarded by an env var check that's false by default
  • No new dependencies
  • No API surface change: bootstrap() signature, exported functions, env vars passed to PHP — all unchanged
  • Tested: existing test suite + manual end-to-end verification

Happy to iterate on naming, structure, or scope — including factoring the override config into a single object instead of three independent env vars if that's preferred. Just let me know.

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 NativePHP#141: this is a smallest-possible patch that
unblocks downstream integration work without committing the project
to maintain non-Laravel frameworks first-class.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant