mirror of
https://github.com/sp-tarkov/forge.git
synced 2025-02-12 12:10:41 -05:00
Scribe API Documentation
Installs Scribe for (mostly) automatic API documentation. Does a pretty good job and it's pretty painless to set-up. I'll have to configure it to work in the CI and to ensure that the static files are being pushed to production as they should be, but this is a good start.
This commit is contained in:
parent
d70a38bf08
commit
297937a2ea
@ -89,3 +89,6 @@ DB_HUB_COLLATION=utf8mb4_0900_ai_ci
|
|||||||
|
|
||||||
GITEA_DOMAIN=
|
GITEA_DOMAIN=
|
||||||
GITEA_TOKEN=
|
GITEA_TOKEN=
|
||||||
|
|
||||||
|
# API key for Scribe documentation.
|
||||||
|
SCRIBE_AUTH_KEY=
|
||||||
|
@ -42,3 +42,6 @@ SCOUT_DRIVER=collection
|
|||||||
MAIL_MAILER=log
|
MAIL_MAILER=log
|
||||||
MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com"
|
MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com"
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
# API key for Scribe documentation.
|
||||||
|
SCRIBE_AUTH_KEY=
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,3 +24,4 @@ Homestead.json
|
|||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
.scribe
|
||||||
|
@ -9,41 +9,77 @@ use App\Traits\ApiResponses;
|
|||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Knuckles\Scribe\Attributes\BodyParam;
|
||||||
|
use Knuckles\Scribe\Attributes\Response;
|
||||||
|
use Knuckles\Scribe\Attributes\ResponseField;
|
||||||
|
use Laravel\Sanctum\PersonalAccessToken;
|
||||||
|
|
||||||
class AuthController extends Controller
|
class AuthController extends Controller
|
||||||
{
|
{
|
||||||
use ApiResponses;
|
use ApiResponses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login
|
||||||
|
*
|
||||||
|
* Authenticates the user and returns a read-only API token. This API token can then be saved and used for future
|
||||||
|
* requests that require authentication. <aside class="warning">This method is made available for mod authors to
|
||||||
|
* incorporate into their mods so that users can easily authenticate using their own API token. For typical API use,
|
||||||
|
* you should log into the website, create an API token, and use that token for your API requests.</aside>
|
||||||
|
*
|
||||||
|
* @unauthenticated
|
||||||
|
*
|
||||||
|
* @group Authentication
|
||||||
|
*/
|
||||||
|
#[BodyParam('token_name', 'string', 'The name of the API token.', required: false, example: 'Dynamic API Token')]
|
||||||
|
#[Response(['message' => 'authenticated', 'data' => ['token' => 'YOUR_API_KEY'], 'status' => 200], status: 200, description: 'Authenticated successfully')]
|
||||||
|
#[Response(['message' => 'invalid credentials', 'status' => 401], status: 401, description: 'Invalid credentials')]
|
||||||
|
#[ResponseField('token', description: 'The newly created read-only API token to use for future authenticated requests.')]
|
||||||
public function login(LoginUserRequest $request): JsonResponse
|
public function login(LoginUserRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$request->validated($request->all());
|
$request->validated($request->all());
|
||||||
|
|
||||||
if (! Auth::attempt($request->only('email', 'password'))) {
|
if (! Auth::attempt($request->only('email', 'password'))) {
|
||||||
return $this->error(__('Invalid credentials'), 401);
|
return $this->error(__('invalid credentials'), 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::firstWhere('email', $request->email);
|
$user = User::firstWhere('email', $request->email);
|
||||||
$tokenName = $request->token_name ?? __('Dynamic API Token');
|
$tokenName = $request->token_name ?? __('Dynamic API Token');
|
||||||
|
|
||||||
return $this->success(__('Authenticated'), [
|
return $this->success(__('authenticated'), [
|
||||||
// Only allowing the 'read' scope to be dynamically created. Can revisit later when writes are possible.
|
// Only allowing the 'read' scope to be dynamically created. Can revisit later when writes are possible.
|
||||||
'token' => $user->createToken($tokenName, ['read'])->plainTextToken,
|
'token' => $user->createToken($tokenName, ['read'])->plainTextToken,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout
|
||||||
|
*
|
||||||
|
* Destroys the user's current API token, effectively logging them out.
|
||||||
|
*
|
||||||
|
* @group Authentication
|
||||||
|
*/
|
||||||
|
#[Response(['message' => 'success', 'status' => 200], status: 200, description: 'Token destroyed successfully')]
|
||||||
public function logout(Request $request): JsonResponse
|
public function logout(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var \Laravel\Sanctum\PersonalAccessToken $token */
|
/** @var PersonalAccessToken $token */
|
||||||
$token = $request->user()->currentAccessToken();
|
$token = $request->user()->currentAccessToken();
|
||||||
$token->delete();
|
$token->delete();
|
||||||
|
|
||||||
return $this->success(__('Revoked API token'));
|
return $this->success(__('success'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout All
|
||||||
|
*
|
||||||
|
* Destroys all the user's API tokens, effectively logging everyone out of the account.
|
||||||
|
*
|
||||||
|
* @group Authentication
|
||||||
|
*/
|
||||||
|
#[Response(['message' => 'success', 'status' => 200], status: 200, description: 'Tokens destroyed successfully')]
|
||||||
public function logoutAll(Request $request): JsonResponse
|
public function logoutAll(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$request->user()->tokens()->delete();
|
$request->user()->tokens()->delete();
|
||||||
|
|
||||||
return $this->success(__('Revoked all API tokens'));
|
return $this->success(__('success'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,43 +3,58 @@
|
|||||||
namespace App\Http\Controllers\Api\V0;
|
namespace App\Http\Controllers\Api\V0;
|
||||||
|
|
||||||
use App\Http\Filters\V1\ModFilter;
|
use App\Http\Filters\V1\ModFilter;
|
||||||
use App\Http\Requests\Api\V0\StoreModRequest;
|
|
||||||
use App\Http\Requests\Api\V0\UpdateModRequest;
|
|
||||||
use App\Http\Resources\Api\V0\ModResource;
|
use App\Http\Resources\Api\V0\ModResource;
|
||||||
use App\Models\Mod;
|
use App\Models\Mod;
|
||||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Knuckles\Scribe\Attributes\QueryParam;
|
||||||
|
use Knuckles\Scribe\Attributes\UrlParam;
|
||||||
|
|
||||||
class ModController extends ApiController
|
class ModController extends ApiController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Get Mods
|
||||||
|
*
|
||||||
|
* List, filter, and sort basic information about mods.
|
||||||
|
*
|
||||||
|
* @group Mods
|
||||||
*/
|
*/
|
||||||
|
#[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'users,versions,license')]
|
||||||
|
#[QueryParam('filter[id]', 'string', 'Filter by the `id`. Select multiple by separating the IDs with a comma.', required: false, example: '5,10,15')]
|
||||||
|
#[QueryParam('filter[hub_id]', 'string', 'Filter by the `hub_id` attribute. Select multiple by separating the IDs with a comma.', required: false, example: '20')]
|
||||||
|
#[QueryParam('filter[name]', 'string', 'Filter by the `name` attribute. Use `*` as the wildcard character.', required: false, example: '*SAIN*')]
|
||||||
|
#[QueryParam('filter[slug]', 'string', 'Filter by the `slug` attribute. Use `*` as the wildcard character.', required: false, example: '*raid-times')]
|
||||||
|
#[QueryParam('filter[teaser]', 'string', 'Filter by the `teaser` attribute. Use `*` as the wildcard character.', required: false, example: '*weighted*random*times*')]
|
||||||
|
#[QueryParam('filter[source_code_link]', 'string', 'Filter by the `source_code_link` attribute. Use `*` as the wildcard character.', required: false, example: '*https*.net*')]
|
||||||
|
#[QueryParam('filter[featured]', 'boolean', 'Filter by the `featured` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')]
|
||||||
|
#[QueryParam('filter[contains_ads]', 'boolean', 'Filter by the `contains_ads` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')]
|
||||||
|
#[QueryParam('filter[contains_ai_content]', 'boolean', 'Filter by the `contains_ai_content` attribute. All "truthy" or "falsy" values are supported.', required: false, example: 'true')]
|
||||||
|
#[QueryParam('filter[created_at]', 'string', 'Filter by the `created_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')]
|
||||||
|
#[QueryParam('filter[updated_at]', 'string', 'Filter by the `updated_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')]
|
||||||
|
#[QueryParam('filter[published_at]', 'string', 'Filter by the `published_at` attribute. Ranges are possible by seperating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')]
|
||||||
|
#[QueryParam('sort', 'string', 'Sort the results by a comma seperated list of attributes. The default sort direction is ASC, append the attribute name with a minus to sort DESC.', required: false, example: '-featured,name')]
|
||||||
public function index(ModFilter $filters): AnonymousResourceCollection
|
public function index(ModFilter $filters): AnonymousResourceCollection
|
||||||
{
|
{
|
||||||
return ModResource::collection(Mod::filter($filters)->paginate());
|
return ModResource::collection(Mod::filter($filters)->paginate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//public function store(StoreModRequest $request): void {}
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(StoreModRequest $request): void {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Get Mod
|
||||||
|
*
|
||||||
|
* Display more detailed information about a specific mod.
|
||||||
|
*
|
||||||
|
* @group Mods
|
||||||
*/
|
*/
|
||||||
|
#[UrlParam('id', 'integer', 'The ID of the mod.', required: true, example: 558)]
|
||||||
|
#[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'users,versions,license')]
|
||||||
public function show(Mod $mod): JsonResource
|
public function show(Mod $mod): JsonResource
|
||||||
{
|
{
|
||||||
return new ModResource($mod);
|
return new ModResource($mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//public function update(UpdateModRequest $request, Mod $mod): void {}
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(UpdateModRequest $request, Mod $mod): void {}
|
|
||||||
|
|
||||||
/**
|
//public function destroy(Mod $mod): void {}
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Mod $mod): void {}
|
|
||||||
}
|
}
|
||||||
|
@ -3,43 +3,48 @@
|
|||||||
namespace App\Http\Controllers\Api\V0;
|
namespace App\Http\Controllers\Api\V0;
|
||||||
|
|
||||||
use App\Http\Filters\V1\UserFilter;
|
use App\Http\Filters\V1\UserFilter;
|
||||||
use App\Http\Requests\Api\V0\StoreUserRequest;
|
|
||||||
use App\Http\Requests\Api\V0\UpdateUserRequest;
|
|
||||||
use App\Http\Resources\Api\V0\UserResource;
|
use App\Http\Resources\Api\V0\UserResource;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Knuckles\Scribe\Attributes\QueryParam;
|
||||||
|
|
||||||
class UsersController extends ApiController
|
class UsersController extends ApiController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Get Users
|
||||||
|
*
|
||||||
|
* List, filter, and sort basic information about users.
|
||||||
|
*
|
||||||
|
* @group Users
|
||||||
*/
|
*/
|
||||||
|
#[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'user_role')]
|
||||||
|
#[QueryParam('filter[id]', 'string', 'Filter by the `id`. Select multiple by separating the IDs with a comma.', required: false, example: '5,10,15')]
|
||||||
|
#[QueryParam('filter[name]', 'string', 'Filter by the `name` attribute. Use `*` as the wildcard character.', required: false, example: '*fringe')]
|
||||||
|
#[QueryParam('filter[created_at]', 'string', 'Filter by the `created_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')]
|
||||||
|
#[QueryParam('filter[updated_at]', 'string', 'Filter by the `updated_at` attribute. Ranges are possible by separating the dates with a comma.', required: false, example: '2023-12-31,2024-12-31')]
|
||||||
|
#[QueryParam('sort', 'string', 'Sort the results by a comma seperated list of attributes. The default sort direction is ASC, append the attribute name with a minus to sort DESC.', required: false, example: 'created_at,-name')]
|
||||||
public function index(UserFilter $filters): AnonymousResourceCollection
|
public function index(UserFilter $filters): AnonymousResourceCollection
|
||||||
{
|
{
|
||||||
return UserResource::collection(User::filter($filters)->paginate());
|
return UserResource::collection(User::filter($filters)->paginate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//public function store(StoreUserRequest $request): void {}
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(StoreUserRequest $request): void {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Get User
|
||||||
|
*
|
||||||
|
* Display more detailed information about a specific user.
|
||||||
|
*
|
||||||
|
* @group Users
|
||||||
*/
|
*/
|
||||||
|
#[QueryParam('include', 'string', 'The relationships to include within the `includes` key. By default no relationships are automatically included.', required: false, example: 'user_role')]
|
||||||
public function show(User $user): JsonResource
|
public function show(User $user): JsonResource
|
||||||
{
|
{
|
||||||
return new UserResource($user);
|
return new UserResource($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//public function update(UpdateUserRequest $request, User $user): void {}
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(UpdateUserRequest $request, User $user): void {}
|
|
||||||
|
|
||||||
/**
|
//public function destroy(User $user): void {}
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(User $user): void {}
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ trait ApiResponses
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Return a success JSON response.
|
* Return a success JSON response.
|
||||||
*
|
|
||||||
* @param array<mixed> $data
|
|
||||||
*/
|
*/
|
||||||
protected function success(string $message, ?array $data = []): JsonResponse
|
protected function success(string $message, ?array $data = []): JsonResponse
|
||||||
{
|
{
|
||||||
@ -18,15 +16,17 @@ trait ApiResponses
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The base response.
|
* The base response.
|
||||||
*
|
|
||||||
* @param array<mixed> $data
|
|
||||||
*/
|
*/
|
||||||
private function baseResponse(?string $message = '', ?array $data = [], ?int $code = 200): JsonResponse
|
private function baseResponse(?string $message = '', ?array $data = [], ?int $code = 200): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([
|
$response = [];
|
||||||
'message' => $message,
|
$response['message'] = $message;
|
||||||
'data' => $data,
|
if ($data) {
|
||||||
], $code);
|
$response['data'] = $data;
|
||||||
|
}
|
||||||
|
$response['status'] = $code;
|
||||||
|
|
||||||
|
return response()->json($response, $code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"barryvdh/laravel-debugbar": "^3.13",
|
"barryvdh/laravel-debugbar": "^3.13",
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
"knuckleswtf/scribe": "^4.37",
|
||||||
"larastan/larastan": "^2.9",
|
"larastan/larastan": "^2.9",
|
||||||
"laravel/pint": "^1.16",
|
"laravel/pint": "^1.16",
|
||||||
"laravel/sail": "^1.29",
|
"laravel/sail": "^1.29",
|
||||||
|
445
composer.lock
generated
445
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "aef706ee9aa7b671ca81c5ced4a7bfb7",
|
"content-hash": "a687bfe8867c5e74bf6a974aaa969f62",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@ -9510,6 +9510,56 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-20T07:24:02+00:00"
|
"time": "2024-02-20T07:24:02+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "erusev/parsedown",
|
||||||
|
"version": "1.7.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/erusev/parsedown.git",
|
||||||
|
"reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
|
||||||
|
"reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Parsedown": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Emanuil Rusev",
|
||||||
|
"email": "hello@erusev.com",
|
||||||
|
"homepage": "http://erusev.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser for Markdown.",
|
||||||
|
"homepage": "http://parsedown.org",
|
||||||
|
"keywords": [
|
||||||
|
"markdown",
|
||||||
|
"parser"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/erusev/parsedown/issues",
|
||||||
|
"source": "https://github.com/erusev/parsedown/tree/1.7.x"
|
||||||
|
},
|
||||||
|
"time": "2019-12-30T22:54:17+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "fakerphp/faker",
|
"name": "fakerphp/faker",
|
||||||
"version": "v1.23.1",
|
"version": "v1.23.1",
|
||||||
@ -9815,6 +9865,101 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-03-08T09:58:59+00:00"
|
"time": "2024-03-08T09:58:59+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "knuckleswtf/scribe",
|
||||||
|
"version": "4.37.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/knuckleswtf/scribe.git",
|
||||||
|
"reference": "6318f3f68cbf09328e5cb6843ce1739e529ef1ac"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/knuckleswtf/scribe/zipball/6318f3f68cbf09328e5cb6843ce1739e529ef1ac",
|
||||||
|
"reference": "6318f3f68cbf09328e5cb6843ce1739e529ef1ac",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"erusev/parsedown": "1.7.4",
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-pdo": "*",
|
||||||
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
"illuminate/console": "^8.0|^9.0|^10.0|^11.0",
|
||||||
|
"illuminate/routing": "^8.0|^9.0|^10.0|^11.0",
|
||||||
|
"illuminate/support": "^8.0|^9.0|^10.0|^11.0",
|
||||||
|
"league/flysystem": "^1.1.4|^2.1.1|^3.0",
|
||||||
|
"mpociot/reflection-docblock": "^1.0.1",
|
||||||
|
"nikic/php-parser": "^5.0",
|
||||||
|
"nunomaduro/collision": "^5.10|^6.0|^7.0|^8.0",
|
||||||
|
"php": ">=8.0",
|
||||||
|
"ramsey/uuid": "^4.2.2",
|
||||||
|
"shalvah/clara": "^3.1.0",
|
||||||
|
"shalvah/upgrader": ">=0.6.0",
|
||||||
|
"spatie/data-transfer-object": "^2.6|^3.0",
|
||||||
|
"symfony/var-exporter": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/yaml": "^5.4|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"mpociot/laravel-apidoc-generator": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"brianium/paratest": "^6.0",
|
||||||
|
"dms/phpunit-arraysubset-asserts": "^0.4",
|
||||||
|
"laravel/legacy-factories": "^1.3.0",
|
||||||
|
"laravel/lumen-framework": "^8.0|^9.0|^10.0",
|
||||||
|
"league/fractal": "^0.20",
|
||||||
|
"nikic/fast-route": "^1.3",
|
||||||
|
"orchestra/testbench": "^6.0|^7.0|^8.0",
|
||||||
|
"pestphp/pest": "^1.21",
|
||||||
|
"phpstan/phpstan": "^1.0",
|
||||||
|
"phpunit/phpunit": "^9.0|^10.0",
|
||||||
|
"symfony/css-selector": "^5.4|^6.0",
|
||||||
|
"symfony/dom-crawler": "^5.4|^6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Knuckles\\Scribe\\ScribeServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Knuckles\\Camel\\": "camel/",
|
||||||
|
"Knuckles\\Scribe\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Shalvah"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Generate API documentation for humans from your Laravel codebase.✍",
|
||||||
|
"homepage": "http://github.com/knuckleswtf/scribe",
|
||||||
|
"keywords": [
|
||||||
|
"api",
|
||||||
|
"dingo",
|
||||||
|
"documentation",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/knuckleswtf/scribe/issues",
|
||||||
|
"source": "https://github.com/knuckleswtf/scribe/tree/4.37.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://patreon.com/shalvah",
|
||||||
|
"type": "patreon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-08-30T12:15:51+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "larastan/larastan",
|
"name": "larastan/larastan",
|
||||||
"version": "v2.9.8",
|
"version": "v2.9.8",
|
||||||
@ -10197,6 +10342,59 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-05-16T03:13:13+00:00"
|
"time": "2024-05-16T03:13:13+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mpociot/reflection-docblock",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mpociot/reflection-docblock.git",
|
||||||
|
"reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mpociot/reflection-docblock/zipball/c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587",
|
||||||
|
"reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~4.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"dflydev/markdown": "~1.0",
|
||||||
|
"erusev/parsedown": "~1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Mpociot": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Mike van Riel",
|
||||||
|
"email": "mike.vanriel@naenius.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mpociot/reflection-docblock/issues",
|
||||||
|
"source": "https://github.com/mpociot/reflection-docblock/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2016-06-20T20:53:12+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "myclabs/deep-copy",
|
"name": "myclabs/deep-copy",
|
||||||
"version": "1.12.0",
|
"version": "1.12.0",
|
||||||
@ -12426,6 +12624,111 @@
|
|||||||
],
|
],
|
||||||
"time": "2023-02-07T11:34:05+00:00"
|
"time": "2023-02-07T11:34:05+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "shalvah/clara",
|
||||||
|
"version": "3.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shalvah/clara.git",
|
||||||
|
"reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shalvah/clara/zipball/cdbb5737cbdd101756d97dd2279a979a1af7710b",
|
||||||
|
"reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.4",
|
||||||
|
"symfony/console": "^4.0|^5.0|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"eloquent/phony-phpunit": "^7.0",
|
||||||
|
"phpunit/phpunit": "^9.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"helpers.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Shalvah\\Clara\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "🔊 Simple, pretty, testable console output for CLI apps.",
|
||||||
|
"keywords": [
|
||||||
|
"cli",
|
||||||
|
"log",
|
||||||
|
"logging"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shalvah/clara/issues",
|
||||||
|
"source": "https://github.com/shalvah/clara/tree/3.2.0"
|
||||||
|
},
|
||||||
|
"time": "2024-02-27T20:30:59+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shalvah/upgrader",
|
||||||
|
"version": "0.6.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shalvah/upgrader.git",
|
||||||
|
"reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shalvah/upgrader/zipball/d95ed17fe9f5e1ee7d47ad835595f1af080a867f",
|
||||||
|
"reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/support": ">=8.0",
|
||||||
|
"nikic/php-parser": "^5.0",
|
||||||
|
"php": ">=8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"dms/phpunit-arraysubset-asserts": "^0.2.0",
|
||||||
|
"pestphp/pest": "^1.21",
|
||||||
|
"phpstan/phpstan": "^1.0",
|
||||||
|
"spatie/ray": "^1.33"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Shalvah\\Upgrader\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Shalvah",
|
||||||
|
"email": "hello@shalvah.me"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Create automatic upgrades for your package.",
|
||||||
|
"homepage": "http://github.com/shalvah/upgrader",
|
||||||
|
"keywords": [
|
||||||
|
"upgrade"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shalvah/upgrader/issues",
|
||||||
|
"source": "https://github.com/shalvah/upgrader/tree/0.6.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://patreon.com/shalvah",
|
||||||
|
"type": "patreon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-02-20T11:51:46+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/backtrace",
|
"name": "spatie/backtrace",
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
@ -12489,6 +12792,70 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-07-22T08:21:24+00:00"
|
"time": "2024-07-22T08:21:24+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/data-transfer-object",
|
||||||
|
"version": "3.9.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/data-transfer-object.git",
|
||||||
|
"reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/data-transfer-object/zipball/1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8",
|
||||||
|
"reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"illuminate/collections": "^8.36",
|
||||||
|
"jetbrains/phpstorm-attributes": "^1.0",
|
||||||
|
"larapack/dd": "^1.1",
|
||||||
|
"phpunit/phpunit": "^9.5.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\DataTransferObject\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Brent Roose",
|
||||||
|
"email": "brent@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Data transfer objects with batteries included",
|
||||||
|
"homepage": "https://github.com/spatie/data-transfer-object",
|
||||||
|
"keywords": [
|
||||||
|
"data-transfer-object",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/data-transfer-object/issues",
|
||||||
|
"source": "https://github.com/spatie/data-transfer-object/tree/3.9.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"abandoned": "spatie/laravel-data",
|
||||||
|
"time": "2022-09-16T13:34:38+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/error-solutions",
|
"name": "spatie/error-solutions",
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@ -12806,6 +13173,82 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-06-12T15:01:18+00:00"
|
"time": "2024-06-12T15:01:18+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/var-exporter",
|
||||||
|
"version": "v7.1.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/var-exporter.git",
|
||||||
|
"reference": "b80a669a2264609f07f1667f891dbfca25eba44c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/b80a669a2264609f07f1667f891dbfca25eba44c",
|
||||||
|
"reference": "b80a669a2264609f07f1667f891dbfca25eba44c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/property-access": "^6.4|^7.0",
|
||||||
|
"symfony/serializer": "^6.4|^7.0",
|
||||||
|
"symfony/var-dumper": "^6.4|^7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\VarExporter\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Allows exporting any serializable PHP data structure to plain PHP code",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"clone",
|
||||||
|
"construct",
|
||||||
|
"export",
|
||||||
|
"hydrate",
|
||||||
|
"instantiate",
|
||||||
|
"lazy-loading",
|
||||||
|
"proxy",
|
||||||
|
"serialize"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/var-exporter/tree/v7.1.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-06-28T08:00:31+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v7.1.4",
|
"version": "v7.1.4",
|
||||||
|
269
config/scribe.php
Normal file
269
config/scribe.php
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Knuckles\Scribe\Extracting\Strategies;
|
||||||
|
|
||||||
|
return [
|
||||||
|
// The HTML <title> for the generated documentation. If this is empty, Scribe will infer it from config('app.name').
|
||||||
|
'title' => 'The Forge API Documentation',
|
||||||
|
|
||||||
|
// A short description of your API. Will be included in the docs webpage, Postman collection and OpenAPI spec.
|
||||||
|
'description' => '',
|
||||||
|
|
||||||
|
// The base URL displayed in the docs. If this is empty, Scribe will use the value of config('app.url') at generation time.
|
||||||
|
// If you're using `laravel` type, you can set this to a dynamic string, like '{{ config("app.tenant_url") }}' to get a dynamic base URL.
|
||||||
|
'base_url' => null,
|
||||||
|
|
||||||
|
'routes' => [
|
||||||
|
[
|
||||||
|
// Routes that match these conditions will be included in the docs
|
||||||
|
'match' => [
|
||||||
|
// Match only routes whose paths match this pattern (use * as a wildcard to match any characters). Example: 'users/*'.
|
||||||
|
'prefixes' => ['api/*'],
|
||||||
|
|
||||||
|
// Match only routes whose domains match this pattern (use * as a wildcard to match any characters). Example: 'api.*'.
|
||||||
|
'domains' => ['*'],
|
||||||
|
|
||||||
|
// [Dingo router only] Match only routes registered under this version. Wildcards are NOT supported.
|
||||||
|
'versions' => ['v0'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// Include these routes even if they did not match the rules above.
|
||||||
|
'include' => [
|
||||||
|
// 'users.index', 'POST /new', '/auth/*'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Exclude these routes even if they matched the rules above.
|
||||||
|
'exclude' => [
|
||||||
|
// 'GET /health', 'admin.*'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// The type of documentation output to generate.
|
||||||
|
// - "static" will generate a static HTMl page in the /public/docs folder,
|
||||||
|
// - "laravel" will generate the documentation as a Blade view, so you can add routing and authentication.
|
||||||
|
// - "external_static" and "external_laravel" do the same as above, but generate a basic template,
|
||||||
|
// passing the OpenAPI spec as a URL, allowing you to easily use the docs with an external generator
|
||||||
|
'type' => 'static',
|
||||||
|
|
||||||
|
// See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options
|
||||||
|
'theme' => 'default',
|
||||||
|
|
||||||
|
'static' => [
|
||||||
|
// HTML documentation, assets and Postman collection will be generated to this folder.
|
||||||
|
// Source Markdown will still be in resources/docs.
|
||||||
|
'output_path' => 'public/docs',
|
||||||
|
],
|
||||||
|
|
||||||
|
'laravel' => [
|
||||||
|
// Whether to automatically create a docs endpoint for you to view your generated docs.
|
||||||
|
// If this is false, you can still set up routing manually.
|
||||||
|
'add_routes' => true,
|
||||||
|
|
||||||
|
// URL path to use for the docs endpoint (if `add_routes` is true).
|
||||||
|
// By default, `/docs` opens the HTML page, `/docs.postman` opens the Postman collection, and `/docs.openapi` the OpenAPI spec.
|
||||||
|
'docs_url' => '/docs',
|
||||||
|
|
||||||
|
// Directory within `public` in which to store CSS and JS assets.
|
||||||
|
// By default, assets are stored in `public/vendor/scribe`.
|
||||||
|
// If set, assets will be stored in `public/{{assets_directory}}`
|
||||||
|
'assets_directory' => null,
|
||||||
|
|
||||||
|
// Middleware to attach to the docs endpoint (if `add_routes` is true).
|
||||||
|
'middleware' => [],
|
||||||
|
],
|
||||||
|
|
||||||
|
'external' => [
|
||||||
|
'html_attributes' => [],
|
||||||
|
],
|
||||||
|
|
||||||
|
'try_it_out' => [
|
||||||
|
// Add a Try It Out button to your endpoints so consumers can test endpoints right from their browser.
|
||||||
|
// Don't forget to enable CORS headers for your endpoints.
|
||||||
|
'enabled' => true,
|
||||||
|
|
||||||
|
// The base URL for the API tester to use (for example, you can set this to your staging URL).
|
||||||
|
// Leave as null to use the current app URL when generating (config("app.url")).
|
||||||
|
'base_url' => null,
|
||||||
|
|
||||||
|
// [Laravel Sanctum] Fetch a CSRF token before each request, and add it as an X-XSRF-TOKEN header.
|
||||||
|
'use_csrf' => false,
|
||||||
|
|
||||||
|
// The URL to fetch the CSRF token from (if `use_csrf` is true).
|
||||||
|
'csrf_url' => '/sanctum/csrf-cookie',
|
||||||
|
],
|
||||||
|
|
||||||
|
// How is your API authenticated? This information will be used in the displayed docs, generated examples and response calls.
|
||||||
|
'auth' => [
|
||||||
|
// Set this to true if ANY endpoints in your API use authentication.
|
||||||
|
'enabled' => true,
|
||||||
|
|
||||||
|
// Set this to true if your API should be authenticated by default. If so, you must also set `enabled` (above) to true.
|
||||||
|
// You can then use @unauthenticated or @authenticated on individual endpoints to change their status from the default.
|
||||||
|
'default' => true,
|
||||||
|
|
||||||
|
// Where is the auth value meant to be sent in a request?
|
||||||
|
// Options: query, body, basic, bearer, header (for custom header)
|
||||||
|
'in' => 'bearer',
|
||||||
|
|
||||||
|
// The name of the auth parameter (eg token, key, apiKey) or header (eg Authorization, Api-Key).
|
||||||
|
'name' => 'Authorization',
|
||||||
|
|
||||||
|
// The value of the parameter to be used by Scribe to authenticate response calls.
|
||||||
|
// This will NOT be included in the generated documentation. If empty, Scribe will use a random value.
|
||||||
|
'use_value' => env('SCRIBE_AUTH_KEY'),
|
||||||
|
|
||||||
|
// Placeholder your users will see for the auth parameter in the example requests.
|
||||||
|
// Set this to null if you want Scribe to use a random value as placeholder instead.
|
||||||
|
'placeholder' => 'YOUR_API_KEY',
|
||||||
|
|
||||||
|
// Any extra authentication-related info for your users. Markdown and HTML are supported.
|
||||||
|
'extra_info' => 'You can generate your own API token by logging into The Forge, clicking your profile picture, and clicking <b>API Tokens</b>.',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Text to place in the "Introduction" section, right after the `description`. Markdown and HTML are supported.
|
||||||
|
'intro_text' => <<<'INTRO'
|
||||||
|
This documentation aims to provide all the information you need to work with our API.
|
||||||
|
|
||||||
|
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
|
||||||
|
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>
|
||||||
|
INTRO
|
||||||
|
,
|
||||||
|
|
||||||
|
// Example requests for each endpoint will be shown in each of these languages.
|
||||||
|
// Supported options are: bash, javascript, php, python
|
||||||
|
// To add a language of your own, see https://scribe.knuckles.wtf/laravel/advanced/example-requests
|
||||||
|
'example_languages' => [
|
||||||
|
'javascript',
|
||||||
|
'php',
|
||||||
|
'python',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Generate a Postman collection (v2.1.0) in addition to HTML docs.
|
||||||
|
// For 'static' docs, the collection will be generated to public/docs/collection.json.
|
||||||
|
// For 'laravel' docs, it will be generated to storage/app/scribe/collection.json.
|
||||||
|
// Setting `laravel.add_routes` to true (above) will also add a route for the collection.
|
||||||
|
'postman' => [
|
||||||
|
'enabled' => true,
|
||||||
|
'overrides' => [
|
||||||
|
// 'info.version' => '2.0.0',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// Generate an OpenAPI spec (v3.0.1) in addition to docs webpage.
|
||||||
|
// For 'static' docs, the collection will be generated to public/docs/openapi.yaml.
|
||||||
|
// For 'laravel' docs, it will be generated to storage/app/scribe/openapi.yaml.
|
||||||
|
// Setting `laravel.add_routes` to true (above) will also add a route for the spec.
|
||||||
|
'openapi' => [
|
||||||
|
'enabled' => true,
|
||||||
|
'overrides' => [
|
||||||
|
// 'info.version' => '2.0.0',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'groups' => [
|
||||||
|
// Endpoints which don't have a @group will be placed in this default group.
|
||||||
|
'default' => 'Endpoints',
|
||||||
|
|
||||||
|
// By default, Scribe will sort groups alphabetically, and endpoints in the order their routes are defined.
|
||||||
|
// You can override this by listing the groups, subgroups and endpoints here in the order you want them.
|
||||||
|
// See https://scribe.knuckles.wtf/blog/laravel-v4#easier-sorting and https://scribe.knuckles.wtf/laravel/reference/config#order for details
|
||||||
|
'order' => [],
|
||||||
|
],
|
||||||
|
|
||||||
|
// Custom logo path. This will be used as the value of the src attribute for the <img> tag,
|
||||||
|
// so make sure it points to an accessible URL or path. Set to false to not use a logo.
|
||||||
|
// For example, if your logo is in public/img:
|
||||||
|
// - 'logo' => '../img/logo.png' // for `static` type (output folder is public/docs)
|
||||||
|
// - 'logo' => 'img/logo.png' // for `laravel` type
|
||||||
|
'logo' => false,
|
||||||
|
|
||||||
|
// Customize the "Last updated" value displayed in the docs by specifying tokens and formats.
|
||||||
|
// Examples:
|
||||||
|
// - {date:F j Y} => March 28, 2022
|
||||||
|
// - {git:short} => Short hash of the last Git commit
|
||||||
|
// Available tokens are `{date:<format>}` and `{git:<format>}`.
|
||||||
|
// The format you pass to `date` will be passed to PHP's `date()` function.
|
||||||
|
// The format you pass to `git` can be either "short" or "long".
|
||||||
|
'last_updated' => 'Last updated: {date:F j, Y}',
|
||||||
|
|
||||||
|
'examples' => [
|
||||||
|
// Set this to any number (eg. 1234) to generate the same example values for parameters on each run,
|
||||||
|
'faker_seed' => null,
|
||||||
|
|
||||||
|
// With API resources and transformers, Scribe tries to generate example models to use in your API responses.
|
||||||
|
// By default, Scribe will try the model's factory, and if that fails, try fetching the first from the database.
|
||||||
|
// You can reorder or remove strategies here.
|
||||||
|
'models_source' => ['factoryCreate', 'factoryMake', 'databaseFirst'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// The strategies Scribe will use to extract information about your routes at each stage.
|
||||||
|
// If you create or install a custom strategy, add it here.
|
||||||
|
'strategies' => [
|
||||||
|
'metadata' => [
|
||||||
|
Strategies\Metadata\GetFromDocBlocks::class,
|
||||||
|
Strategies\Metadata\GetFromMetadataAttributes::class,
|
||||||
|
],
|
||||||
|
'urlParameters' => [
|
||||||
|
Strategies\UrlParameters\GetFromLaravelAPI::class,
|
||||||
|
Strategies\UrlParameters\GetFromUrlParamAttribute::class,
|
||||||
|
Strategies\UrlParameters\GetFromUrlParamTag::class,
|
||||||
|
],
|
||||||
|
'queryParameters' => [
|
||||||
|
Strategies\QueryParameters\GetFromFormRequest::class,
|
||||||
|
Strategies\QueryParameters\GetFromInlineValidator::class,
|
||||||
|
Strategies\QueryParameters\GetFromQueryParamAttribute::class,
|
||||||
|
Strategies\QueryParameters\GetFromQueryParamTag::class,
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
Strategies\Headers\GetFromHeaderAttribute::class,
|
||||||
|
Strategies\Headers\GetFromHeaderTag::class,
|
||||||
|
[
|
||||||
|
'override',
|
||||||
|
[
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'bodyParameters' => [
|
||||||
|
Strategies\BodyParameters\GetFromFormRequest::class,
|
||||||
|
Strategies\BodyParameters\GetFromInlineValidator::class,
|
||||||
|
Strategies\BodyParameters\GetFromBodyParamAttribute::class,
|
||||||
|
Strategies\BodyParameters\GetFromBodyParamTag::class,
|
||||||
|
],
|
||||||
|
'responses' => [
|
||||||
|
Strategies\Responses\UseResponseAttributes::class,
|
||||||
|
Strategies\Responses\UseTransformerTags::class,
|
||||||
|
Strategies\Responses\UseApiResourceTags::class,
|
||||||
|
Strategies\Responses\UseResponseTag::class,
|
||||||
|
Strategies\Responses\UseResponseFileTag::class,
|
||||||
|
[
|
||||||
|
Strategies\Responses\ResponseCalls::class,
|
||||||
|
[
|
||||||
|
'only' => ['GET *'],
|
||||||
|
// Disable debug mode when generating response calls to avoid error stack traces in responses
|
||||||
|
'config' => [
|
||||||
|
'app.debug' => false,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'responseFields' => [
|
||||||
|
Strategies\ResponseFields\GetFromResponseFieldAttribute::class,
|
||||||
|
Strategies\ResponseFields\GetFromResponseFieldTag::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// For response calls, API resource responses and transformer responses,
|
||||||
|
// Scribe will try to start database transactions, so no changes are persisted to your database.
|
||||||
|
// Tell Scribe which connections should be transacted here. If you only use one db connection, you can leave this as is.
|
||||||
|
'database_connections_to_transact' => [config('database.default')],
|
||||||
|
|
||||||
|
'fractal' => [
|
||||||
|
// If you are using a custom serializer with league/fractal, you can specify it here.
|
||||||
|
'serializer' => null,
|
||||||
|
],
|
||||||
|
|
||||||
|
'routeMatcher' => \Knuckles\Scribe\Matching\RouteMatcher::class,
|
||||||
|
];
|
486
public/docs/collection.json
Normal file
486
public/docs/collection.json
Normal file
File diff suppressed because one or more lines are too long
393
public/docs/css/theme-default.print.css
Normal file
393
public/docs/css/theme-default.print.css
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
/* Copied from https://github.com/slatedocs/slate/blob/c4b4c0b8f83e891ca9fab6bbe9a1a88d5fe41292/stylesheets/print.css and unminified */
|
||||||
|
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
main,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
section,
|
||||||
|
summary {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
audio,
|
||||||
|
canvas,
|
||||||
|
progress,
|
||||||
|
video {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: baseline
|
||||||
|
}
|
||||||
|
|
||||||
|
audio:not([controls]) {
|
||||||
|
display: none;
|
||||||
|
height: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden],
|
||||||
|
template {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active,
|
||||||
|
a:hover {
|
||||||
|
outline: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: 1px dotted
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
|
||||||
|
dfn {
|
||||||
|
font-style: italic
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background: #ff0;
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
svg:not(:root) {
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 1em 40px
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
pre,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
overflow: visible
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
html input[type="button"],
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
button[disabled],
|
||||||
|
html input[disabled] {
|
||||||
|
cursor: default
|
||||||
|
}
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
input::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
line-height: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="search"] {
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
box-sizing: content-box
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="search"]::-webkit-search-cancel-button,
|
||||||
|
input[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 0.35em 0.625em 0.75em
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
border: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
optgroup {
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h1,
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4,
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h1,
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4 {
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
|
||||||
|
.content pre,
|
||||||
|
.content code {
|
||||||
|
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
.content pre,
|
||||||
|
.content code {
|
||||||
|
word-break: break-all;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
hyphens: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'slate';
|
||||||
|
src: url(../fonts/slate.eot?-syv14m);
|
||||||
|
src: url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"), url(../fonts/slate.woff2?-syv14m) format("woff2"), url(../fonts/slate.woff?-syv14m) format("woff"), url(../fonts/slate.ttf?-syv14m) format("truetype"), url(../fonts/slate.svg?-syv14m#slate) format("svg");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside.warning:before,
|
||||||
|
.content aside.notice:before,
|
||||||
|
.content aside.success:before {
|
||||||
|
font-family: 'slate';
|
||||||
|
speak: none;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
line-height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside.warning:before {
|
||||||
|
content: "\e600"
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside.notice:before {
|
||||||
|
content: "\e602"
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside.success:before {
|
||||||
|
content: "\e606"
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocify,
|
||||||
|
.toc-footer,
|
||||||
|
.lang-selector,
|
||||||
|
.search,
|
||||||
|
#nav-button {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocify-wrapper>img {
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.content pre,
|
||||||
|
.content code {
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
.content pre code {
|
||||||
|
border: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.content pre {
|
||||||
|
padding: 1.3em
|
||||||
|
}
|
||||||
|
|
||||||
|
.content code {
|
||||||
|
padding: 0.2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.content table {
|
||||||
|
border: 1px solid #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.content table tr {
|
||||||
|
border-bottom: 1px solid #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.content table td,
|
||||||
|
.content table th {
|
||||||
|
padding: 0.7em
|
||||||
|
}
|
||||||
|
|
||||||
|
.content p {
|
||||||
|
line-height: 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
.content a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 21px;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-width: 2px 0;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h2 {
|
||||||
|
font-size: 1.8em;
|
||||||
|
margin-top: 2em;
|
||||||
|
border-top: 2px solid #ccc;
|
||||||
|
padding-top: 0.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h1+h2,
|
||||||
|
.content h1+div+h2 {
|
||||||
|
border-top: none;
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h3,
|
||||||
|
.content h4 {
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
text-transform: uppercase
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h5,
|
||||||
|
.content h6 {
|
||||||
|
text-transform: uppercase
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside {
|
||||||
|
padding: 1em;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
line-height: 1.6
|
||||||
|
}
|
||||||
|
|
||||||
|
.content aside:before {
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
font-size: 14px
|
||||||
|
}
|
1085
public/docs/css/theme-default.style.css
Normal file
1085
public/docs/css/theme-default.style.css
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/docs/images/navbar.png
Normal file
BIN
public/docs/images/navbar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 B |
11426
public/docs/index.html
Normal file
11426
public/docs/index.html
Normal file
File diff suppressed because it is too large
Load Diff
149
public/docs/js/theme-default-4.37.2.js
Normal file
149
public/docs/js/theme-default-4.37.2.js
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const updateHash = function (id) {
|
||||||
|
window.location.hash = `#${id}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const navButton = document.getElementById('nav-button');
|
||||||
|
const menuWrapper = document.querySelector('.tocify-wrapper');
|
||||||
|
function toggleSidebar(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (menuWrapper) {
|
||||||
|
menuWrapper.classList.toggle('open');
|
||||||
|
navButton.classList.toggle('open');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeSidebar() {
|
||||||
|
if (menuWrapper) {
|
||||||
|
menuWrapper.classList.remove('open');
|
||||||
|
navButton.classList.remove('open');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
navButton.addEventListener('click', toggleSidebar);
|
||||||
|
|
||||||
|
window.hljs.highlightAll();
|
||||||
|
|
||||||
|
const wrapper = document.getElementById('toc');
|
||||||
|
// https://jets.js.org/
|
||||||
|
window.jets = new window.Jets({
|
||||||
|
// *OR - Selects elements whose values contains at least one part of search substring
|
||||||
|
searchSelector: '*OR',
|
||||||
|
searchTag: '#input-search',
|
||||||
|
contentTag: '#toc li',
|
||||||
|
didSearch: function(term) {
|
||||||
|
wrapper.classList.toggle('jets-searching', String(term).length > 0)
|
||||||
|
},
|
||||||
|
// map these accent keys to plain values
|
||||||
|
diacriticsMap: {
|
||||||
|
a: 'ÀÁÂÃÄÅàáâãäåĀāąĄ',
|
||||||
|
c: 'ÇçćĆčČ',
|
||||||
|
d: 'đĐďĎ',
|
||||||
|
e: 'ÈÉÊËèéêëěĚĒēęĘ',
|
||||||
|
i: 'ÌÍÎÏìíîïĪī',
|
||||||
|
l: 'łŁ',
|
||||||
|
n: 'ÑñňŇńŃ',
|
||||||
|
o: 'ÒÓÔÕÕÖØòóôõöøŌō',
|
||||||
|
r: 'řŘ',
|
||||||
|
s: 'ŠšśŚ',
|
||||||
|
t: 'ťŤ',
|
||||||
|
u: 'ÙÚÛÜùúûüůŮŪū',
|
||||||
|
y: 'ŸÿýÝ',
|
||||||
|
z: 'ŽžżŻźŹ'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function hashChange() {
|
||||||
|
const currentItems = document.querySelectorAll('.tocify-subheader.visible, .tocify-item.tocify-focus');
|
||||||
|
Array.from(currentItems).forEach((elem) => {
|
||||||
|
elem.classList.remove('visible', 'tocify-focus');
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentTag = document.querySelector(`a[href="${window.location.hash}"]`);
|
||||||
|
if (currentTag) {
|
||||||
|
const parent = currentTag.closest('.tocify-subheader');
|
||||||
|
if (parent) {
|
||||||
|
parent.classList.add('visible');
|
||||||
|
}
|
||||||
|
|
||||||
|
const siblings = currentTag.closest('.tocify-header');
|
||||||
|
if (siblings) {
|
||||||
|
Array.from(siblings.querySelectorAll('.tocify-subheader')).forEach((elem) => {
|
||||||
|
elem.classList.add('visible');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTag.parentElement.classList.add('tocify-focus');
|
||||||
|
|
||||||
|
// wait for dom changes to be done
|
||||||
|
setTimeout(() => {
|
||||||
|
currentTag.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
|
||||||
|
// only close the sidebar on level-2 events
|
||||||
|
if (currentTag.parentElement.classList.contains('level-2')) {
|
||||||
|
closeSidebar();
|
||||||
|
}
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let languages = JSON.parse(document.body.getAttribute('data-languages'));
|
||||||
|
// Support a key => value object where the key is the name, or an array of strings where the value is the name
|
||||||
|
if (!Array.isArray(languages)) {
|
||||||
|
languages = Object.values(languages);
|
||||||
|
}
|
||||||
|
// if there is no language use the first one
|
||||||
|
const currentLanguage = window.localStorage.getItem('language') || languages[0];
|
||||||
|
const languageStyle = document.getElementById('language-style');
|
||||||
|
const langSelector = document.querySelectorAll('.lang-selector button.lang-button');
|
||||||
|
|
||||||
|
function setActiveLanguage(newLanguage) {
|
||||||
|
window.localStorage.setItem('language', newLanguage);
|
||||||
|
if (!languageStyle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newStyle = languages.map((language) => {
|
||||||
|
return language === newLanguage
|
||||||
|
// the current one should be visible
|
||||||
|
? `body .content .${language}-example pre { display: block; }`
|
||||||
|
// the inactive one should be hidden
|
||||||
|
: `body .content .${language}-example pre { display: none; }`;
|
||||||
|
}).join(`\n`);
|
||||||
|
|
||||||
|
Array.from(langSelector).forEach((elem) => {
|
||||||
|
elem.classList.toggle('active', elem.getAttribute('data-language-name') === newLanguage);
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeHash = window.location.hash.slice(1);
|
||||||
|
|
||||||
|
languageStyle.innerHTML = newStyle;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
updateHash(activeHash);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
setActiveLanguage(currentLanguage);
|
||||||
|
|
||||||
|
Array.from(langSelector).forEach((elem) => {
|
||||||
|
elem.addEventListener('click', () => {
|
||||||
|
const newLanguage = elem.getAttribute('data-language-name');
|
||||||
|
setActiveLanguage(newLanguage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('hashchange', hashChange, false);
|
||||||
|
|
||||||
|
const divs = document.querySelectorAll('.content h1[id], .content h2[id]');
|
||||||
|
|
||||||
|
document.addEventListener('scroll', () => {
|
||||||
|
divs.forEach(item => {
|
||||||
|
const rect = item.getBoundingClientRect();
|
||||||
|
if (rect.top > 0 && rect.top < 150) {
|
||||||
|
const location = window.location.toString().split('#')[0];
|
||||||
|
history.replaceState(null, null, location + '#' + item.id);
|
||||||
|
hashChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
hashChange();
|
||||||
|
});
|
277
public/docs/js/tryitout-4.37.2.js
Normal file
277
public/docs/js/tryitout-4.37.2.js
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
window.abortControllers = {};
|
||||||
|
|
||||||
|
function cacheAuthValue() {
|
||||||
|
// Whenever the auth header is set for one endpoint, cache it for the others
|
||||||
|
window.lastAuthValue = '';
|
||||||
|
let authInputs = document.querySelectorAll(`.auth-value`)
|
||||||
|
authInputs.forEach(el => {
|
||||||
|
el.addEventListener('input', (event) => {
|
||||||
|
window.lastAuthValue = event.target.value;
|
||||||
|
authInputs.forEach(otherInput => {
|
||||||
|
if (otherInput === el) return;
|
||||||
|
// Don't block the main thread
|
||||||
|
setTimeout(() => {
|
||||||
|
otherInput.value = window.lastAuthValue;
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', cacheAuthValue);
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
if (!document.cookie) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookies = document.cookie.split(';')
|
||||||
|
.map(c => c.trim())
|
||||||
|
.filter(c => c.startsWith(name + '='));
|
||||||
|
|
||||||
|
if (cookies.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodeURIComponent(cookies[0].split('=')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryItOut(endpointId) {
|
||||||
|
document.querySelector(`#btn-tryout-${endpointId}`).hidden = true;
|
||||||
|
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = false;
|
||||||
|
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`).hidden = false;
|
||||||
|
executeBtn.disabled = false;
|
||||||
|
|
||||||
|
// Show all input fields
|
||||||
|
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
|
||||||
|
.forEach(el => el.style.display = 'block');
|
||||||
|
|
||||||
|
if (document.querySelector(`#form-${endpointId}`).dataset.authed === "1") {
|
||||||
|
const authElement = document.querySelector(`#auth-${endpointId}`);
|
||||||
|
authElement && (authElement.hidden = false);
|
||||||
|
}
|
||||||
|
// Expand all nested fields
|
||||||
|
document.querySelectorAll(`#form-${endpointId} details`)
|
||||||
|
.forEach(el => el.open = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelTryOut(endpointId) {
|
||||||
|
if (window.abortControllers[endpointId]) {
|
||||||
|
window.abortControllers[endpointId].abort();
|
||||||
|
delete window.abortControllers[endpointId];
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector(`#btn-tryout-${endpointId}`).hidden = false;
|
||||||
|
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
|
||||||
|
executeBtn.hidden = true;
|
||||||
|
executeBtn.textContent = executeBtn.dataset.initialText;
|
||||||
|
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = true;
|
||||||
|
// Hide inputs
|
||||||
|
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
|
||||||
|
.forEach(el => el.style.display = 'none');
|
||||||
|
document.querySelectorAll(`#form-${endpointId} details`)
|
||||||
|
.forEach(el => el.open = false);
|
||||||
|
const authElement = document.querySelector(`#auth-${endpointId}`);
|
||||||
|
authElement && (authElement.hidden = true);
|
||||||
|
|
||||||
|
document.querySelector('#execution-results-' + endpointId).hidden = true;
|
||||||
|
document.querySelector('#execution-error-' + endpointId).hidden = true;
|
||||||
|
|
||||||
|
// Revert to sample code blocks
|
||||||
|
document.querySelector('#example-requests-' + endpointId).hidden = false;
|
||||||
|
document.querySelector('#example-responses-' + endpointId).hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeAPICall(method, path, body = {}, query = {}, headers = {}, endpointId = null) {
|
||||||
|
console.log({endpointId, path, body, query, headers});
|
||||||
|
|
||||||
|
if (!(body instanceof FormData) && typeof body !== "string") {
|
||||||
|
body = JSON.stringify(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(window.tryItOutBaseUrl + '/' + path.replace(/^\//, ''));
|
||||||
|
|
||||||
|
// We need this function because if you try to set an array or object directly to a URLSearchParams object,
|
||||||
|
// you'll get [object Object] or the array.toString()
|
||||||
|
function addItemToSearchParamsObject(key, value, searchParams) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((v, i) => {
|
||||||
|
// Append {filters: [first, second]} as filters[0]=first&filters[1]second
|
||||||
|
addItemToSearchParamsObject(key + '[' + i + ']', v, searchParams);
|
||||||
|
})
|
||||||
|
} else if (typeof value === 'object' && value !== null) {
|
||||||
|
Object.keys(value).forEach((i) => {
|
||||||
|
// Append {filters: {name: first}} as filters[name]=first
|
||||||
|
addItemToSearchParamsObject(key + '[' + i + ']', value[i], searchParams);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
searchParams.append(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(query)
|
||||||
|
.forEach(key => addItemToSearchParamsObject(key, query[key], url.searchParams));
|
||||||
|
|
||||||
|
window.abortControllers[endpointId] = new AbortController();
|
||||||
|
|
||||||
|
return fetch(url, {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
body: method === 'GET' ? undefined : body,
|
||||||
|
signal: window.abortControllers[endpointId].signal,
|
||||||
|
referrer: window.tryItOutBaseUrl,
|
||||||
|
mode: 'cors',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => Promise.all([response.status, response.statusText, response.text(), response.headers]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideCodeSamples(endpointId) {
|
||||||
|
document.querySelector('#example-requests-' + endpointId).hidden = true;
|
||||||
|
document.querySelector('#example-responses-' + endpointId).hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResponse(endpointId, response, status, headers) {
|
||||||
|
hideCodeSamples(endpointId);
|
||||||
|
|
||||||
|
// Hide error views
|
||||||
|
document.querySelector('#execution-error-' + endpointId).hidden = true;
|
||||||
|
|
||||||
|
const responseContentEl = document.querySelector('#execution-response-content-' + endpointId);
|
||||||
|
|
||||||
|
// Prettify it if it's JSON
|
||||||
|
let isJson = false;
|
||||||
|
try {
|
||||||
|
const jsonParsed = JSON.parse(response);
|
||||||
|
if (jsonParsed !== null) {
|
||||||
|
isJson = true;
|
||||||
|
response = JSON.stringify(jsonParsed, null, 4);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
responseContentEl.textContent = response === '' ? responseContentEl.dataset.emptyResponseText : response;
|
||||||
|
isJson && window.hljs.highlightElement(responseContentEl);
|
||||||
|
const statusEl = document.querySelector('#execution-response-status-' + endpointId);
|
||||||
|
statusEl.textContent = ` (${status})`;
|
||||||
|
document.querySelector('#execution-results-' + endpointId).hidden = false;
|
||||||
|
statusEl.scrollIntoView({behavior: "smooth", block: "center"});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(endpointId, err) {
|
||||||
|
hideCodeSamples(endpointId);
|
||||||
|
// Hide response views
|
||||||
|
document.querySelector('#execution-results-' + endpointId).hidden = true;
|
||||||
|
|
||||||
|
// Show error views
|
||||||
|
let errorMessage = err.message || err;
|
||||||
|
const $errorMessageEl = document.querySelector('#execution-error-message-' + endpointId);
|
||||||
|
$errorMessageEl.textContent = errorMessage + $errorMessageEl.textContent;
|
||||||
|
const errorEl = document.querySelector('#execution-error-' + endpointId);
|
||||||
|
errorEl.hidden = false;
|
||||||
|
errorEl.scrollIntoView({behavior: "smooth", block: "center"});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executeTryOut(endpointId, form) {
|
||||||
|
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
|
||||||
|
executeBtn.textContent = executeBtn.dataset.loadingText;
|
||||||
|
executeBtn.disabled = true;
|
||||||
|
executeBtn.scrollIntoView({behavior: "smooth", block: "center"});
|
||||||
|
|
||||||
|
let body;
|
||||||
|
let setter;
|
||||||
|
if (form.dataset.hasfiles === "1") {
|
||||||
|
body = new FormData();
|
||||||
|
setter = (name, value) => body.append(name, value);
|
||||||
|
} else if (form.dataset.isarraybody === "1") {
|
||||||
|
body = [];
|
||||||
|
setter = (name, value) => _.set(body, name, value);
|
||||||
|
} else {
|
||||||
|
body = {};
|
||||||
|
setter = (name, value) => _.set(body, name, value);
|
||||||
|
}
|
||||||
|
const bodyParameters = form.querySelectorAll('input[data-component=body]');
|
||||||
|
bodyParameters.forEach(el => {
|
||||||
|
let value = el.value;
|
||||||
|
|
||||||
|
if (el.type === 'number' && typeof value === 'string') {
|
||||||
|
value = parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.type === 'file' && el.files[0]) {
|
||||||
|
setter(el.name, el.files[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.type !== 'radio') {
|
||||||
|
if (value === "" && el.required === false) {
|
||||||
|
// Don't include empty optional values in the request
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setter(el.name, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.checked) {
|
||||||
|
value = (value === 'false') ? false : true;
|
||||||
|
setter(el.name, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const query = {};
|
||||||
|
const queryParameters = form.querySelectorAll('input[data-component=query]');
|
||||||
|
queryParameters.forEach(el => {
|
||||||
|
if (el.type !== 'radio' || (el.type === 'radio' && el.checked)) {
|
||||||
|
if (el.value === '') {
|
||||||
|
// Don't include empty values in the request
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_.set(query, el.name, el.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let path = form.dataset.path;
|
||||||
|
const urlParameters = form.querySelectorAll('input[data-component=url]');
|
||||||
|
urlParameters.forEach(el => (path = path.replace(new RegExp(`\\{${el.name}\\??}`), el.value)));
|
||||||
|
|
||||||
|
const headers = Object.fromEntries(Array.from(form.querySelectorAll('input[data-component=header]'))
|
||||||
|
.map(el => [el.name, el.value]));
|
||||||
|
|
||||||
|
// When using FormData, the browser sets the correct content-type + boundary
|
||||||
|
let method = form.dataset.method;
|
||||||
|
if (body instanceof FormData) {
|
||||||
|
delete headers['Content-Type'];
|
||||||
|
|
||||||
|
// When using FormData with PUT or PATCH, use method spoofing so PHP can access the post body
|
||||||
|
if (['PUT', 'PATCH'].includes(form.dataset.method)) {
|
||||||
|
method = 'POST';
|
||||||
|
setter('_method', form.dataset.method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let preflightPromise = Promise.resolve();
|
||||||
|
if (window.useCsrf && window.csrfUrl) {
|
||||||
|
preflightPromise = makeAPICall('GET', window.csrfUrl).then(() => {
|
||||||
|
headers['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return preflightPromise.then(() => makeAPICall(method, path, body, query, headers, endpointId))
|
||||||
|
.then(([responseStatus, statusText, responseContent, responseHeaders]) => {
|
||||||
|
handleResponse(endpointId, responseContent, responseStatus, responseHeaders)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.name === "AbortError") {
|
||||||
|
console.log("Request cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("Error while making request: ", err);
|
||||||
|
handleError(endpointId, err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
executeBtn.disabled = false;
|
||||||
|
executeBtn.textContent = executeBtn.dataset.initialText;
|
||||||
|
});
|
||||||
|
}
|
15082
public/docs/openapi.yaml
Normal file
15082
public/docs/openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,6 @@
|
|||||||
use App\Http\Controllers\Api\AuthController;
|
use App\Http\Controllers\Api\AuthController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/status', function () {
|
|
||||||
return response()->json(['message' => 'okay']);
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::post('/login', [AuthController::class, 'login']);
|
Route::post('/login', [AuthController::class, 'login']);
|
||||||
Route::group(['middleware' => 'auth:sanctum'], function () {
|
Route::group(['middleware' => 'auth:sanctum'], function () {
|
||||||
Route::delete('/logout', [AuthController::class, 'logout']);
|
Route::delete('/logout', [AuthController::class, 'logout']);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user