Skip to content

Commit 3d5ff27

Browse files
Updated routing
1 parent 608c6d7 commit 3d5ff27

12 files changed

+253
-63
lines changed

src/Laravel/Actions/ResolveLaravelRoutControllerCollectionsAction.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function execute(
3838
$this->resolveRouteParameters($route),
3939
$route->methods,
4040
$this->resolveUrl($route),
41+
$route->getName(),
4142
);
4243

4344
continue;
@@ -58,6 +59,7 @@ public function execute(
5859
$this->resolveRouteParameters($route),
5960
$route->methods,
6061
$this->resolveUrl($route),
62+
$route->getName(),
6163
);
6264

6365
continue;
@@ -68,10 +70,10 @@ public function execute(
6870
}
6971

7072
$controllers[$controllerClass]->actions[$route->getActionMethod()] = new RouteControllerAction(
71-
$route->getActionMethod(),
7273
$this->resolveRouteParameters($route),
7374
$route->methods,
7475
$this->resolveUrl($route),
76+
$route->getName(),
7577
);
7678
}
7779

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
3+
namespace Spatie\TypeScriptTransformer\Laravel;
4+
5+
use Spatie\TypeScriptTransformer\DefaultTypeProviders\DefaultTypesProvider;
6+
use Spatie\TypeScriptTransformer\Laravel\Actions\ResolveLaravelRoutControllerCollectionsAction;
7+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteClosure;
8+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteCollection;
9+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteController;
10+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteControllerAction;
11+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteInvokableController;
12+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteParameter;
13+
use Spatie\TypeScriptTransformer\Laravel\Routes\RouteParameterCollection;
14+
use Spatie\TypeScriptTransformer\References\CustomReference;
15+
use Spatie\TypeScriptTransformer\Transformed\Transformed;
16+
use Spatie\TypeScriptTransformer\TypeScript\TypeReference;
17+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptAlias;
18+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptFunctionDefinition;
19+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptGeneric;
20+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptGenericTypeVariable;
21+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptIdentifier;
22+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptIndexedAccess;
23+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptNode;
24+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptNumber;
25+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptObject;
26+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptOperator;
27+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptParameter;
28+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptProperty;
29+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptRaw;
30+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptString;
31+
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptUnion;
32+
33+
class LaravelNamedRouteDefaultTypesProvider implements DefaultTypesProvider
34+
{
35+
public function __construct(
36+
protected ResolveLaravelRoutControllerCollectionsAction $resolveLaravelRoutControllerCollectionsAction = new ResolveLaravelRoutControllerCollectionsAction(),
37+
protected array $location = [],
38+
) {
39+
}
40+
41+
public function provide(): array
42+
{
43+
$routeCollection = $this->resolveLaravelRoutControllerCollectionsAction->execute(
44+
null,
45+
includeRouteClosures: true,
46+
);
47+
48+
$transformedRoutes = new Transformed(
49+
new TypeScriptAlias(
50+
new TypeScriptIdentifier('NamedRouteList'),
51+
$this->parseRouteCollection($routeCollection),
52+
),
53+
$routesListReference = new CustomReference('laravel_named_routes', 'routes_list'),
54+
'NamedRouteList',
55+
true,
56+
$this->location,
57+
);
58+
59+
$jsonEncodedRoutes = $this->routeCollectionToJson($routeCollection);
60+
$baseUrl = url('/');
61+
62+
$transformedRoute = new Transformed(
63+
new TypeScriptFunctionDefinition(
64+
new TypeScriptGeneric(
65+
new TypeScriptIdentifier('route'),
66+
[
67+
new TypeScriptGenericTypeVariable(
68+
new TypeScriptIdentifier('TRoute'),
69+
extends: TypeScriptOperator::keyof(new TypeReference($routesListReference))
70+
),
71+
]
72+
),
73+
[
74+
new TypeScriptParameter('route', new TypeScriptIdentifier('TRoute')),
75+
new TypeScriptParameter(
76+
'parameters',
77+
new TypeScriptIndexedAccess(new TypeReference($routesListReference), [
78+
new TypeScriptIdentifier('TRoute'),
79+
new TypeScriptIdentifier('"parameters"'),
80+
]),
81+
isOptional: true),
82+
],
83+
new TypeScriptString(),
84+
new TypeScriptRaw(<<<TS
85+
let routes = JSON.parse('$jsonEncodedRoutes');
86+
let baseUrl = '$baseUrl';
87+
88+
let found = routes[route];
89+
90+
let url = baseUrl + '/' + found.url;
91+
92+
if(parameters) {
93+
for(let parameter in parameters) {
94+
url = url.replace('{' + parameter + '}', parameters[parameter]);
95+
}
96+
}
97+
98+
return url;
99+
TS
100+
)
101+
),
102+
new CustomReference('laravel_named_routes', 'route_function'),
103+
'route',
104+
true,
105+
$this->location,
106+
);
107+
108+
return [$transformedRoutes, $transformedRoute];
109+
}
110+
111+
protected function parseRouteCollection(RouteCollection $collection): TypeScriptNode
112+
{
113+
$mappingFunction = fn (RouteControllerAction|RouteInvokableController|RouteClosure $entity) => new TypeScriptProperty(
114+
$entity->name,
115+
new TypeScriptObject([
116+
new TypeScriptProperty(
117+
'parameters',
118+
$this->parseRouteParameterCollection($entity->parameters),
119+
),
120+
])
121+
);
122+
123+
$properties = collect(array_merge($collection->controllers, $collection->closures))
124+
->flatMap(function (RouteController|RouteInvokableController|RouteClosure $entity) use ($mappingFunction) {
125+
$singleRoute = $entity instanceof RouteInvokableController || $entity instanceof RouteClosure;
126+
127+
if ($singleRoute && $entity->name) {
128+
return [$mappingFunction($entity)];
129+
}
130+
131+
if ($entity instanceof RouteController) {
132+
return collect($entity->actions)
133+
->filter(fn (RouteControllerAction $action) => $action->name)
134+
->values()
135+
->map($mappingFunction);
136+
}
137+
138+
return [];
139+
})
140+
->all();
141+
142+
return new TypeScriptObject($properties);
143+
}
144+
145+
protected function parseRouteParameterCollection(RouteParameterCollection $collection): TypeScriptNode
146+
{
147+
return new TypeScriptObject(array_map(function (RouteParameter $parameter) {
148+
return $this->parseRouteParameter($parameter);
149+
}, $collection->parameters));
150+
}
151+
152+
protected function parseRouteParameter(RouteParameter $parameter): TypeScriptNode
153+
{
154+
return new TypeScriptProperty(
155+
$parameter->name,
156+
new TypeScriptUnion([new TypeScriptString(), new TypeScriptNumber()]),
157+
isOptional: $parameter->optional,
158+
);
159+
}
160+
161+
protected function routeCollectionToJson(RouteCollection $collection): string
162+
{
163+
$mappingFunction = fn (RouteInvokableController|RouteControllerAction|RouteClosure $entity) => [
164+
$entity->name => [
165+
'url' => $entity->url,
166+
'methods' => array_values($entity->methods),
167+
],
168+
];
169+
170+
$controllers = collect($collection->controllers)->mapWithKeys(function (RouteController|RouteInvokableController $controller) use ($mappingFunction) {
171+
if ($controller instanceof RouteInvokableController && $controller->name) {
172+
return $mappingFunction($controller);
173+
}
174+
175+
if ($controller instanceof RouteController) {
176+
return collect($controller->actions)
177+
->filter(fn (RouteControllerAction $action) => $action->name)
178+
->values()
179+
->mapWithKeys($mappingFunction);
180+
}
181+
182+
return [];
183+
});
184+
185+
$closures = collect($collection->closures)
186+
->filter(fn (RouteClosure $closure) => $closure->name)
187+
->values()
188+
->mapWithKeys(function (RouteClosure $closure) use ($mappingFunction) {
189+
return $mappingFunction($closure);
190+
});
191+
192+
return $controllers->merge($closures)->toJson(JSON_UNESCAPED_SLASHES);
193+
}
194+
}

