Skip to content

Commit 0dc314f

Browse files
committed
fix: patch up broken inertia integration
1 parent 4bdcd48 commit 0dc314f

8 files changed

Lines changed: 83 additions & 6 deletions

File tree

src/ViewInstallCommand.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ protected function installReact()
169169
'recursive' => true,
170170
]);
171171

172+
$this->setupLiteFrontend($directory);
173+
172174
$package = json_decode(file_get_contents("$directory/package.json"), true);
173175
$package['type'] = 'module';
174176
$package['scripts']['dev'] = 'vite';
@@ -233,6 +235,8 @@ protected function installSvelte()
233235
'recursive' => true,
234236
]);
235237

238+
$this->setupLiteFrontend($directory);
239+
236240
$package = json_decode(file_get_contents("$directory/package.json"), true);
237241
$package['type'] = 'module';
238242
$package['scripts']['dev'] = 'vite';
@@ -407,10 +411,12 @@ protected function installVue()
407411
return 1;
408412
}
409413

410-
\Leaf\FS\Directory::copy(__DIR__ . '/themes/tailwind', $directory, [
414+
\Leaf\FS\Directory::copy(__DIR__ . '/themes/vue', $directory, [
411415
'recursive' => true,
412416
]);
413417

418+
$this->setupLiteFrontend($directory);
419+
414420
$package = json_decode(file_get_contents("$directory/package.json"), true);
415421
$package['type'] = 'module';
416422
$package['scripts']['dev'] = 'vite';
@@ -451,6 +457,57 @@ protected function installVue()
451457
}
452458

453459
// ------------------------ utils ------------------------ //
460+
461+
/**
462+
* Wire up index.php for a lite (non-MVC) frontend install: point the
463+
* view engine at the copied views/ directory, cache compiled views in
464+
* storage/cache, and load the demo routes file the theme ships with.
465+
* Idempotent — safe to run on repeated installs.
466+
*/
467+
protected function setupLiteFrontend(string $directory)
468+
{
469+
$indexFile = "$directory/index.php";
470+
471+
$viewConfig = <<<'PHP'
472+
app()->config([
473+
'views.path' => 'views',
474+
'views.cache' => __DIR__ . '/storage/cache',
475+
]);
476+
PHP;
477+
478+
$routesRequire = "require __DIR__ . '/routes/_frontend.php';";
479+
480+
if (!file_exists($indexFile)) {
481+
file_put_contents(
482+
$indexFile,
483+
"<?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n$viewConfig\n\n$routesRequire\n\napp()->run();\n"
484+
);
485+
486+
return;
487+
}
488+
489+
\Leaf\FS\File::write($indexFile, function ($content) use ($viewConfig, $routesRequire) {
490+
$additions = '';
491+
492+
if (strpos($content, "'views.path'") === false && strpos($content, '"views.path"') === false) {
493+
$additions .= "$viewConfig\n\n";
494+
}
495+
496+
if (strpos($content, 'routes/_frontend.php') === false) {
497+
$additions .= "$routesRequire\n\n";
498+
}
499+
500+
if ($additions === '') {
501+
return $content;
502+
}
503+
504+
if (strpos($content, 'app()->run();') !== false) {
505+
return str_replace('app()->run();', "$additions" . 'app()->run();', $content);
506+
}
507+
508+
return rtrim($content) . "\n\n" . rtrim($additions) . "\n";
509+
});
510+
}
454511
protected function isMVCApp()
455512
{
456513
$directory = getcwd();

src/themes/leaf3/AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
Before performing any task:
44

55
1. Read `.leaf/CONTEXT.md` for project goals and architectural decisions.
6-
2. Use Leaf documentation:
6+
2. Use Leaf documentation. Fetch these RAW (curl or a non-summarizing fetch) — summarized docs have invented APIs that don't exist:
77

88
- https://leafphp.dev/ai/SKILL.md
9+
- https://leafphp.dev/ai/references/lite.md — this is a lite app: modules that MVC auto-configures need manual wiring here, and this file is the complete contract (db, views, Vite, schema). Read it before writing any setup code.
910
- https://leafphp.dev/llms.txt
1011

1112
3. Inspect the codebase and use `leaf context` when you need a concise map of the application's structure. `context` lives in the global `leaf` CLI (no `php` prefix) — `php leaf context` will fail.

src/themes/react/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default defineConfig({
66
plugins: [
77
leaf({
88
hotFile: 'hot',
9-
input: ['app/views/js/app.jsx'],
9+
input: ['views/js/app.jsx'],
1010
refresh: true,
1111
}),
1212
react(),

src/themes/svelte/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
55
export default defineConfig({
66
plugins: [
77
leaf({
8-
input: ['app/views/js/app.js', 'app/views/css/app.css'],
8+
input: ['views/js/app.js'],
99
refresh: true,
1010
}),
1111
svelte(),

src/themes/tailwind/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default defineConfig({
66
plugins: [
77
tailwindcss(),
88
leaf({
9-
input: ["js/app.js", "css/app.css"],
9+
input: ["views/css/app.css"],
1010
refresh: true,
1111
}),
1212
],

src/themes/vue/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import vue from "@vitejs/plugin-vue";
55
export default defineConfig({
66
plugins: [
77
leaf({
8-
input: ["app/views/js/app.jsx"],
8+
input: ["views/js/app.js"],
99
refresh: true,
1010
}),
1111
vue({

tests/commands.test.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@
127127
}
128128
});
129129

130+
test('lite theme vite inputs point at files the theme ships', function () {
131+
// view:install copies each theme into the project root, so every
132+
// entry in the theme's vite.config.js input must resolve relative
133+
// to the theme dir itself — an app/views/* path builds nothing
134+
foreach (['react', 'svelte', 'vue'] as $theme) {
135+
$themeDir = dirname(__DIR__) . "/src/themes/$theme";
136+
$config = file_get_contents("$themeDir/vite.config.js");
137+
138+
preg_match('/input:\s*\[([^\]]*)\]/', $config, $inputList);
139+
preg_match_all('/[\'"]([^\'"]+)[\'"]/', $inputList[1] ?? '', $inputs);
140+
141+
expect($inputs[1])->not->toBeEmpty();
142+
143+
foreach ($inputs[1] as $input) {
144+
expect(file_exists("$themeDir/$input"))->toBeTrue("$theme vite input '$input' does not exist in the copied theme");
145+
}
146+
}
147+
});
148+
130149
test('lite apps are born AI-ready', function () {
131150
leaf('create my-app --lite');
132151

0 commit comments

Comments
 (0)