mergeConfigFrom(__DIR__ . '/../../config/shippingCarriers/acs.php', 'acs'); $this->mergeConfigFrom(__DIR__ . '/../../config/shippingCarriers/boxnow.php', 'boxnow'); $this->app->singleton(AcsClient::class, fn () => new AcsClient(config('acs'))); $this->app->singleton(BoxNowClient::class, fn () => new BoxNowClient(config('boxnow'))); $this->app->bind(CarrierFulfillmentInterface::class, function ($app, array $params) { return match ($params['carrier'] ?? null) { 'acs' => $app->make(AcsFulfillmentService::class), 'box-now' => $app->make(BoxNowFulfillmentService::class), default => null, }; }); // The vendor Rates page has no extension hook, so we swap it for // our subclass everywhere. Route::get($path, VendorClass::class) // instantiates the vendor class directly via the container for the // initial full-page load (bypassing Livewire's component registry // entirely), so this container bind is required in addition to the // Livewire::component() re-registration below — the bind covers // first load, the Livewire registration covers every AJAX // round-trip (form submits, table interactions) afterwards. $this->app->bind(VendorManageShippingRates::class, ManageShippingRates::class); } public function boot(): void { $this->publishes([ __DIR__ . '/../../config/shippingCarriers/acs.php' => config_path('shippingCarriers/acs.php'), __DIR__ . '/../../config/shippingCarriers/boxnow.php' => config_path('shippingCarriers/boxnow.php'), ], 'core-config'); Order::resolveRelationUsing('shipments', function ($order) { return $order->hasMany(Shipment::class); }); // Deferred: the Shipping facade resolves a binding registered in // lunarphp/table-rate-shipping's own ShippingServiceProvider::boot(), // and provider boot order between packages isn't guaranteed. $this->app->booted(function () { Shipping::extend('acs', fn ($app) => $app->make(AcsRateDriver::class)); Shipping::extend('box-now', fn ($app) => $app->make(BoxNowRateDriver::class)); $this->app->make(ConsoleSchedule::class) ->job(new WarmAcsAreaCacheJob) ->dailyAt('06:00') ->when(fn () => ShippingMethod::where('driver', 'acs')->exists()); $this->app->make(ConsoleSchedule::class) ->job(new PollShipmentTrackingJob) ->everyThirtyMinutes(); $this->overrideRatesPageLivewireComponent(); }); } /** * The vendor Rates page has no extension hook, so we swap it for our * subclass (see Shipping/Filament/Pages/ManageShippingRates). Filament * already registered the vendor class as a Livewire component under a * name derived from its class string (see * Panel::registerLivewireComponents()); Livewire's own registry is a * simple last-write-wins name => class map, so re-registering the same * derived name against our subclass here overrides it — keeping the * route, sub-navigation, and every Livewire round-trip (including form * submissions) pointed at one consistent component identity. */ private function overrideRatesPageLivewireComponent(): void { $name = $this->app->make(ComponentRegistry::class)->getName(VendorManageShippingRates::class); Livewire::component($name, ManageShippingRates::class); } }