A round of fixes for the route generator and the typescript:install command.
Fix provider config file detection in install command (#84)
typescript:install failed for apps created before Laravel 11 that later upgraded, because those apps have no bootstrap/providers.php file and the command assumed it was always present. The command now detects the correct provider registration target instead of relying on that file existing.
Thanks @TheoGibbons.
Fix silent failure registering the service provider in typescript:install (#89)
typescript:install injected the service provider into bootstrap/providers.php with a str_replace anchored on a literal fully qualified class string, so it silently did nothing (while still reporting success) whenever that file used short, imported class names (#86). It now uses Laravel's ServiceProvider::addProviderToBootstrapFile(), which evaluates the file rather than matching raw text and therefore handles every layout, and it reports an honest error when registration is not possible.
The misleading typescript:transform message now points users to typescript:install, and the unreachable namespace rewriting was dropped to keep the command simple.
Thanks @rubenvanassche.
Keep routes that share a controller in the route generator (#90)
Routes were indexed by controller identity (invokable class, or class@method), so any two routes pointing at the same endpoint overwrote each other and only the last one survived in the generated TypeScript (#87). This silently dropped Route::inertia() pages and the per-locale routes registered by localized routing packages. RouteController::$actions is now a flat list of route bindings instead of a map keyed by method, so the resolver appends every route and the helper emits all named routes.
Thanks @rubenvanassche.
Throw on missing route in generated route(), add hasRoute predicate (#85)
Calling the generated route() with an unknown name returned the literal string /undefined (an accidental result of '/' + undefined), which silently produced broken URLs in href attributes and elsewhere. route() now throws when the name is not in the manifest, matching Laravel's server-side RouteNotFoundException and surfacing the bug at the call site (spatie/typescript-transformer#151).
A new exported hasRoute(name): name is keyof RouteParameters predicate is emitted alongside route(), mirroring Laravel's Route::has(). It is the safe way to guard the throw for callers that work with dynamic names, such as locale routing wrappers or runtime-composed strings.
// before: could silently produce /undefined
const url = route(maybeName);
// after
if (hasRoute(maybeName)) {
const url = route(maybeName);
}For well-typed TypeScript this is impossible to hit, since the parameter type already constrains the name. Dynamic-name callers should guard with hasRoute() first.
Thanks @rubenvanassche.
What's Changed
- Fix provider config file detection in install command by @TheoGibbons in #84
- Throw on missing route in generated
route(), addhasRoutepredicate by @rubenvanassche in #85 - Fix silent failure registering the service provider in typescript:install by @rubenvanassche in #89
- Keep routes that share a controller in the route generator by @rubenvanassche in #90
Full Changelog: 3.2.0...3.3.0