From a47e6f8fefd0d032ff725eaec3ddfb83d2553be2 Mon Sep 17 00:00:00 2001 From: nuno maduro Date: Sat, 2 May 2026 19:30:14 +0100 Subject: [PATCH] wip --- bin/pest-tia-vite-deps.mjs | 40 +++++++++++++-- src/Plugins/Tia/JsModuleGraph.php | 83 +++++++++++++++++++++++++++---- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/bin/pest-tia-vite-deps.mjs b/bin/pest-tia-vite-deps.mjs index b5c3107b..49133249 100644 --- a/bin/pest-tia-vite-deps.mjs +++ b/bin/pest-tia-vite-deps.mjs @@ -6,10 +6,22 @@ import { createRequire } from 'node:module' import { resolve, relative, extname, sep, join } from 'node:path' import { pathToFileURL } from 'node:url' -const PAGE_EXTENSIONS = new Set(['.vue', '.tsx', '.jsx', '.svelte']) +const PAGE_EXTENSIONS = new Set([ + '.vue', '.svelte', + '.tsx', '.jsx', + '.ts', '.js', + '.mts', '.cts', '.mjs', '.cjs', +]) const ASSET_EXT_RE = /\.(css|scss|sass|less|styl|stylus|svg|png|jpe?g|gif|webp|avif|ico|bmp|woff2?|ttf|eot|otf|md|mdx|txt|html|mp4|webm|mp3|wav|ogg|m4a|pdf|wasm|glsl|frag|vert)$/i const PROJECT_ROOT = resolve(process.argv[2] ?? process.cwd()) -const PAGES_REL = (process.env.TIA_VITE_PAGES_DIR ?? 'resources/js/Pages').replace(/\\/g, '/') +const PAGE_DIR_CANDIDATES = [ + 'resources/js/Pages', + 'resources/js/pages', + 'assets/js/Pages', + 'assets/js/pages', + 'assets/Pages', + 'assets/pages', +] async function loadRolldown() { const projectRequire = createRequire(join(PROJECT_ROOT, 'package.json')) @@ -64,6 +76,22 @@ async function listPageFiles(pagesDir) { return out } +async function discoverPagesDir() { + const override = process.env.TIA_VITE_PAGES_DIR + if (override && override.length > 0) { + return resolve(PROJECT_ROOT, override.replace(/\\/g, '/')) + } + + for (const rel of PAGE_DIR_CANDIDATES) { + const abs = resolve(PROJECT_ROOT, rel) + if (!existsSync(abs)) continue + const files = await listPageFiles(abs) + if (files.length > 0) return abs + } + + return null +} + function componentNameFor(pageAbs, pagesDir) { const rel = relative(pagesDir, pageAbs).split(sep).join('/') const ext = extname(rel) @@ -79,7 +107,13 @@ function isLocalSpecifier(source, aliasKeys) { } async function main() { - const pagesDir = resolve(PROJECT_ROOT, PAGES_REL) + const pagesDir = await discoverPagesDir() + + if (pagesDir === null) { + process.stdout.write('{}') + return + } + const pages = await listPageFiles(pagesDir) if (pages.length === 0) { diff --git a/src/Plugins/Tia/JsModuleGraph.php b/src/Plugins/Tia/JsModuleGraph.php index a889f342..d0e117fa 100644 --- a/src/Plugins/Tia/JsModuleGraph.php +++ b/src/Plugins/Tia/JsModuleGraph.php @@ -27,6 +27,31 @@ final class JsModuleGraph 'vite.config.mts', ]; + /** + * Candidate page directories, in priority order. Must stay in sync with + * `PAGE_DIR_CANDIDATES` in bin/pest-tia-vite-deps.mjs. + * + * @var list + */ + private const array PAGE_DIR_CANDIDATES = [ + 'resources/js/Pages', + 'resources/js/pages', + 'assets/js/Pages', + 'assets/js/pages', + 'assets/Pages', + 'assets/pages', + ]; + + /** + * @var list + */ + private const array PAGE_EXTENSIONS = [ + 'vue', 'svelte', + 'tsx', 'jsx', + 'ts', 'js', + 'mts', 'cts', 'mjs', 'cjs', + ]; + /** * @return array> */ @@ -51,8 +76,44 @@ final class JsModuleGraph return false; } - foreach (['Pages', 'pages'] as $dir) { - if (is_dir($projectRoot.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'js'.DIRECTORY_SEPARATOR.$dir)) { + return self::firstExistingPagesDir($projectRoot) !== null; + } + + private static function firstExistingPagesDir(string $projectRoot): ?string + { + foreach (self::PAGE_DIR_CANDIDATES as $rel) { + $abs = $projectRoot.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $rel); + + if (! is_dir($abs)) { + continue; + } + + if (self::dirHasPageFile($abs)) { + return $abs; + } + } + + return null; + } + + private static function dirHasPageFile(string $dir): bool + { + try { + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::LEAVES_ONLY, + ); + } catch (\UnexpectedValueException) { + return false; + } + + /** @var \SplFileInfo $file */ + foreach ($iterator as $file) { + if (! $file->isFile()) { + continue; + } + + if (in_array(strtolower($file->getExtension()), self::PAGE_EXTENSIONS, true)) { return true; } } @@ -188,17 +249,21 @@ final class JsModuleGraph return null; } - foreach (['Pages', 'pages'] as $dir) { - if (is_dir($projectRoot.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'js'.DIRECTORY_SEPARATOR.$dir)) { - $parts[] = 'pagesDir:'.$dir; + $override = getenv('TIA_VITE_PAGES_DIR'); - break; - } + if (is_string($override) && $override !== '') { + $parts[] = 'pagesDirOverride:'.$override; } - $jsRoot = $projectRoot.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'js'; + $pagesDir = self::firstExistingPagesDir($projectRoot); - if (is_dir($jsRoot)) { + if ($pagesDir !== null) { + $parts[] = 'pagesDir:'.str_replace($projectRoot.DIRECTORY_SEPARATOR, '', $pagesDir); + } + + $jsRoot = $pagesDir !== null ? dirname($pagesDir) : null; + + if ($jsRoot !== null && is_dir($jsRoot)) { $entries = []; $iterator = new \RecursiveIteratorIterator(