The CodeBuds TypeScript Generator Bundle is a Symfony bundle designed to improve developer experience by automatically generating TypeScript files based on PHP files. This bundle scans your PHP entities and creates corresponding TypeScript interfaces and types. It can also scan the PHP Enums to generate the equivalent TypeScript Enums.
To install the bundle, use composer:
composer require codebuds/ts-generator-bundle --dev
This bundle provides three configurable parameters with default values:
You can overwrite these default configurations by creating a YAML file inside your config directory:
#config/generate_ts.yaml
generate_ts:
namespace: 'App\CustomNamespace\'
type_output_directory: '%kernel.project_dir%/custom/types'
interface_output_directory: '%kernel.project_dir%/custom/interfaces'
enum_output_directory: '%kernel.project_dir%/custom/enums'
entity_input_directory: '%kernel.project_dir%/custom/Entity'
enum_input_directory: '%kernel.project_dir%/custom/Enum'
To generate TypeScript interfaces, run the following command:
php bin/console codebuds:generate-ts:interfaces --force
To generate TypeScript types, run the following command:
php bin/console codebuds:generate-ts:types --force
Here is the output when the command generates new interfaces:
Generate TypeScript Interfaces
==============================
0/3 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
[INFO] /srv/app/assets/interfaces/Sub1/SubSub1/SubSubEntity2.ts generated for /srv/app/src/Entity/Sub1/SubSub1/SubSubEntity2.php
[INFO] /srv/app/assets/interfaces/Sub2/SubEntity2.ts generated for /srv/app/src/Entity/Sub2/SubEntity2.php
[INFO] /srv/app/assets/interfaces/Root.ts generated for /srv/app/src/Entity/Root.php
3/3 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
If nothing changes in the output you will get
Generate TypeScript Interfaces
==============================
0/3 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
! [NOTE] No changes for /srv/app/assets/interfaces/Sub1/SubSub1/SubSubEntity2.ts
! [NOTE] No changes for /srv/app/assets/interfaces/Sub2/SubEntity2.ts
! [NOTE] No changes for /srv/app/assets/interfaces/Root.ts
3/3 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
You can overwrite the configured values for the namespace, inputDirectory and outputDirectory when running the commande :
codebuds:generate-ts:interfaces --namespace=App/Test/ --inputDirectory=vendor/codebuds/generate-ts-bundle/src/Tests/data --outputDirectory=vendor/codebuds/generate-ts-bundle/src/Tests/output --force
The script will try to match the types. If you have an entity that has relations it will map those to the TypeScript Interfaces.
With an Entity like :
<?php
namespace App\Test;
use App\Repository\RootRepository;
use App\Test\Sub1\SubEntity1;
use App\Test\Sub1\SubSub1\SubSubEntity1;
use App\Test\Sub1\SubSub1\SubSubEntity2;
use App\Test\Sub2\SubEntity2;
use DateTimeInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RootRepository::class)]
class Root
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne]
private ?SubSubEntity1 $subSubEntity1 = null;
#[ORM\OneToMany(mappedBy: 'root', targetEntity: SubSubEntity2::class)]
private Collection $subSubEntity2;
#[ORM\ManyToMany(targetEntity: SubEntity1::class, inversedBy: 'roots')]
private Collection $subEntity1;
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
private ?SubEntity2 $subEntity2 = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?DateTimeInterface $datetime = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $text = null;
}
The interface output will be :
import {SubSubEntity1} from "./Sub1/SubSub1/SubSubEntity1"
import {SubSubEntity2} from "./Sub1/SubSub1/SubSubEntity2"
import {SubEntity1} from "./Sub1/SubEntity1"
import {SubEntity2} from "./Sub2/SubEntity2"
export interface Root {
id: number;
subSubEntity1: SubSubEntity1;
subSubEntity2: Array<SubSubEntity2>;
subEntity1: Array<SubEntity1>;
subEntity2: SubEntity2;
datetime: Date;
text: string;
}
The type output will be :
import {SubSubEntity1} from "./Sub1/SubSub1/SubSubEntity1"
import {SubSubEntity2} from "./Sub1/SubSub1/SubSubEntity2"
import {SubEntity1} from "./Sub1/SubEntity1"
import {SubEntity2} from "./Sub2/SubEntity2"
export type Root = {
id: number;
subSubEntity1: SubSubEntity1;
subSubEntity2: Array<SubSubEntity2>;
subEntity1: Array<SubEntity1>;
subEntity2: SubEntity2;
datetime: Date;
text: string;
}
To generate TypeScript enums, run the following command:
php bin/console codebuds:generate-ts:enums --force
This works for simple enums :
<?php
namespace App\Test\Enum;
enum NotBacked
{
case First;
case Second;
}
Turns into
export enum NotBacked {
First,
Second,
}
And for backed enums :
<?php
namespace App\Test\Enum;
enum BackedString: string
{
case String = 'String';
case Another = 'Something';
}
Turns into :
export enum BackedString {
String = "String",
Another = "Something",
}
If you want to contribute to this project, feel free to open issues and submit pull requests.
This bundle is open-source software licensed under the MIT license.
How can I help you explore Laravel packages today?