Expose public Scalar API docs
This commit is contained in:
+2
-1
@@ -14,7 +14,8 @@
|
|||||||
"laravel/fortify": "^1.34",
|
"laravel/fortify": "^1.34",
|
||||||
"laravel/framework": "^13.0",
|
"laravel/framework": "^13.0",
|
||||||
"laravel/tinker": "^3.0",
|
"laravel/tinker": "^3.0",
|
||||||
"laravel/wayfinder": "^0.1.14"
|
"laravel/wayfinder": "^0.1.14",
|
||||||
|
"scalar/laravel": "^0.2.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.24",
|
"fakerphp/faker": "^1.24",
|
||||||
|
|||||||
Generated
+131
-1
@@ -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": "c55625a323719bb164dc4b9b763d6ede",
|
"content-hash": "896a8244956aa86a482b054e2616a90f",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@@ -3770,6 +3770,136 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-12-14T04:43:48+00:00"
|
"time": "2025-12-14T04:43:48+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "scalar/laravel",
|
||||||
|
"version": "0.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/scalar/laravel.git",
|
||||||
|
"reference": "5f6dace4740a082df5058804430f12af01925810"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/scalar/laravel/zipball/5f6dace4740a082df5058804430f12af01925810",
|
||||||
|
"reference": "5f6dace4740a082df5058804430f12af01925810",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^10.0||^11.0||^12.0||^13.0",
|
||||||
|
"php": "^8.2||^8.3",
|
||||||
|
"spatie/laravel-package-tools": "^1.16"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/pint": "^1.14",
|
||||||
|
"nunomaduro/collision": "^8.7.0||^7.10.0",
|
||||||
|
"orchestra/testbench": "^8.0||^9.0||^10.0||^11.0",
|
||||||
|
"pestphp/pest": "^2.3.4||^3.7.4||^4.0",
|
||||||
|
"pestphp/pest-plugin-arch": "^2.7.0||^3.0.0||^4.0",
|
||||||
|
"pestphp/pest-plugin-laravel": "^2.3.0||^3.1.0||^4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"Scalar": "Scalar\\Facades\\Scalar"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Scalar\\ScalarServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Scalar\\": "src/",
|
||||||
|
"Scalar\\Database\\Factories\\": "database/factories/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Hans Pagel",
|
||||||
|
"email": "mail@hanspagel.com",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Render your OpenAPI-based API reference",
|
||||||
|
"homepage": "https://github.com/scalar/laravel",
|
||||||
|
"keywords": [
|
||||||
|
"laravel",
|
||||||
|
"openapi",
|
||||||
|
"scalar",
|
||||||
|
"swagger"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/scalar/laravel/issues",
|
||||||
|
"source": "https://github.com/scalar/laravel/tree/0.2.1"
|
||||||
|
},
|
||||||
|
"time": "2026-03-23T14:14:34+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-package-tools",
|
||||||
|
"version": "1.93.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-package-tools.git",
|
||||||
|
"reference": "0d097bce95b2bf6802fb1d83e1e753b0f5a948e7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/0d097bce95b2bf6802fb1d83e1e753b0f5a948e7",
|
||||||
|
"reference": "0d097bce95b2bf6802fb1d83e1e753b0f5a948e7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^10.0|^11.0|^12.0|^13.0",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.5",
|
||||||
|
"orchestra/testbench": "^8.0|^9.2|^10.0|^11.0",
|
||||||
|
"pestphp/pest": "^2.1|^3.1|^4.0",
|
||||||
|
"phpunit/php-code-coverage": "^10.0|^11.0|^12.0",
|
||||||
|
"phpunit/phpunit": "^10.5|^11.5|^12.5",
|
||||||
|
"spatie/pest-plugin-test-time": "^2.2|^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\LaravelPackageTools\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Tools for creating Laravel packages",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-package-tools",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-package-tools",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
||||||
|
"source": "https://github.com/spatie/laravel-package-tools/tree/1.93.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-02-21T12:49:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
"version": "v8.0.8",
|
"version": "v8.0.8",
|
||||||
|
|||||||
@@ -0,0 +1,198 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar Domain
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the subdomain where Scalar will be accessible from. If this
|
||||||
|
| setting is null, Scalar will reside under the same domain as the
|
||||||
|
| application. Otherwise, this value will serve as the subdomain.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'domain' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the URI path where Scalar will be accessible from. Feel free
|
||||||
|
| to change this path to anything you like. Note that the URI will not
|
||||||
|
| affect the paths of its internal API that aren't exposed to users.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'path' => '/api/docs',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar Route Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These middleware will get attached onto each Scalar route, giving you
|
||||||
|
| the chance to add your own middleware to this list or change any of
|
||||||
|
| the existing middleware. Or, you can simply stick with this list.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'middleware' => ['web'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar OpenAPI Document URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the URL to the OpenAPI document that Scalar will use to generate
|
||||||
|
| the API reference. By default, it points to the latest version of the
|
||||||
|
| Scalar Galaxy package. You can change this to use a custom OpenAPI file.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'url' => '/api/docs/openapi.json',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar CDN URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the URL to the CDN where Scalar's API reference assets are hosted.
|
||||||
|
| By default, it points to the jsDelivr CDN for the @scalar/api-reference
|
||||||
|
| package. You can change this if you want to use a different CDN.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'cdn' => 'https://cdn.jsdelivr.net/npm/@scalar/api-reference',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Scalar Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The configuration options for the Scalar API reference. This array
|
||||||
|
| contains all the settings that control the behavior and appearance
|
||||||
|
| of the API documentation.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'configuration' => [
|
||||||
|
/** A string to use one of the color presets */
|
||||||
|
'theme' =>
|
||||||
|
// 'alternate',
|
||||||
|
// 'bluePlanet',
|
||||||
|
// 'deepSpace',
|
||||||
|
// 'default',
|
||||||
|
// 'kepler',
|
||||||
|
'laravel',
|
||||||
|
// 'mars',
|
||||||
|
// 'moon',
|
||||||
|
// 'purple',
|
||||||
|
// 'saturn',
|
||||||
|
// 'solarized',
|
||||||
|
// 'none',
|
||||||
|
|
||||||
|
/** The layout to use for the references */
|
||||||
|
'layout' => 'modern',
|
||||||
|
|
||||||
|
/** URL to a request proxy for the API client */
|
||||||
|
'proxyUrl' => 'https://proxy.scalar.com',
|
||||||
|
|
||||||
|
/** Whether to show the sidebar */
|
||||||
|
'showSidebar' => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show models in the sidebar, search, and content.
|
||||||
|
*/
|
||||||
|
'hideModels' => false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the “Download OpenAPI Document” button
|
||||||
|
*/
|
||||||
|
'hideDownloadButton' => false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the “Test Request” button
|
||||||
|
*/
|
||||||
|
'hideTestRequestButton' => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the sidebar search bar
|
||||||
|
*/
|
||||||
|
'hideSearch' => false,
|
||||||
|
|
||||||
|
/** Whether dark mode is on or off initially (light mode) */
|
||||||
|
'darkMode' => false,
|
||||||
|
|
||||||
|
/** forceDarkModeState makes it always this state no matter what*/
|
||||||
|
'forceDarkModeState' => 'dark',
|
||||||
|
|
||||||
|
/** Whether to show the dark mode toggle */
|
||||||
|
'hideDarkModeToggle' => false,
|
||||||
|
|
||||||
|
/** Key used with CTRL/CMD to open the search modal (defaults to 'k' e.g. CMD+k) */
|
||||||
|
'searchHotKey' => 'k',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If used, passed data will be added to the HTML header
|
||||||
|
*
|
||||||
|
* @see https://unhead.unjs.io/usage/composables/use-seo-meta
|
||||||
|
*/
|
||||||
|
'metaData' => [
|
||||||
|
'title' => config('app.name').' API Reference',
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to a favicon image
|
||||||
|
*
|
||||||
|
* @example '/favicon.svg'
|
||||||
|
*/
|
||||||
|
'favicon' => '',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of httpsnippet clients to hide from the clients menu
|
||||||
|
* By default hides Unirest, pass `[]` to show all clients
|
||||||
|
*/
|
||||||
|
'hiddenClients' => [
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/** Determine the HTTP client that’s selected by default */
|
||||||
|
'defaultHttpClient' => [
|
||||||
|
'targetId' => 'shell',
|
||||||
|
'clientKey' => 'curl',
|
||||||
|
],
|
||||||
|
|
||||||
|
/** Custom CSS to be added to the page */
|
||||||
|
// 'customCss' => '',
|
||||||
|
|
||||||
|
/** Prefill authentication */
|
||||||
|
// 'authentication' => [
|
||||||
|
// // TODO
|
||||||
|
// ],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The baseServerURL is used when the spec servers are relative paths and we are using SSR.
|
||||||
|
* On the client we can grab the window.location.origin but on the server we need
|
||||||
|
* to use this prop.
|
||||||
|
*/
|
||||||
|
// 'baseServerURL' => '',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of servers to override the openapi spec servers
|
||||||
|
*/
|
||||||
|
// 'servers' => [
|
||||||
|
// [
|
||||||
|
// 'url' => 'https://api.scalar.com',
|
||||||
|
// 'description' => 'Production server',
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We’re using Inter and JetBrains Mono as the default fonts. If you want to use your own fonts, set this to false.
|
||||||
|
*/
|
||||||
|
'withDefaultFonts' => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default we only open the relevant tag based on the url, however if you want all the tags open by default then set this configuration option :)
|
||||||
|
*/
|
||||||
|
'defaultOpenAllTags' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Laravel\Fortify\Features;
|
use Laravel\Fortify\Features;
|
||||||
|
|
||||||
@@ -7,6 +9,16 @@ Route::inertia('/', 'Welcome', [
|
|||||||
'canRegister' => Features::enabled(Features::registration()),
|
'canRegister' => Features::enabled(Features::registration()),
|
||||||
])->name('home');
|
])->name('home');
|
||||||
|
|
||||||
|
Route::get('api/docs/openapi.json', function (): Response {
|
||||||
|
$path = base_path('docs/openapi/kanbangit-api.openapi.json');
|
||||||
|
|
||||||
|
abort_unless(File::exists($path), 404);
|
||||||
|
|
||||||
|
return response(File::get($path), 200, [
|
||||||
|
'Content-Type' => 'application/vnd.oai.openapi+json; charset=utf-8',
|
||||||
|
]);
|
||||||
|
})->name('api.docs.openapi');
|
||||||
|
|
||||||
Route::middleware(['auth', 'verified'])->group(function () {
|
Route::middleware(['auth', 'verified'])->group(function () {
|
||||||
Route::inertia('dashboard', 'Dashboard')->name('dashboard');
|
Route::inertia('dashboard', 'Dashboard')->name('dashboard');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Api;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class PublicApiDocumentationTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_scalar_api_docs_are_public(): void
|
||||||
|
{
|
||||||
|
$this->get('/api/docs')
|
||||||
|
->assertOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_openapi_document_is_publicly_served(): void
|
||||||
|
{
|
||||||
|
$response = $this->get('/api/docs/openapi.json')
|
||||||
|
->assertOk();
|
||||||
|
|
||||||
|
$this->assertStringStartsWith(
|
||||||
|
'application/vnd.oai.openapi+json',
|
||||||
|
(string) $response->headers->get('Content-Type'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$document = json_decode((string) $response->getContent(), true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
|
||||||
|
$this->assertSame('3.1.0', $document['openapi']);
|
||||||
|
$this->assertSame([], $document['security']);
|
||||||
|
$this->assertArrayHasKey('/projects', $document['paths']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_application_api_still_requires_an_authenticated_user(): void
|
||||||
|
{
|
||||||
|
$this->getJson('/api/projects')
|
||||||
|
->assertUnauthorized();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user