Coder Social home page Coder Social logo

laravel-typegen's Introduction

Laravel Typegen

Table of contents

Features

  • Generate types from Laravel's Models
  • Support Relationhips
  • Support Enum (from PHP8.1)
  • Generate types from Laravel's Form Requests
  • Generate types for ziggy (Routing)
  • Provide useful types for Laravel (e.g. pagination, etc.)

Supported Versions

This library supports the following versions:

  • Laravel 9.x and 10.x
  • TypeScript 5.0 and above

Installation

$ npm install -D @7nohe/laravel-typegen

Laravel Typegen may require installing doctrine/dbal via Composer in order to execute the php artisan model:show command internally.

$ composer require doctrine/dbal

Usage

Edit package.json

{
    "scripts": {
        "typegen": "laravel-typegen"
    },
}
$ npm run typegen

Enum Support

We also support php8.1 enums.

<!-- app/Enums/GenderType.php -->
<?php

namespace App\Enums;

enum GenderType: string
{
    case Male = 'Male';
    case Female = 'Female';
    case Other = 'Other';
}

Then, cast model attributes to enums.

<!-- app/Models/User.php -->
<?php

namespace App\Models;
use App\Enums\GenderType;

class User extends Authenticatable
{
    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'gender'            => GenderType::class,
    ];
}

This library will generate the following TypeScript types:

export type User = {
    id: number;
    name: string;
    email: string;
    gender: GenderType;
    email_verified_at?: string;
    created_at?: string;
    updated_at?: string;
    posts?: Post[];
};
export enum GenderType {
    Male = "Male",
    Female = "Female",
    Other = "Other"
}

Laravel Enum Support

If you use Laravel Enum, use the option --laravel-enum.

{
    "scripts": {
        "typegen": "laravel-typegen --laravel-enum"
    },
}

Use strongly typed route() function for ziggy

Running the laravel-typegen command with the --ziggy option will generate route.d.ts.

It helps typing the route() function.

{
    "scripts": {
        "typegen": "laravel-typegen --ziggy"
    },
}

For example, define the following routes

// routes/web.php
Route::resource('posts', PostsController::class);
$ php artisan route:list
GET|HEAD posts/{post} posts.show › PostsController@show

Parameters will be checked strictly based on the route name.

// in your TypeScript code

// OK
route('posts.show', { post: post.id })

// Error
route('posts.show', { id: post.id })

If you have created a project using the --typescript option of Laravel Breeze, you need to delete the declaration for the route() function in resources/js/types/global.d.ts.

import { PageProps as InertiaPageProps } from '@inertiajs/core';
import { AxiosInstance } from 'axios';
 import ziggyRoute, { Config as ZiggyConfig } from 'ziggy-js';
import { PageProps as AppPageProps } from './';

declare global {
    interface Window {
        axios: AxiosInstance;
    }

    var route: typeof ziggyRoute;
    var Ziggy: ZiggyConfig;
}

- declare module 'vue' {
-     interface ComponentCustomProperties {
-        route: typeof ziggyRoute;
-     }
- }

declare module '@inertiajs/core' {
    interface PageProps extends InertiaPageProps, AppPageProps {}
}

Useful types for Laravel

We provide useful types for Laravel (especially for Inertia).

For example, to return a paginated Inertia response in DashboardController, you can write the following

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Inertia\Inertia;

class DashboardController extends Controller
{
    public function __invoke()
    {
        $users = User::latest('id')->paginate(5);
        return Inertia::render(
            'Dashboard',
            [
                'users' => $users
            ]
        );
    }
}

You can import types already defined by Laravel Typegen.

<!-- Dashboard.vue -->
<script setup lang="ts">
import { Paginate } from '@7nohe/laravel-typegen';
import { User } from '@/types/model'; // generated types

defineProps<{ users: Paginate<User> }>();

</script>
<template>
    <div>
        <ul>
            <li v-for="user in users.data">- {{ user.name }}({{ user.email }})</li>
        </ul>
        <div class="flex justify-center mt-4 space-x-4">
            <Link v-for="(link, key) in users.links" :key="key" :href="link.url ?? '#'" v-html="link.label" />
        </div>
    </div>
</template>

Form Request types

You can generate types from Laravel's Form Request by executing the command with the --form-requests option.

If you have the Form Request class as shown below:

<?php

namespace App\Http\Requests;

use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class ProfileUpdateRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            'name' => ['string', 'max:255'],
            'email' => ['email', 'max:255', Rule::unique(User::class)->ignore($this->user()->id)],
        ];
    }
}

The corresponding TypeScript types will be automatically generated as follows:

// formRequests.ts
export type ProfileUpdateRequest = {
    name?: string;
    email?: string;
};

By using these generated types in combination with HTTP Client libraries like Axios, you can write more type-safe code.

Available options

Usage: laravel-typegen [options]

Generate TypeScript types from your Laravel code

Options:
  -V, --version         output the version number
  -o, --output <value>  Output directory (default: "resources/js/types")
  --laravel-enum        Use Laravel Enum (default: false)
  --enum-path <value>   Path to enum files (default: "app/Enums")
  --model-path <value>  Path to model files (default: "app/Models")
  -z, --ziggy           Generate types for ziggy (default: false)
  --vendor-routes       Include routes defined by vendor packages (default: false)
  --ignore-route-dts    Ignore generating route.d.ts (default: false)
  --form-request        Generate types for FormRequests (default: false)
  -h, --help            display help for command

Development

Setup example project

$ cd examples/laravel10-app
$ cp .env.example .env
$ docker run --rm \
    -u "$(id -u):$(id -g)" \
    -v "$(pwd):/var/www/html" \
    -w /var/www/html \
    laravelsail/php81-composer:latest \
    composer install --ignore-platform-reqs
$ ./vendor/bin/sail up -d
$ ./vendor/bin/sail php artisan key:generate
$ ./vendor/bin/sail php artisan migrate --seed
$ ./vendor/bin/sail npm install

Debug

$ pnpm install
$ sh debug.sh

License

MIT

laravel-typegen's People

Contributors

4lun avatar 7nohe avatar naoyamiyagawa avatar watarunishimura avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

laravel-typegen's Issues

Generate the props type for a Page from a Controller action

Let's assume we have a PostsController like the following in a Laravel project:

class PostsController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return Inertia::render(
            'Posts/Index',
            [
                'posts' => $posts
            ]
        );
    }
}

This code generates a props type called PostsIndexProps, which can be used as follows:

<script setup lang="ts">
import { PostsIndexProps } from '@/types/props';
const page = usePage<PostsIndexProps>()
</script>

Option to use objects instead of enums

use

export const GenderType = {
    Male: "Male",
    Female: "Female",
    Other: "Other"
} as const

instead of

export enum GenderType {
    Male = "Male",
    Female = "Female",
    Other = "Other"
}

feat: support generate types via sail and outside of docker container

Summary

When generating, utilize sail artisan instead of php artisan outside of the Sail container to echo model JSON. Within the Docker container, we can invoke php artisan model:show if Sail is being used. However, outside the Docker container, calling artisan model:show via PHP is not possible; we need to use sail.

Could I try this issue? If it's ok, I will create PR.

Solution

  • add sail option
  • if sail option is enabled, use sail artisan instead of php artisan

Error on running npm run typegen

Hey hey, this is personal project I haven't touch for a while, and now I'm getting this error when trying to run the command. Any idea what could be happening?
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.