Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 45 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,35 @@ class MySuperClass {

This provides you full type safety without any additional code. Your PHP code is fully analysable by PHPStan.

### Utility Types

There are a few Utility Types that are provided to make your life easier. They ship with a PHP stan extension, so that
you still fully enjoy type safety.

Following types are provided:

- `BrandedString<"brandName">`: Emits a branded string for the FE. Useful for IDs and tokens.
- `BrandedInt<"brandName">`: Emits a branded int for the FE.
- `DateTimeString<?"format">`: Accepts a dateTime string in a speficic Format and casts to DateTimeImmutable. It is
converted to DateTimeImmutable in PHPStan. Meaning, the FN will get a DateTimeImmutable and expects a
DateTimeImmutable as return value.
- `Pick<object|array{}>`: Allows you to pick a subset of properties from an object or array. Useful for output types.
- `Omit<object|array{}>`: Allows you to omit a subset of properties from an object or array.

### Enum Handling

Enums are transformed to string literals (Enum::Value->name) in the generated code. Even for backed enum.
This allows for consistent handling of enums in the FE and BE. This applies to both input and output types.

```
enum MyEnum: string {
case A = "something";
case B = "something else";
}

=> "A" | "B"
```

### Laravel Default Integration

We provide a first-party integration with laravel. By default, we discover remotely called functions in
Expand All @@ -84,7 +113,22 @@ options. This lets you configure how exceptions are mapped to different buckets.
Additionally, we provide code generation out of the box for laravel and your typescript project. To do so, run
`php artisan operations:codegen frontend/directory`, this will directly generate you a good starter kit for operations,
so that ou can seamlessly bridge the gap between your FE and BE. See more below for detailed codegen examples and
customizations, including writing your very own code generation plugin.
customizations, including writing your very own code generation plugin.

#### Optimizing for production

As described below, for better performance, the type parsing can be optimized and run ahead of time once. This will produce
a file that can be included in your project.

For laravel you can run:
```
php artisan operations:codegen
php artisan operations:clear-optimize

// OR
php artisan optimize
php artisan optimize:clear
```

## Type Parsing

Expand Down Expand Up @@ -157,49 +201,3 @@ $registry = require 'asts.php';
$ast = $registry->get('MyClass@methodname@input');
$otherAst = $registry->get('MyClass@methodname@output');
```

## Extending the Parser

The parser is quite simple and can be extended to support more specific types with custom parsers.

Ordering matters. The first parser that can parse the type will be used. Therefore, be careful if you prepend or append
parsers to the default parsers. For example, the datetime parser parses any DateTime interface. If you need custom logic
you need to prepend your custom parser.

```php
use Le0daniel\PhpTsBindings\Contracts\Parser;
use Le0daniel\PhpTsBindings\Parser\Definition\Token;
use Le0daniel\PhpTsBindings\Contracts\NodeInterface;
use Le0daniel\PhpTsBindings\Parser\TypeParser;

class CarbonDateTimeParser implements Parser {

public function canParse(string $fullyQualifiedClassName, Token $token): bool {
return is_a($fullyQualifiedClassName, Carbon::class, true);
}

public function parse(string $fullyQualifiedClassName, Token $token, TypeParser $parser): NodeInterface {
return new CarbonLeafNode();
}
}

$parser = new TypeParser(
parsers: TypeParser::getDefaultParsers(
prepend: [
new CarbonDateTimeParser(),
];
),
);
```

By default, the parser uses the following parsers:

- new EnumCasesParser(): Takes an EnumClass and expects a string literal as input
- new DateTimeParser(): Takes a DateTime string, parses it as a DateTime object and serializes it as a string
- new CustomClassParser(): Takes a custom class and creates an object struct for input/output.

If you don't want to use any of the default parsers, you can pass an empty array to the constructor of TypeParser.

```php
new TypeParser(parsers: []);
```
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Library to create type bindings between PHP8 and TS, supporting parsing, serialization and emitting of TS types for PHP objects/input strongly typed",
"type": "library",
"require": {
"php": "^8.4"
"php": "^8.5"
},
"require-dev": {
"pestphp/pest": "4.x-dev",
Expand Down
Loading