diff --git a/routes/api.php b/routes/api.php index 5dad31bdf..bc53e7f3a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -19,6 +19,7 @@ use Binaryk\LaravelRestify\Http\Controllers\RepositoryStoreController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryUpdateBulkController; use Binaryk\LaravelRestify\Http\Controllers\RepositoryUpdateController; +use Binaryk\LaravelRestify\Http\Controllers\RestifyJsSetupController; use Illuminate\Support\Facades\Route; // Global Search... @@ -29,6 +30,9 @@ Route::post('/profile', '\\'.ProfileUpdateController::class); Route::post('/profile/avatar', '\\'.ProfileAvatarController::class); +// RestifyJS +Route::get('/restifyjs/setup', '\\'.RestifyJsSetupController::class); + // Filters Route::get('/{repository}/filters', '\\'.RepositoryFilterController::class); diff --git a/src/Commands/stubs/user-repository.stub b/src/Commands/stubs/user-repository.stub index 778073359..9e88ae07a 100644 --- a/src/Commands/stubs/user-repository.stub +++ b/src/Commands/stubs/user-repository.stub @@ -4,6 +4,7 @@ namespace App\Restify; use Binaryk\LaravelRestify\Fields\Field; use Binaryk\LaravelRestify\Http\Requests\RestifyRequest; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class UserRepository extends Repository @@ -15,7 +16,7 @@ class UserRepository extends Repository return [ Field::make('name')->rules('required'), - Field::make('email')->storingRules('required', ''unique:users')->messages([ + Field::make('email')->storingRules('required', 'unique:users')->messages([ 'required' => 'This field is required.', ]), diff --git a/src/Eager/Related.php b/src/Eager/Related.php index b806fea09..7b713b463 100644 --- a/src/Eager/Related.php +++ b/src/Eager/Related.php @@ -5,8 +5,9 @@ use Binaryk\LaravelRestify\Fields\EagerField; use Binaryk\LaravelRestify\Repositories\Repository; use Binaryk\LaravelRestify\Traits\Make; +use JsonSerializable; -class Related +class Related implements JsonSerializable { use Make; @@ -34,4 +35,14 @@ public function resolveField(Repository $repository): EagerField { return $this->field->resolve($repository); } + + public function jsonSerialize() + { + return [ + 'relation' => $this->getRelation(), + 'field' => isset($this->field) + ? $this->field->jsonSerialize() + : null, + ]; + } } diff --git a/src/Http/Controllers/RestifyJsSetupController.php b/src/Http/Controllers/RestifyJsSetupController.php new file mode 100644 index 000000000..d1739bb4e --- /dev/null +++ b/src/Http/Controllers/RestifyJsSetupController.php @@ -0,0 +1,49 @@ +json([ + 'config' => $this->config(), + 'repositories' => $this->repositories($request), + ]); + } + + private function repositories(RestifyRequest $request): array + { + return collect(Restify::$repositories) + ->map(fn (string $repository) => app($repository)) + ->map(fn (Repository $repository) => $repository->restifyjsSerialize($request)) + ->all(); + } + + private function config(): array + { + return [ + 'domain' => $this->deleteFirstAndLastSlash(config('app.url')), + 'base' => $this->deleteFirstAndLastSlash(Restify::path()), + ]; + } + + private function deleteFirstAndLastSlash(string $domain): string + { + if (Str::startsWith($domain, '/')) { + $domain = Str::replaceFirst('/', '', $domain); + } + + if (Str::endsWith($domain, '/')) { + $domain = Str::replaceLast('/', '', $domain); + } + + return $domain; + } +} diff --git a/src/Repositories/Repository.php b/src/Repositories/Repository.php index dfefb80aa..e39143b15 100644 --- a/src/Repositories/Repository.php +++ b/src/Repositories/Repository.php @@ -2,6 +2,7 @@ namespace Binaryk\LaravelRestify\Repositories; +use Binaryk\LaravelRestify\Actions\Action; use Binaryk\LaravelRestify\Contracts\RestifySearchable; use Binaryk\LaravelRestify\Controllers\RestResponse; use Binaryk\LaravelRestify\Eager\Related; @@ -1074,4 +1075,18 @@ public function isEagerState(): bool { return $this->eagerState === true; } + + public function restifyjsSerialize(RestifyRequest $request): array + { + return [ + 'uriKey' => static::uriKey(), + 'related' => static::collectFilters('matches'), + 'sort' => static::collectFilters('sortables'), + 'match' => static::collectFilters('matches'), + 'searchables' => static::collectFilters('searchables'), + 'actions' => $this->resolveActions($request)->filter(fn (Action $action) => $action->isShownOnIndex( + $request, $this + ))->values(), + ]; + } } diff --git a/tests/Controllers/RestifyJsSetupControllerTest.php b/tests/Controllers/RestifyJsSetupControllerTest.php new file mode 100644 index 000000000..a7cca7495 --- /dev/null +++ b/tests/Controllers/RestifyJsSetupControllerTest.php @@ -0,0 +1,30 @@ +getJson('restifyjs/setup') + ->assertJsonStructure([ + 'config' => [ + 'domain', + 'base', + ], + 'repositories' => [ + [ + 'uriKey', + 'related', + 'sort', + 'match', + 'searchables', + 'actions', + ], + ], + ]) + ->assertOk(); + } +}