diff --git a/package.json b/package.json index 7395dd5..fdf1605 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "private": true, "type": "module", "scripts": { - "build": "vite build", - "dev": "vite", - "build:backend": "vite build --config ./vite.config.js" + "prebuild": "node scripts/install-module-dependencies.mjs", + "build": "vite build --config ./vite.config.js", + "dev": "vite --config ./vite.config.js" }, "dependencies": { "@laravel/passkeys": "^0.2.0", diff --git a/scripts/install-module-dependencies.mjs b/scripts/install-module-dependencies.mjs new file mode 100644 index 0000000..90ef65e --- /dev/null +++ b/scripts/install-module-dependencies.mjs @@ -0,0 +1,54 @@ +import { + existsSync, + readdirSync, + realpathSync, + statSync, +} from 'node:fs'; +import { join } from 'node:path'; +import { spawnSync } from 'node:child_process'; + +const modulesPath = join(process.cwd(), 'Modules'); + +if (!existsSync(modulesPath)) { + process.exit(0); +} + +const installed = new Set(); + +for (const moduleName of readdirSync(modulesPath)) { + const modulePath = join(modulesPath, moduleName); + + if (!statSync(modulePath).isDirectory()) { + continue; + } + + const packageJson = join(modulePath, 'package.json'); + const packageLock = join(modulePath, 'package-lock.json'); + + if (!existsSync(packageJson) || !existsSync(packageLock)) { + continue; + } + + const physicalModulePath = realpathSync(modulePath); + + if (installed.has(physicalModulePath)) { + continue; + } + + installed.add(physicalModulePath); + + console.log(`[Modules] Installing npm dependencies for ${moduleName}...`); + + const result = spawnSync( + 'npm', + ['ci', '--no-audit', '--no-fund'], + { + cwd: modulePath, + stdio: 'inherit', + }, + ); + + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +} diff --git a/vite.config.js b/vite.config.js index 19ce398..7c63cef 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,24 +2,11 @@ import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import { bunny } from 'laravel-vite-plugin/fonts'; import tailwindcss from '@tailwindcss/vite'; -import { existsSync, readdirSync } from 'node:fs'; +import { existsSync, readdirSync, realpathSync, statSync } from 'node:fs'; import { join, relative } from 'node:path'; const projectRoot = process.cwd(); -/** - * Discover module CSS/JS entry points. - * - * Supported module layouts: - * - * Modules/Foo/Resources/assets/css/app.css - * Modules/Foo/Resources/assets/js/app.js - * - * and the lower-case equivalent: - * - * Modules/Foo/resources/assets/css/app.css - * Modules/Foo/resources/assets/js/app.js - */ function discoverModuleInputs() { const modulesPath = join(projectRoot, 'Modules'); @@ -28,19 +15,30 @@ function discoverModuleInputs() { } const inputs = []; + const physicalFiles = new Set(); for (const moduleName of readdirSync(modulesPath)) { const modulePath = join(modulesPath, moduleName); - const candidates = [ - join(modulePath, 'Resources/assets/css/app.css'), - join(modulePath, 'Resources/assets/js/app.js'), - join(modulePath, 'resources/assets/css/app.css'), - join(modulePath, 'resources/assets/js/app.js'), - ]; + if (!statSync(modulePath).isDirectory()) { + continue; + } - for (const candidate of candidates) { - if (existsSync(candidate)) { + for (const resourcesDirectory of ['Resources', 'resources']) { + for (const entry of ['assets/css/app.css', 'assets/js/app.js']) { + const candidate = join(modulePath, resourcesDirectory, entry); + + if (!existsSync(candidate)) { + continue; + } + + const physicalPath = realpathSync(candidate); + + if (physicalFiles.has(physicalPath)) { + continue; + } + + physicalFiles.add(physicalPath); inputs.push(relative(projectRoot, candidate)); } } @@ -55,14 +53,12 @@ console.log('[Vite] Backend theme inputs:'); console.log(' resources/themes/backend/assets/css/app.css'); console.log(' resources/themes/backend/assets/js/passkeys.js'); -if (moduleInputs.length > 0) { +if (moduleInputs.length) { console.log('[Vite] Module inputs:'); for (const input of moduleInputs) { console.log(` ${input}`); } -} else { - console.log('[Vite] No module asset entry points discovered.'); } export default defineConfig({ @@ -77,18 +73,17 @@ export default defineConfig({ refresh: [ 'resources/themes/backend/views/**/*.blade.php', 'resources/themes/backend/assets/**/*', - 'Modules/*/Resources/views/**/*.blade.php', 'Modules/*/Resources/assets/**/*', 'Modules/*/resources/views/**/*.blade.php', 'Modules/*/resources/assets/**/*', - 'Modules/**/*.php', ], fonts: [ bunny('Instrument Sans', { weights: [400, 500, 600], + optimizedFallbacks: false, }), ], }), @@ -98,7 +93,6 @@ export default defineConfig({ server: { cors: true, - watch: { ignored: [ '**/storage/framework/views/**',