From 1b90bd852c8baeb2c1c92159d8d00d156c789522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Dalmolin?= Date: Tue, 29 Oct 2024 19:02:40 -0300 Subject: [PATCH] Readme updates --- README.md | 146 ++++++++++++++----------- src/Commands/GenerateEnumsCommand.php | 2 +- src/Commands/MakeEnumMethodCommand.php | 2 +- 3 files changed, 82 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index d5055dc..f85164c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Paragon -### A tool for automatically generating typescript/javascript objects and utilities based on their PHP counterparts. - [![Latest Version on Packagist](https://img.shields.io/packagist/v/kirschbaum-development/paragon.svg)](https://packagist.org/packages/kirschbaum-development/paragon) [![Total Downloads](https://img.shields.io/packagist/dt/kirschbaum-development/paragon.svg)](https://packagist.org/packages/kirschbaum-development/paragon) [![Actions Status](https://github.com/kirschbaum-development/paragon/actions/workflows/tests.yml/badge.svg)](https://github.com/kirschbaum-development/paragon/actions) +A tool for automatically generating typescript/javascript objects and utilities based on their PHP counterparts. + ## Requirements | Laravel Version | Paragon Version | @@ -19,21 +19,15 @@ composer require kirschbaum-development/paragon ``` -## TypeScript Enums - -Enums are a fantastic addition to the PHP-verse but are really lame in the TypeScript-verse. However, it can be annoying trying to get those enum values on the -front-end of your project. Are you supposed to pass them as a method when returning a view or perhaps via an API? This -generator solves that problem by scraping your app directory for any and all enums and recreates them as TypeScript -classes so you can import them directly into your Vue, React, or Svelte front-end! +### Enums -The simplest way to get started is to run the following command: +**TL;DR:** Run the following command to generate Typescript (or Javascript) enums from your PHP enums: ```bash -php artisan paragon:generate-enums +php artisan paragon:enum:generate ``` -That's it. Now, wherever you may have had enums in your project, "paragons" or near perfect duplicates of those have -been recreated inside of `resources/js/enums`. Here are some examples of the API: +That's it. Now, wherever you may have had enums in your project, "paragons" or near perfect duplicates of those have been recreated inside of `resources/js/enums`. Here are some examples of the API: ```php PHP API use App\Enums\Status; @@ -57,57 +51,17 @@ Status.tryFrom('active'); As you can see the API is nearly the same, the only difference being how the two languages expect you to access objects! -Let's take a closer look at a simple PHP enum and its generated Typescript code. - -```php -namespace App\Enums; - -enum Status: string -{ - case Active = 'active'; - case Inactive = 'inactive'; -} -``` - -```ts -import Enum from '../Enum.ts'; +**Generating javascript enums** -type StatusDefinition = { - name: string; - value: string; -}; +This package also supports generating Javascript enums. To do so, simply pass the `--javascript` flag to the command: -class Status extends Enum { - protected static items = Object.freeze({ - Active: Object.freeze({ - name: 'Active', - value: 'active', - }), - Inactive: Object.freeze({ - name: 'Inactive', - value: 'inactive', - }), - }); - - public static get Active(): AlarmStatusDefinition { - return this.items['Active']; - } - - public static get Inactive(): AlarmStatusDefinition { - return this.items['Inactive']; - } -} - -export default Status; +```bash +php artisan paragon:enum:generate --javascript ``` -At first glance it appears as though a lot more stuff is happening, but the above generated code allows us to interact -with the enum in a nearly identical way as in PHP. And you may notice the generated TypeScript class extends the `Enum` -class. This gives us some underlying functionality that is available to every enum. - ### Public Methods -A good majority of the time it is useful to use public methods to return a proper human-readable label or some other functionality on an enum. We've got this covered too. Assuming the following method exists on the above `Status` enum: +A good majority of the time it is useful to use public methods to return a proper human-readable label or some other functionality on an enum. Paragon got this covered too. Assuming the following method exists on the above `Status` enum: ```php public function label(): string @@ -117,6 +71,14 @@ public function label(): string self::Inactive => 'Inactive', }; } + +public function color(): string +{ + return match ($this) { + self::Active => 'bg-green-100', + self::Inactive => 'bg-red-100', + }; +} ``` The following method would become accessible using TypeScript: @@ -124,22 +86,19 @@ The following method would become accessible using TypeScript: ```ts Status.Active.label() // 'Active' Status.Inactive.label() // 'Inactive' +Status.Active.color() // 'bg-greed-100' +Status.Inactive.color() // 'bg-red-100' ``` -### Custom Static Methods +### Additional Enum Methods -Traits can also be applied to enums that give the extra functionality via static methods. While this package ignores -static methods as it would be pretty difficult to convert PHP code into TypeScript automatically, we allow you to create -files that Paragon will auto-import for you so you can add the same type of functionality on the front-end! Simply run +While this package ignores static methods on the PHP Enums, we allow you to create additional methods that Paragon will make available for every generated Enum. ```bash -php artisan paragon:enum-method +php artisan paragon:enum:add-method ``` -You can either let it prompt you for a name or pass it in via the CLI `name` argument. This will create a new file at -`resources/js/vendors/paragon/enums`. You are free to do whatever you need inside this file. You have direct access to -`this.items` which allows you to interact with the enum cases in whatever way you need. Just keep in mind that because -the items are "frozen", you can't mutate them directly. +This will create a new file at `resources/js/vendors/paragon/enums` containing a method. You are free to do whatever you need inside this file. You have direct access to `this.items` which allows you to interact with the enum cases in whatever way you need. Just keep in mind that because the items are "frozen", you can't mutate them directly. An example would be to have a method that automatically generates a select list from your Enum. ### Ignoring Enums Or Public Methods @@ -202,3 +161,58 @@ export default defineConfig({ ], }); ``` + +## Technical Details 🤓 + +Enums are a fantastic addition to the PHP-verse but are really lame in the TypeScript-verse. However, it can be annoying trying to get those enum values on the +front-end of your project. Are you supposed to pass them as a method when returning a view or perhaps via an API? This +generator solves that problem by scraping your app directory for any and all enums and recreates them as TypeScript +classes so you can import them directly into your Vue, React, or Svelte front-end! + +Let's take a closer look at a simple PHP enum and its generated Typescript code. + +```php +namespace App\Enums; + +enum Status: string +{ + case Active = 'active'; + case Inactive = 'inactive'; +} +``` + +```ts +import Enum from '../Enum.ts'; + +type StatusDefinition = { + name: string; + value: string; +}; + +class Status extends Enum { + protected static items = Object.freeze({ + Active: Object.freeze({ + name: 'Active', + value: 'active', + }), + Inactive: Object.freeze({ + name: 'Inactive', + value: 'inactive', + }), + }); + + public static get Active(): AlarmStatusDefinition { + return this.items['Active']; + } + + public static get Inactive(): AlarmStatusDefinition { + return this.items['Inactive']; + } +} + +export default Status; +``` + +At first glance it appears as though a lot more stuff is happening, but the above generated code allows us to interact +with the enum in a nearly identical way as in PHP. And you may notice the generated TypeScript class extends the `Enum` +class. This gives us some underlying functionality that is available to every enum. \ No newline at end of file diff --git a/src/Commands/GenerateEnumsCommand.php b/src/Commands/GenerateEnumsCommand.php index a09e8da..3d6d0ed 100644 --- a/src/Commands/GenerateEnumsCommand.php +++ b/src/Commands/GenerateEnumsCommand.php @@ -19,7 +19,7 @@ use Symfony\Component\Console\Input\InputOption; use UnitEnum; -#[AsCommand(name: 'paragon:generate-enums', description: 'Generate Typescript versions of existing PHP enums')] +#[AsCommand(name: 'paragon:enum:generate', description: 'Generate Typescript versions of existing PHP enums')] class GenerateEnumsCommand extends Command { /** diff --git a/src/Commands/MakeEnumMethodCommand.php b/src/Commands/MakeEnumMethodCommand.php index f0d9c94..4be7cd5 100644 --- a/src/Commands/MakeEnumMethodCommand.php +++ b/src/Commands/MakeEnumMethodCommand.php @@ -15,7 +15,7 @@ use function Laravel\Prompts\text; -#[AsCommand(name: 'paragon:enum-method', description: 'Create a new typescript enum method')] +#[AsCommand(name: 'paragon:enum:add-method', description: 'Create a new global typescript method to be applied to every generated enum')] class MakeEnumMethodCommand extends GeneratorCommand { /**