diff --git a/src/Features/ViteBundler.php b/src/Features/ViteBundler.php index 96f379b7..987187c7 100644 --- a/src/Features/ViteBundler.php +++ b/src/Features/ViteBundler.php @@ -5,8 +5,8 @@ declare(strict_types=1); namespace Stancl\Tenancy\Features; use Illuminate\Foundation\Application; +use Illuminate\Support\Facades\Vite; use Stancl\Tenancy\Contracts\Feature; -use Stancl\Tenancy\Overrides\Vite; use Stancl\Tenancy\Tenancy; class ViteBundler implements Feature @@ -21,6 +21,8 @@ class ViteBundler implements Feature public function bootstrap(Tenancy $tenancy): void { - $this->app->singleton(\Illuminate\Foundation\Vite::class, Vite::class); + Vite::createAssetPathsUsing(function ($path, $secure = null) { + return global_asset($path); + }); } } diff --git a/src/Overrides/Vite.php b/src/Overrides/Vite.php deleted file mode 100644 index 66bc9268..00000000 --- a/src/Overrides/Vite.php +++ /dev/null @@ -1,22 +0,0 @@ -toBeInstanceOf(Vite::class); - expect($vite)->not()->toBeInstanceOf(StanclVite::class); +use function Stancl\Tenancy\Tests\pest; +beforeEach(function () { config([ - 'tenancy.features' => [ViteBundler::class], + 'app.asset_url' => null, + 'tenancy.filesystem.asset_helper_override' => true, + 'tenancy.bootstrappers' => [FilesystemTenancyBootstrapper::class], ]); - $tenant = Tenant::create(); + TenancyUrlGenerator::$prefixRouteNames = false; + TenancyUrlGenerator::$passTenantParameterToRoutes = true; + TenantAssetController::$headers = []; - tenancy()->initialize($tenant); + $manifestPath = public_path('build/manifest.json'); + File::ensureDirectoryExists(dirname($manifestPath)); + File::put($manifestPath, json_encode([ + 'foo' => [ + 'file' => 'assets/foo-AbC123.js', + 'src' => 'js/foo.js', + ], + ])); - app()->forgetInstance(Vite::class); - - $vite = app(Vite::class); - - expect($vite)->toBeInstanceOf(StanclVite::class); + $this->tenant = Tenant::create(); + $this->assetPath = 'foo'; }); + +test('vite bundler ensures vite assets use global_asset when asset_helper_override is enabled', function () { + config(['tenancy.features' => [ViteBundler::class]]); + + app(CloneRoutesAsTenant::class)->handle(); + + Event::listen(TenancyInitialized::class, BootstrapTenancy::class); + Event::listen(TenancyEnded::class, RevertToCentralContext::class); + + tenancy()->initialize($this->tenant); + + expect(asset($this->assetPath)) + ->toBe(route('stancl.tenancy.asset', ['path' => $this->assetPath])) + ->and(global_asset($this->assetPath)) + ->toBe('http://localhost/' . $this->assetPath); + + $viteAssetUrl = app(Vite::class)->asset($this->assetPath); + $expectedGlobalUrl = global_asset('build/assets/foo-AbC123.js'); + + expect($viteAssetUrl) + ->toBe($expectedGlobalUrl) + ->and($viteAssetUrl) + ->not->toBe(route('stancl.tenancy.asset', ['path' => 'build/assets/foo-AbC123.js'])); +}); + +test('vite uses tenant assets when asset_helper_override is enabled without ViteBundler', function () { + config(['tenancy.features' => []]); + + app(CloneRoutesAsTenant::class)->handle(); + + Event::listen(TenancyInitialized::class, BootstrapTenancy::class); + Event::listen(TenancyEnded::class, RevertToCentralContext::class); + + tenancy()->initialize($this->tenant); + + expect(asset($this->assetPath)) + ->toBe(route('stancl.tenancy.asset', ['path' => $this->assetPath])) + ->and(global_asset($this->assetPath)) + ->toBe('http://localhost/' . $this->assetPath); + + $viteAssetUrl = app(Vite::class)->asset($this->assetPath); + + expect($viteAssetUrl) + ->toBe(route('stancl.tenancy.asset', ['path' => 'build/assets/foo-AbC123.js'])) + ->and($viteAssetUrl) + ->not->toBe(global_asset('build/assets/foo-AbC123.js')); +}); + +test('vite asset helper works correctly with path identification', function (bool $kernelIdentification) { + TenancyUrlGenerator::$prefixRouteNames = true; + TenancyUrlGenerator::$passTenantParameterToRoutes = true; + + config([ + 'tenancy.filesystem.asset_helper_override' => true, + 'tenancy.features' => [ViteBundler::class], + 'tenancy.identification.default_middleware' => InitializeTenancyByPath::class, + 'tenancy.bootstrappers' => array_merge([UrlGeneratorBootstrapper::class], config('tenancy.bootstrappers')), + ]); + + Event::listen(TenancyInitialized::class, BootstrapTenancy::class); + Event::listen(TenancyEnded::class, RevertToCentralContext::class); + + $viteRoute = Route::prefix('{tenant}')->get('/vite_helper', function () { + return app(Vite::class)->asset('foo'); + })->name('tenant.helper.vite'); + + $assetRoute = Route::prefix('{tenant}')->get('/asset_helper', function () { + return asset('foo'); + })->name('tenant.helper.asset'); + + if ($kernelIdentification) { + app(Kernel::class)->pushMiddleware(InitializeTenancyByPath::class); + } else { + $viteRoute->middleware(InitializeTenancyByPath::class); + $assetRoute->middleware(InitializeTenancyByPath::class); + } + + app(CloneRoutesAsTenant::class)->handle(); + + tenancy()->initialize(Tenant::create()); + + expect(pest()->get(route('tenant.helper.asset'))->getContent()) + ->toBe(route('stancl.tenancy.asset', ['path' => 'foo'])); + expect(pest()->get(route('tenant.helper.vite'))->getContent()) + ->toBe(global_asset('build/assets/foo-AbC123.js')); +})->with([ + 'kernel identification' => true, + 'route-level identification' => false, +]);