Add Scramble package and configure API documentation; update letter routes and controller responses

This commit is contained in:
NoBody313
2025-03-23 05:22:53 +07:00
parent ade38e2745
commit 6d431d9610
7 changed files with 418 additions and 69 deletions
+1 -6
View File
@@ -92,7 +92,6 @@ class LetterController extends Controller
'message' => 'Surat berhasil disimpan', 'message' => 'Surat berhasil disimpan',
'data' => $letter->load('fileUpload') 'data' => $letter->load('fileUpload')
], 201); ], 201);
} catch (ValidationException $e) { } catch (ValidationException $e) {
return response()->json([ return response()->json([
'success' => false, 'success' => false,
@@ -178,7 +177,6 @@ class LetterController extends Controller
'message' => 'Surat berhasil diperbarui', 'message' => 'Surat berhasil diperbarui',
'data' => $letter->load('fileUpload') 'data' => $letter->load('fileUpload')
]); ]);
} catch (ModelNotFoundException $e) { } catch (ModelNotFoundException $e) {
return response()->json([ return response()->json([
'success' => false, 'success' => false,
@@ -214,7 +212,6 @@ class LetterController extends Controller
'success' => true, 'success' => true,
'message' => 'Surat berhasil dihapus' 'message' => 'Surat berhasil dihapus'
]); ]);
} catch (ModelNotFoundException $e) { } catch (ModelNotFoundException $e) {
return response()->json([ return response()->json([
'success' => false, 'success' => false,
@@ -292,9 +289,7 @@ class LetterController extends Controller
'nomor_surat_acceptance' => $letter->nomor_surat_acceptance, 'nomor_surat_acceptance' => $letter->nomor_surat_acceptance,
'is_completion' => $letter->is_completion, 'is_completion' => $letter->is_completion,
'nomor_surat_completion' => $letter->nomor_surat_completion, 'nomor_surat_completion' => $letter->nomor_surat_completion,
'lampiran' => $letter->fileUpload ? 'lampiran' => $letter->fileUpload ? $letter->fileUpload->id : null,
asset('storage/lampiran/' . basename($letter->fileUpload->file_path)) :
null,
'created_at' => $letter->created_at, 'created_at' => $letter->created_at,
]; ];
} }
+1
View File
@@ -10,6 +10,7 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"dedoc/scramble": "^0.12.15",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1" "laravel/tinker": "^2.10.1"
Generated
+244 -61
View File
@@ -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": "85c1d2065f70e38b0d6bf66559fb13c5", "content-hash": "b78b17d2db2640f5084597c5cc0e977e",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@@ -135,6 +135,82 @@
], ],
"time": "2024-02-09T16:56:22+00:00" "time": "2024-02-09T16:56:22+00:00"
}, },
{
"name": "dedoc/scramble",
"version": "v0.12.15",
"source": {
"type": "git",
"url": "https://github.com/dedoc/scramble.git",
"reference": "aee9401500f398e9b570298a6757104a757c170c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dedoc/scramble/zipball/aee9401500f398e9b570298a6757104a757c170c",
"reference": "aee9401500f398e9b570298a6757104a757c170c",
"shasum": ""
},
"require": {
"illuminate/contracts": "^10.0|^11.0|^12.0",
"myclabs/deep-copy": "^1.12",
"nikic/php-parser": "^5.0",
"php": "^8.1",
"phpstan/phpdoc-parser": "^1.0|^2.0",
"spatie/laravel-package-tools": "^1.9.2"
},
"require-dev": {
"laravel/pint": "^v1.1.0",
"nunomaduro/collision": "^7.0|^8.0",
"orchestra/testbench": "^8.0|^9.0|^10.0",
"pestphp/pest": "^2.34|^3.7",
"pestphp/pest-plugin-laravel": "^2.3|^3.1",
"phpunit/phpunit": "^10.5|^11.5.3",
"spatie/laravel-permission": "^6.10",
"spatie/pest-plugin-snapshots": "^2.1"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Dedoc\\Scramble\\ScrambleServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Dedoc\\Scramble\\": "src",
"Dedoc\\Scramble\\Database\\Factories\\": "database/factories"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Lytvynenko",
"email": "litvinenko95@gmail.com",
"role": "Developer"
}
],
"description": "Automatic generation of API documentation for Laravel applications.",
"homepage": "https://github.com/dedoc/scramble",
"keywords": [
"documentation",
"laravel",
"openapi"
],
"support": {
"issues": "https://github.com/dedoc/scramble/issues",
"source": "https://github.com/dedoc/scramble/tree/v0.12.15"
},
"funding": [
{
"url": "https://github.com/romalytvynenko",
"type": "github"
}
],
"time": "2025-03-22T13:58:51+00:00"
},
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
"version": "v3.0.3", "version": "v3.0.3",
@@ -2173,6 +2249,66 @@
], ],
"time": "2024-12-05T17:15:07+00:00" "time": "2024-12-05T17:15:07+00:00"
}, },
{
"name": "myclabs/deep-copy",
"version": "1.13.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3 <3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpspec/prophecy": "^1.10",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2025-02-12T12:17:51+00:00"
},
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "3.8.6", "version": "3.8.6",
@@ -2647,6 +2783,53 @@
], ],
"time": "2024-07-20T21:41:07+00:00" "time": "2024-07-20T21:41:07+00:00"
}, },
{
"name": "phpstan/phpdoc-parser",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"doctrine/annotations": "^2.0",
"nikic/php-parser": "^5.3.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.6",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0"
},
"time": "2025-02-19T13:28:12+00:00"
},
{ {
"name": "psr/clock", "name": "psr/clock",
"version": "1.0.0", "version": "1.0.0",
@@ -3350,6 +3533,66 @@
], ],
"time": "2024-04-27T21:32:50+00:00" "time": "2024-04-27T21:32:50+00:00"
}, },
{
"name": "spatie/laravel-package-tools",
"version": "1.91.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-package-tools.git",
"reference": "b0b509b9b01d77caa431ce9af3a706bc678e09c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/b0b509b9b01d77caa431ce9af3a706bc678e09c9",
"reference": "b0b509b9b01d77caa431ce9af3a706bc678e09c9",
"shasum": ""
},
"require": {
"illuminate/contracts": "^9.28|^10.0|^11.0|^12.0",
"php": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.5",
"orchestra/testbench": "^7.7|^8.0|^9.0|^10.0",
"pestphp/pest": "^1.23|^2.1|^3.1",
"phpunit/phpunit": "^9.5.24|^10.5|^11.5",
"spatie/pest-plugin-test-time": "^1.1|^2.2"
},
"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.91.1"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2025-03-21T09:50:49+00:00"
},
{ {
"name": "symfony/clock", "name": "symfony/clock",
"version": "v7.2.0", "version": "v7.2.0",
@@ -6326,66 +6569,6 @@
}, },
"time": "2024-05-16T03:13:13+00:00" "time": "2024-05-16T03:13:13+00:00"
}, },
{
"name": "myclabs/deep-copy",
"version": "1.13.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3 <3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpspec/prophecy": "^1.10",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2025-02-12T12:17:51+00:00"
},
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
"version": "v8.6.1", "version": "v8.6.1",
+103
View File
@@ -0,0 +1,103 @@
<?php
use Dedoc\Scramble\Http\Middleware\RestrictedDocsAccess;
return [
/*
* Your API path. By default, all routes starting with this path will be added to the docs.
* If you need to change this behavior, you can add your custom routes resolver using `Scramble::routes()`.
*/
'api_path' => 'api',
/*
* Your API domain. By default, app domain is used. This is also a part of the default API routes
* matcher, so when implementing your own, make sure you use this config if needed.
*/
'api_domain' => null,
/*
* The path where your OpenAPI specification will be exported.
*/
'export_path' => 'api.json',
'info' => [
/*
* API version.
*/
'version' => env('API_VERSION', '0.0.1'),
/*
* Description rendered on the home page of the API documentation (`/docs/api`).
*/
'description' => '',
],
/*
* Customize Stoplight Elements UI
*/
'ui' => [
/*
* Define the title of the documentation's website. App name is used when this config is `null`.
*/
'title' => null,
/*
* Define the theme of the documentation. Available options are `light` and `dark`.
*/
'theme' => 'light',
/*
* Hide the `Try It` feature. Enabled by default.
*/
'hide_try_it' => false,
/*
* Hide the schemas in the Table of Contents. Enabled by default.
*/
'hide_schemas' => false,
/*
* URL to an image that displays as a small square logo next to the title, above the table of contents.
*/
'logo' => '',
/*
* Use to fetch the credential policy for the Try It feature. Options are: omit, include (default), and same-origin
*/
'try_it_credentials_policy' => 'include',
],
/*
* The list of servers of the API. By default, when `null`, server URL will be created from
* `scramble.api_path` and `scramble.api_domain` config variables. When providing an array, you
* will need to specify the local server URL manually (if needed).
*
* Example of non-default config (final URLs are generated using Laravel `url` helper):
*
* ```php
* 'servers' => [
* 'Live' => 'api',
* 'Prod' => 'https://scramble.dedoc.co/api',
* ],
* ```
*/
'servers' => null,
/**
* Determines how Scramble stores the descriptions of enum cases.
* Available options:
* - 'description' Case descriptions are stored as the enum schema's description using table formatting.
* - 'extension' Case descriptions are stored in the `x-enumDescriptions` enum schema extension.
*
* @see https://redocly.com/docs-legacy/api-reference-docs/specification-extensions/x-enum-descriptions
* - false - Case descriptions are ignored.
*/
'enum_cases_description_strategy' => 'description',
'middleware' => [
'web',
RestrictedDocsAccess::class,
],
'extensions' => [],
];
View File
+67
View File
@@ -0,0 +1,67 @@
<!doctype html>
<html lang="en" data-theme="{{ $config->get('ui.theme', 'light') }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ $config->get('ui.title', config('app.name') . ' - API Docs') }}</title>
<script src="https://unpkg.com/@stoplight/elements@8.3.4/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements@8.3.4/styles.min.css">
<script>
const originalFetch = window.fetch;
// intercept TryIt requests and add the XSRF-TOKEN header,
// which is necessary for Sanctum cookie-based authentication to work correctly
window.fetch = (url, options) => {
const CSRF_TOKEN_COOKIE_KEY = "XSRF-TOKEN";
const CSRF_TOKEN_HEADER_KEY = "X-XSRF-TOKEN";
const getCookieValue = (key) => {
const cookie = document.cookie.split(';').find((cookie) => cookie.trim().startsWith(key));
return cookie?.split("=")[1];
};
const updateFetchHeaders = (
headers,
headerKey,
headerValue,
) => {
if (headers instanceof Headers) {
headers.set(headerKey, headerValue);
} else if (Array.isArray(headers)) {
headers.push([headerKey, headerValue]);
} else if (headers) {
headers[headerKey] = headerValue;
}
};
const csrfToken = getCookieValue(CSRF_TOKEN_COOKIE_KEY);
if (csrfToken) {
const { headers = new Headers() } = options || {};
updateFetchHeaders(headers, CSRF_TOKEN_HEADER_KEY, decodeURIComponent(csrfToken));
return originalFetch(url, {
...options,
headers,
});
}
return originalFetch(url, options);
};
</script>
</head>
<body style="height: 100vh; overflow-y: hidden">
<elements-api
id="docs"
tryItCredentialsPolicy="{{ $config->get('ui.try_it_credentials_policy', 'include') }}"
router="hash"
@if($config->get('ui.hide_try_it')) hideTryIt="true" @endif
@if($config->get('ui.hide_schemas')) hideSchemas="true" @endif
logo="{{ $config->get('ui.logo') }}"
/>
<script>
(async () => {
const docs = document.getElementById('docs');
docs.apiDescriptionDocument = @json($spec);
})();
</script>
</body>
</html>
+1 -1
View File
@@ -28,7 +28,7 @@ Route::get('/user', function (Request $request) {
})->middleware('auth:sanctum'); })->middleware('auth:sanctum');
// Letter Management Routes // Letter Management Routes
Route::apiResource('letters', LetterController::class); Route::apiResource('letter', LetterController::class);
// File Attachment Routes // File Attachment Routes
Route::get('/lampiran/{id}', [LetterController::class, 'letterLampiran']) Route::get('/lampiran/{id}', [LetterController::class, 'letterLampiran'])