src/Laravel/LaravelActionDefaultTypesProvider.php renamed to src/Laravel/LaravelRouteActionDefaultTypesProvider.php

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptString;
3333
use Spatie\TypeScriptTransformer\TypeScript\TypeScriptUnion;
3434

35-
class LaravelActionDefaultTypesProvider implements DefaultTypesProvider
35+
class LaravelRouteActionDefaultTypesProvider implements DefaultTypesProvider
3636
{
3737
public function __construct(
3838
protected ResolveLaravelRoutControllerCollectionsAction $resolveLaravelRoutControllerCollectionsAction = new ResolveLaravelRoutControllerCollectionsAction(),
@@ -43,18 +43,18 @@ public function __construct(
4343

4444
public function provide(): array
4545
{
46-
$controllers = $this->resolveLaravelRoutControllerCollectionsAction->execute(
46+
$routeCollection = $this->resolveLaravelRoutControllerCollectionsAction->execute(
4747
$this->defaultNamespace,
4848
includeRouteClosures: false,
4949
);
5050

5151
$transformedRoutes = new Transformed(
5252
new TypeScriptAlias(
53-
new TypeScriptIdentifier('RoutesList'),
54-
$this->parseRouteControllerCollection($controllers),
53+
new TypeScriptIdentifier('ActionRoutesList'),
54+
$this->parseRouteCollection($routeCollection),
5555
),
5656
$routesListReference = new CustomReference('laravel_route_actions', 'routes_list'),
57-
'RoutesList',
57+
'ActionRoutesList',
5858
true,
5959
$this->location,
6060
);
@@ -122,7 +122,7 @@ public function provide(): array
122122
$this->location,
123123
);
124124

125-
$jsonEncodedRoutes = json_encode($controllers->toJsObject(), flags: JSON_UNESCAPED_SLASHES);
125+
$jsonEncodedRoutes = $this->routeCollectionToJson($routeCollection);
126126
$baseUrl = url('/');
127127

128128
$transformedAction = new Transformed(
@@ -174,8 +174,8 @@ public function provide(): array
174174
let baseUrl = '$baseUrl';
175175
176176
let found = typeof action === 'string'
177-
? routes.controllers[action]
178-
: routes.controllers[action[0]]['actions'][action[1]];
177+
? routes[action]
178+
: routes[action[0]]['actions'][action[1]];
179179
180180
let url = baseUrl + '/' + found.url;
181181
@@ -188,7 +188,6 @@ public function provide(): array
188188
return url;
189189
TS
190190
)
191-
// new TypeScriptRaw("let routes = JSON.parse('".json_encode($controllers->toJsObject(), flags: JSON_UNESCAPED_SLASHES)."')")
192191
),
193192
new CustomReference('laravel_route_actions', 'action_function'),
194193
'action',
@@ -199,7 +198,7 @@ public function provide(): array
199198
return [$transformedRoutes, $actionController, $actionParameters, $transformedAction];
200199
}
201200

202-
protected function parseRouteControllerCollection(RouteCollection $collection): TypeScriptNode
201+
protected function parseRouteCollection(RouteCollection $collection): TypeScriptNode
203202
{
204203
return new TypeScriptObject(collect($collection->controllers)->map(function (RouteController|RouteInvokableController $controller, string $name) {
205204
return new TypeScriptProperty(
@@ -226,7 +225,6 @@ protected function parseController(RouteController $controller): TypeScriptNode
226225
protected function parseControllerAction(RouteControllerAction $action): TypeScriptNode
227226
{
228227
return new TypeScriptObject([
229-
new TypeScriptProperty('name', new TypeScriptLiteral($action->name)),
230228
new TypeScriptProperty('parameters', $this->parseRouteParameterCollection($action->parameters)),
231229
]);
232230
}
@@ -254,4 +252,22 @@ protected function parseRouteParameter(RouteParameter $parameter): TypeScriptNod
254252
isOptional: $parameter->optional,
255253
);
256254
}
255+
256+
protected function routeCollectionToJson(RouteCollection $collection): string
257+
{
258+
return collect($collection->controllers)
259+
->map(fn (RouteController|RouteInvokableController $controller) => $controller instanceof RouteInvokableController
260+
? [
261+
'url' => $controller->url,
262+
'methods' => array_values($controller->methods),
263+
]
264+
: [
265+
'actions' => collect($controller->actions)->map(fn (RouteControllerAction $action) => [
266+
'url' => $action->url,
267+
'methods' => array_values($action->methods),
268+
]),
269+
]
270+
)
271+
->toJson(JSON_UNESCAPED_SLASHES);
272+
}
257273
}

src/Laravel/Routes/RouteClosure.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,7 @@ public function __construct(
1111
public RouteParameterCollection $parameters,
1212
public array $methods,
1313
public string $url,
14+
public ?string $name,
1415
) {
1516
}
16-
17-
public function toJsObject(): array
18-
{
19-
return [
20-
'url' => $this->url,
21-
'methods' => array_values($this->methods),
22-
];
23-
}
2417
}

src/Laravel/Routes/RouteCollection.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,4 @@ public function __construct(
1313
public array $closures,
1414
) {
1515
}
16-
17-
public function toJsObject(): array
18-
{
19-
return [
20-
'controllers' => collect($this->controllers)->map(fn (RouteController|RouteInvokableController $controller) => $controller->toJsObject())->all(),
21-
'closures' => collect($this->closures)->map(fn (RouteClosure $closure) => $closure->toJsObject())->all(),
22-
];
23-
}
2416
}

src/Laravel/Routes/RouteController.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,4 @@ public function __construct(
1111
public array $actions,
1212
) {
1313
}
14-
15-
public function toJsObject(): array
16-
{
17-
return [
18-
'actions' => collect($this->actions)->map(fn (RouteControllerAction $action, string $name) => $action->toJsObject())->all(),
19-
];
20-
}
2114
}

src/Laravel/Routes/RouteControllerAction.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,10 @@ class RouteControllerAction implements RouterStructure
88
* @param array<string> $methods
99
*/
1010
public function __construct(
11-
public string $name,
1211
public RouteParameterCollection $parameters,
1312
public array $methods,
1413
public string $url,
14+
public ?string $name,
1515
) {
1616
}
17-
18-
public function toJsObject(): array
19-
{
20-
return [
21-
'url' => $this->url,
22-
'methods' => array_values($this->methods),
23-
];
24-
}
2517
}

src/Laravel/Routes/RouteInvokableController.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,7 @@ public function __construct(
1111
public RouteParameterCollection $parameters,
1212
public array $methods,
1313
public string $url,
14+
public ?string $name,
1415
) {
1516
}
16-
17-
public function toJsObject(): array
18-
{
19-
return [
20-
'url' => $this->url,
21-
'methods' => array_values($this->methods),
22-
];
23-
}
2417
}

0 commit comments

Comments
 (0)