|
2 | 2 |
|
3 | 3 | namespace Spatie\TypeScriptTransformer\Laravel;
|
4 | 4 |
|
5 |
| -use Illuminate\Routing\Route; |
6 |
| -use Illuminate\Routing\Router; |
7 | 5 | use Spatie\TypeScriptTransformer\DefaultTypeProviders\DefaultTypesProvider;
|
8 |
| -use Spatie\TypeScriptTransformer\Laravel\Routes\InvokableRouteController; |
| 6 | +use Spatie\TypeScriptTransformer\Laravel\Actions\ResolveLaravelRoutControllerCollectionsAction; |
9 | 7 | use Spatie\TypeScriptTransformer\Laravel\Routes\RouteController;
|
10 | 8 | use Spatie\TypeScriptTransformer\Laravel\Routes\RouteControllerAction;
|
11 | 9 | use Spatie\TypeScriptTransformer\Laravel\Routes\RouteControllerCollection;
|
| 10 | +use Spatie\TypeScriptTransformer\Laravel\Routes\RouteInvokableController; |
12 | 11 | use Spatie\TypeScriptTransformer\Laravel\Routes\RouteParameter;
|
13 | 12 | use Spatie\TypeScriptTransformer\Laravel\Routes\RouteParameterCollection;
|
14 | 13 | use Spatie\TypeScriptTransformer\Transformed\Transformed;
|
|
20 | 19 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptGenericTypeVariable;
|
21 | 20 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptIdentifier;
|
22 | 21 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptIndexedAccess;
|
| 22 | +use Spatie\TypeScriptTransformer\TypeScript\TypeScriptLiteral; |
| 23 | +use Spatie\TypeScriptTransformer\TypeScript\TypeScriptNode; |
| 24 | +use Spatie\TypeScriptTransformer\TypeScript\TypeScriptNumber; |
23 | 25 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptObject;
|
24 | 26 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptOperator;
|
25 | 27 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptParameter;
|
26 | 28 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptProperty;
|
27 | 29 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptRaw;
|
28 | 30 | use Spatie\TypeScriptTransformer\TypeScript\TypeScriptString;
|
| 31 | +use Spatie\TypeScriptTransformer\TypeScript\TypeScriptUnion; |
29 | 32 |
|
30 | 33 | // @todo implement the method, probably using a RawTypeScriptNode, creating individual notes for each JS construct is probably a bit far fetched
|
31 | 34 | // @todo make sure we support __invoke routes without action
|
32 | 35 | // @todo add support for nullable parameters, these should be inferred
|
33 |
| -// @todo a syntax like route(['Controller', 'action'], {params}), route(['Controller', 'action'], param), route(InvokeableController) would be even cooler but maybe too complicated at the moment |
34 | 36 |
|
35 | 37 | /**
|
36 | 38 | * function route<
|
|
41 | 43 | *
|
42 | 44 | * }
|
43 | 45 | */
|
44 |
| -class RouterGenerator implements DefaultTypesProvider |
| 46 | +class LaravelActionDefaultTypesProvider implements DefaultTypesProvider |
45 | 47 | {
|
| 48 | + public function __construct( |
| 49 | + protected ResolveLaravelRoutControllerCollectionsAction $resolveLaravelRoutControllerCollectionsAction = new ResolveLaravelRoutControllerCollectionsAction() |
| 50 | + ) { |
| 51 | + } |
| 52 | + |
46 | 53 | public function provide(): array
|
47 | 54 | {
|
48 |
| - $controllers = $this->resolveRoutes(); |
| 55 | + $controllers = $this->resolveLaravelRoutControllerCollectionsAction->execute(); |
49 | 56 |
|
50 | 57 | $transformedRoutes = new Transformed(
|
51 | 58 | new TypeScriptAlias(
|
52 | 59 | new TypeScriptIdentifier('Routes'),
|
53 |
| - $controllers->toTypeScriptNode(), |
| 60 | + $this->parseRouteControllerCollection($controllers), |
54 | 61 | ),
|
55 | 62 | null,
|
56 | 63 | 'Routes',
|
@@ -131,60 +138,59 @@ public function provide(): array
|
131 | 138 | return [$transformedRoutes, $actionParam, $transformedAction];
|
132 | 139 | }
|
133 | 140 |
|
134 |
| - private function resolveRoutes(): RouteControllerCollection |
| 141 | + protected function parseRouteControllerCollection(RouteControllerCollection $collection): TypeScriptNode |
135 | 142 | {
|
136 |
| - /** @var array<string, RouteController> $controllers */ |
137 |
| - $controllers = []; |
138 |
| - |
139 |
| - foreach (app(Router::class)->getRoutes()->getRoutes() as $route) { |
140 |
| - $controllerClass = $route->getControllerClass(); |
141 |
| - |
142 |
| - if ($controllerClass === null) { |
143 |
| - continue; |
144 |
| - } |
145 |
| - |
146 |
| - $controllerClass = str_replace('\\', '.', $controllerClass); |
147 |
| - |
148 |
| - if ($route->getActionMethod() === $route->getControllerClass()) { |
149 |
| - $controllers[$controllerClass] = new InvokableRouteController( |
150 |
| - $this->resolveRouteParameters($route), |
151 |
| - $route->methods, |
152 |
| - $this->resolveUrl($route), |
153 |
| - ); |
154 |
| - |
155 |
| - continue; |
156 |
| - } |
157 |
| - |
158 |
| - if (! array_key_exists($controllerClass, $controllers)) { |
159 |
| - $controllers[$controllerClass] = new RouteController([]); |
160 |
| - } |
161 |
| - |
162 |
| - $controllers[$controllerClass]->actions[$route->getActionMethod()] = new RouteControllerAction( |
163 |
| - $route->getActionMethod(), |
164 |
| - $this->resolveRouteParameters($route), |
165 |
| - $route->methods, |
166 |
| - $this->resolveUrl($route), |
| 143 | + return new TypeScriptObject(collect($collection->controllers)->map(function (RouteController|RouteInvokableController $controller, string $name) { |
| 144 | + return new TypeScriptProperty( |
| 145 | + $name, |
| 146 | + $controller instanceof RouteInvokableController |
| 147 | + ? $this->parseInvokableController($controller) |
| 148 | + : $this->parseController($controller), |
167 | 149 | );
|
168 |
| - } |
| 150 | + })->all()); |
| 151 | + } |
169 | 152 |
|
170 |
| - return new RouteControllerCollection($controllers); |
| 153 | + protected function parseController(RouteController $controller): TypeScriptNode |
| 154 | + { |
| 155 | + return new TypeScriptObject([ |
| 156 | + new TypeScriptProperty('actions', new TypeScriptObject(collect($controller->actions)->map(function (RouteControllerAction $action, string $name) { |
| 157 | + return new TypeScriptProperty( |
| 158 | + $name, |
| 159 | + $this->parseControllerAction($action) |
| 160 | + ); |
| 161 | + })->all())), |
| 162 | + ]); |
171 | 163 | }
|
172 | 164 |
|
173 |
| - protected function resolveRouteParameters( |
174 |
| - Route $route |
175 |
| - ): RouteParameterCollection { |
176 |
| - preg_match_all('/\{(.*?)\}/', $route->getDomain().$route->uri, $matches); |
| 165 | + protected function parseControllerAction(RouteControllerAction $action): TypeScriptNode |
| 166 | + { |
| 167 | + return new TypeScriptObject([ |
| 168 | + new TypeScriptProperty('name', new TypeScriptLiteral($action->name)), |
| 169 | + new TypeScriptProperty('parameters', $this->parseRouteParameterCollection($action->parameters)), |
| 170 | + ]); |
| 171 | + } |
177 | 172 |
|
178 |
| - $parameters = array_map(fn (string $match) => new RouteParameter( |
179 |
| - trim($match, '?'), |
180 |
| - str_ends_with($match, '?') |
181 |
| - ), $matches[1]); |
| 173 | + protected function parseInvokableController(RouteInvokableController $controller): TypeScriptNode |
| 174 | + { |
| 175 | + return new TypeScriptObject([ |
| 176 | + new TypeScriptProperty('invokable', new TypeScriptRaw('true')), |
| 177 | + new TypeScriptProperty('parameters', $this->parseRouteParameterCollection($controller->parameters)), |
| 178 | + ]); |
| 179 | + } |
182 | 180 |
|
183 |
| - return new RouteParameterCollection($parameters); |
| 181 | + protected function parseRouteParameterCollection(RouteParameterCollection $collection): TypeScriptNode |
| 182 | + { |
| 183 | + return new TypeScriptObject(array_map(function (RouteParameter $parameter) { |
| 184 | + return $this->parseRouteParameter($parameter); |
| 185 | + }, $collection->parameters)); |
184 | 186 | }
|
185 | 187 |
|
186 |
| - protected function resolveUrl(Route $route): string |
| 188 | + protected function parseRouteParameter(RouteParameter $parameter): TypeScriptNode |
187 | 189 | {
|
188 |
| - return str_replace('?}', '}', $route->getDomain().$route->uri); |
| 190 | + return new TypeScriptProperty( |
| 191 | + $parameter->name, |
| 192 | + new TypeScriptUnion([new TypeScriptString(), new TypeScriptNumber()]), |
| 193 | + isOptional: $parameter->optional, |
| 194 | + ); |
189 | 195 | }
|
190 | 196 | }
|
0 commit comments