From e0cdfaf0932e6fe47e531b25188a96491ab6b31f Mon Sep 17 00:00:00 2001 From: Leandro Pedrosa Rodrigues Date: Fri, 9 Feb 2024 23:05:44 -0300 Subject: [PATCH] docs(readme): change all documentation in readme, and add contributing documentation --- CONTRIBUTING.md | 74 ++++++++++++++++++ README.md | 198 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 226 insertions(+), 46 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9a73277 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contribution/Development + +This section talks about how to contribute and develop in the package. + +## Index + +- [Contribution](#contribution) +- [Development](#development) + - [Code Analysis](#code-analysis) + - [Hooks](#hooks) + +## Contribution + +To contribute to the evolution of the project it is necessary to follow some steps: + +- To create a branch, follow the `[PREFIX]` pattern. The accepted prefixes are those listed below: + - `hotfix`: To fix a production bug in the application; + - `fix`: To fix a bug in the application; + - `feature`: To insert a new feature into the application; + - `build`: Changes that affect the build system or external dependencies (examples: composer, dockerfile, dockercompose); + - `ci`: Changes to CI configuration files and scripts (examples: gitlab-ci, sonarqube, lints, security); + - `docs`: Only modification of documentation (examples: Readme, Changelog); + - `performance`: A code change that improves performance (examples: response time, memory consumption); + - `refactor`: A code change that does not fix a bug or add a feature; + - `style`: Changes that do not affect the meaning of the code (examples: white space, formatting, lint, missing semicolon, etc.); + - `test`: Adding missing tests or correcting existing tests; + - `chore`: When you do everything and a little in the branch (write documentation, format, add tests, clean up useless code, etc.) + +## Development + +### Code Analysis + +A code analyzer is very useful so that we can program in a certain way following the recommendations of each analyzer. + +Currently in the project there is 1 analyzer: + +- PHP Code Sniffer + +#### Linter + +This project uses the `PhpCsFixer` linter. + +There are several scripts in `composer.json` for Code Sniffer: + +- `lint-diff`: Runs the linter only for files that have been modified +- `lint-diff-staged`: Runs the linter for files that have been modified and are in the `staged` section of git +- `lint-fix`: Runs the linter and fixes only the files that have been modified +- `lint-fix-staged`: Runs the linter and fixes the files that have been modified and are in the `staged` section of git + +> The configuration file is in the root of the project called `.php-cs-fixer.php` + +#### Php Stan + +This project makes use of the [*phpstan*](https://phpstan.org/) package, which performs static analysis on the code, validating quality rules. It is possible to find errors in the code without executing it. + +There is the script in `composer.json` to perform analysis: + +- `analyse`: Analyzes according to `phpstan` rules. + +> To look at other available options, see the [*PHPStan*](https://phpstan.org/config-reference) documentation + +### Hooks + +There are three git hooks: + +To activate them, just type the following command: + +``` +npm run prepare +``` + +- **commit-msg**: It is checked when you finish committing to check if the message complies with the rules. +- **pre-commit**: Before each commit, it is checked whether the files that are staged in git comply with the rules +- **prepare-commit-msg**: Prepares the commit to comply with the recommendations diff --git a/README.md b/README.md index 375da96..c7badd2 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,181 @@ -# :package_description - -[![Latest Version on Packagist](https://img.shields.io/packagist/v/:vendor_slug/:package_slug.svg?style=flat-square)](https://packagist.org/packages/:vendor_slug/:package_slug) -[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/:vendor_slug/:package_slug/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/:vendor_slug/:package_slug/actions?query=workflow%3Arun-tests+branch%3Amain) -[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/:vendor_slug/:package_slug/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/:vendor_slug/:package_slug/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) -[![Total Downloads](https://img.shields.io/packagist/dt/:vendor_slug/:package_slug.svg?style=flat-square)](https://packagist.org/packages/:vendor_slug/:package_slug) - ---- -This repo can be used to scaffold a Laravel package. Follow these steps to get started: +# Laravel Api Problem + +[![Latest Version on Packagist](https://img.shields.io/packagist/v/pedrosalpr/laravel-api-problem.svg?style=flat-square)](https://packagist.org/packages/pedrosalpr/laravel-api-problem) +[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/pedrosalpr/laravel-api-problem/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/pedrosalpr/laravel-api-problem/actions?query=workflow%3Arun-tests+branch%3Amain) +[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/pedrosalpr/laravel-api-problem/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/pedrosalpr/laravel-api-problem/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) +[![Total Downloads](https://img.shields.io/packagist/dt/pedrosalpr/laravel-api-problem.svg?style=flat-square)](https://packagist.org/packages/pedrosalpr/laravel-api-problem) + +The objective of this package is to facilitate error outputs from API requests in accordance with the [RFC 9457](https://datatracker.ietf.org/doc/rfc9457/) standard. + +It transforms error outputs into json format with the following characteristics: +- header: + - `Content-Type: application/problem+json` +- response: + - `type`: URI that identifies the type of error that occured, for example `https://example.com/validation-error`. + - `title`: Human-readable identifier, usually the same type field should have the same title field alongside. An example would be something like Form validation failed. + - `status`: A copy of the HTTP status code. + - `detail`: More information about the specific problem, and if it's appropriate also steps to correct it. For example information about a form validation problem Username is already taken, please choose a different username. + - `instance`: An identifier for this specific occurence, which may not be useful to the client but may be included in a bug report for example. + - **Additional fields**: Any fields may be added to give additional information, and consuming clients are expected to ignore any that they don't have specific support for. + - `timestamp`: (RFC 9457 enhancement): A timestamp indicating when the problem was generated. This helps in logging and tracing the error, especially in systems where timing is critical. + +Example: + +Server Response: +```bash +HTTP/1.1 422 Unprocessable Entity +Content-Type: application/problem+json +Content-Language: en +{ + "status": 422, + "type": "https://example.test/validation-error", + "title": "Form validation failed", + "detail": "One or more fields have validation errors. Please check and try again.", + "instance": "http://example.test/api/test/1", + "timestamp": "2024-02-09T11:55:51.252968Z", + "errors": [ + { + "name": "username", + "reason": "Username is already taken." + }, + { + "name": "email", + "reason": "Email format is invalid." + } + ] +} +``` -1. Press the "Use this template" button at the top of this repo to create a new repo with the contents of this skeleton. -2. Run "php ./configure.php" to run a script that will replace all placeholders throughout all the files. -3. Have fun creating your package. -4. If you need help creating a package, consider picking up our Laravel Package Training video course. ---- - -This is where your description should go. Limit it to a paragraph or two. Consider adding a small example. +## Installation -## Support us +You can install the package via composer: -[](https://spatie.be/github-ad-click/:package_name) +```bash +composer require pedrosalpr/laravel-api-problem +``` -We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). +> Only works in Laravel 9 and 10. -We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). +## Usage -## Installation +### Default Mode -You can install the package via composer: +To use it, just go to the `register` method within `Exceptions\Handler.php` and add the following code: -```bash -composer require :vendor_slug/:package_slug +```php +use Pedrosalpr\LaravelApiProblem\LaravelApiProblem; + +public function register(): void +{ + ... + + $this->renderable(function (\Throwable $e, Request $request) { + if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) { + $apiProblem = new LaravelApiProblem($e, $request); + return $apiProblem->render(); + } + }); +} ``` -You can publish and run the migrations with: +If you want to debug, just add the following line before the return: -```bash -php artisan vendor:publish --tag=":package_slug-migrations" -php artisan migrate -``` +`dd($apiProblem->toDebuggableArray());` -You can publish the config file with: +#### Creating Exceptions in the Api Problem pattern -```bash -php artisan vendor:publish --tag=":package_slug-config" -``` +There is the possibility of creating exceptions that extend `LaravelApiProblemException`. + +This already makes it easier to transform the exception into the Api Problem pattern. + +To do this, simply run the following command: -This is the contents of the published config file: +`php artisan laravel-api-problem:exception {name}` + +For example: + +`php artisan laravel-api-problem:exception DummyException` + +This creates a class exception inside `Exceptions\ApiProblem`; ```php -return [ -]; + $this->dummy(), + default => parent::__construct($exception, $request) + }; + } + + protected function dummy() + { + $extensions = [ + 'errors' => "Dummy", + ]; + $this->apiProblem = new LaravelHttpApiProblem( + Response::HTTP_I_AM_A_TEAPOT, + $this->exception->getMessage(), + $this->getUriInstance(), + $extensions + ); + } +} ``` -## Usage +And within the match, add the names of the exceptions classes with their respective methods, such as `dummy()`. + +And in the `Handler.php` file replace the `LaravelApiProblem` object instance to `DummyApiProblem`. ```php -$variable = new VendorName\Skeleton(); -echo $variable->echoPhrase('Hello, VendorName!'); + $this->renderable(function (\Throwable $e, Request $request) { + if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) { + $apiProblem = new DummyApiProblem($e, $request); + return $apiProblem->render(); + } + }); ``` ## Testing -```bash -composer test -``` +TODO ## Changelog @@ -85,7 +191,7 @@ Please review [our security policy](../../security/policy) on how to report secu ## Credits -- [:author_name](https://github.com/:author_username) +- [Leandro Pedrosa Rodrigues](https://github.com/pedrosalpr) - [All Contributors](../../contributors) ## License