Giter Club home page Giter Club logo

kiwilan / typescriptable-laravel Goto Github PK

View Code? Open in Web Editor NEW
19.0 3.0 2.0 887 KB

PHP package for Laravel to type Eloquent models, routes, Spatie Settings with autogenerated TypeScript. If you want to use some helpers with Inertia, you can install associated NPM package.

Home Page: https://packagist.org/packages/kiwilan/typescriptable-laravel

License: MIT License

PHP 68.28% TypeScript 31.48% JavaScript 0.24%
eloquent laravel models php ts typescript inertia routes vue settings

typescriptable-laravel's Introduction

Typescriptable for Laravel

Banner with printer shop picture in background and Typescriptable Laravel title

php version downloads license codecov tests

laravel npm

PHP package for Laravel to type Eloquent models, routes, Spatie Settings with autogenerated TypeScript.

If you want to use some helpers with Inertia, you can install associated NPM package.

Note

Features

  • ๐Ÿ’ฝ All Laravel databases are supported: MySQL, PostgreSQL, SQLite, SQL Server
  • ๐Ÿ’ฌ Generate TS types for Eloquent models
  • ๐Ÿ‘ญ Generate TS types for Eloquent relations
  • ๐Ÿช„ Generate TS types for casts (include native enum support)
  • ๐Ÿ“… Generate TS types for dates
  • ๐Ÿ“ Generate TS types for appends with accessors
    • Partial for Illuminate\Database\Eloquent\Casts\Attribute
    • Old way get*Attribute methods are totally supported
  • #๏ธโƒฃ Generate TS types for counts
  • ๐Ÿ“– Can generate pagination TS types for Laravel pagination
  • ๐Ÿ’พ Can generate simple PHP classes from Eloquent models
  • โš™๏ธ Generate TS types for spatie/laravel-settings
  • ๐Ÿ›ฃ Generate TS types for Laravel routes
  • โœ… Multiple commands to generate types
    • php artisan typescriptable for models, settings and routes (safe even if you don't use all)
    • php artisan typescriptable:models for Eloquent models
    • php artisan typescriptable:settings for spatie/laravel-settings
    • php artisan typescriptable:routes for Laravel routes

Roadmap

Installation

This version requires PHP 8.2+ and supports Laravel 11.

Warning

Laravel 11 dropped Doctrine DBAL. For previous Laravel versions, you can use 1.12.03 version.

Version L9 L10 L11
1.12.03 โœ… โœ… โŒ
2.0.0 โŒ โŒ โœ…

You can install the package via composer:

With Laravel v11+ and PHP 8.2

composer require kiwilan/typescriptable-laravel

With Laravel v9-10 and PHP 8.1

composer require kiwilan/typescriptable-laravel:1.12.03

About TypeScript

If you want to use .d.ts files, you need to use TypeScript in your Laravel project, you have to create a tsconfig.json file and add .d.ts paths in compilerOptions.types:

Note

If you change paths into config or with options, adapt paths.

{
    "compilerOptions": {
        "typeRoots": ["./node_modules/@types", "resources/**/*.d.ts"]
    },
    "include": ["resources/**/*.d.ts"]
}

Configuration

You can publish the config file

php artisan vendor:publish --tag="typescriptable-config"

Usage

php artisan typescriptable

With options:

  • --M|models: Generate Models types.
  • --R|routes: Generate Routes types.
  • --S|settings: Generate Settings types.

Eloquent Models

Generate resources/js/types-models.d.ts file with all models types.

php artisan typescriptable:models

With options:

  • --M|models-path: Path to models directory.
  • --O|output-path: Path to output.
  • --P|php-path: Path to output PHP classes, if null will not print PHP classes.

Spatie Settings

If you use spatie/laravel-settings, you can generate resources/js/types-settings.d.ts file with all settings types.

php artisan typescriptable:settings

With options:

  • --S|settings-path: Path to settings directory.
  • --O|output-path: Path to output.

Routes

Generate resources/js/types-routes.d.ts file with all routes types and resources/js/routes.ts for routes references.

php artisan typescriptable:routes

With options:

  • --R|routes-path: Path to routes directory.
  • --O|output-path: Path to output.

Troubleshooting

Database prefix

If you have a database prefix, you can add it in config/typescriptable.php file with DB_PREFIX env variable.

return [
    'database_prefix' => env('DB_PREFIX', ''),
];

Or you can use DB_PREFIX into config/database.php file.

'prefix' => env('DB_PREFIX', ''),

Two configs works.

Override models

kiwilan/typescriptable-laravel will cover many cases, but if you want to override some models, you can just create a type like resources/js/types/index.ts and extends Model type.

interface BookAdvanced extends App.Models.Book {
    pivot: {
        created_at: string;
        updated_at: string;
    };
}

And you can import custom type in your code when you need to use advanced type.

Examples

Check examples documentation.

Testing

Create a .env file with your database configuration

cp .env.example .env

And you can run tests

composer test

Docker database

Note

To install this on M1 Mac, you need to enable Use Rosetta for x86/amd64 emulation on Apple Silicon in Docker preferences.

To install MySQL with Docker

docker run --name mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    -e MYSQL_USER=testing \
    -e MYSQL_PASSWORD=testing \
    -e MYSQL_DATABASE=testing \
    -p 3306:3306 \
    -d \
    mysql:8.0

To install PostgreSQL with Docker

docker run --name postgresql \
    -e POSTGRES_USER=testing \
    -e POSTGRES_PASSWORD=testing \
    -e POSTGRES_DB=testing \
    -p 5432:5432 \
    -d \
    postgres:15.4

To install SQL Server with Docker

Warning

If you have an error like this: "An invalid attribute was designated on the PDO object", you have to update msphpsql driver. Check laravel/framework#47937 for more information.

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=12345OHdf%e" \
  -p 1433:1433 \
  --name sqlserver \
  --hostname sqlserver \
  -d \
  mcr.microsoft.com/mssql/server:2022-latest

Changelog

Please see CHANGELOG for more information on what has changed recently.

Credits

License

The MIT License (MIT). Please see License File for more information.

typescriptable-laravel's People

Contributors

dependabot[bot] avatar ewilan-riviere avatar github-actions[bot] avatar

Stargazers

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

Watchers

 avatar  avatar  avatar

typescriptable-laravel's Issues

[Bug]: Generating models error when using DB_PREFIX

What happened?

Just using prefix for my databases tables by setting in the config/database.php (e.g. sv_).

Then, when trying to run the command:

php artisan typescriptable:models

I get this errors:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'survey.responses' doesn't exist (Connection: mysql, SQL: SHOW COLUMNS FROM responses)

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:822
    818โ–•                     $this->getName(), $query, $this->prepareBindings($bindings), $e
    819โ–•                 );
    820โ–•             }
    821โ–• 
  โžœ 822โ–•             throw new QueryException(
    823โ–•                 $this->getName(), $query, $this->prepareBindings($bindings), $e
    824โ–•             );
    825โ–•         }
    826โ–•     }

  i   A table was not found: You might have forgotten to run your database migrations. 
      https://laravel.com/docs/master/migrations#running-migrations

      +27 vendor frames 

  28  artisan:35
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

How to reproduce the bug

  1. Setting the database prefix
  2. Install the package
  3. Try to generate TS types for models
  4. Error table not found!

Package Version

^1.11

PHP Version

8.2.10

Which operating systems does with happen with?

macOS

Notes

I was try to publish the package configuration and I don't found any related config to settings the database tables prefix.

[Bug]: linting problem

What happened?

I have problems with this line:

/* eslint-disable eslint-comments/no-unlimited-disable */

and when i run my linter I get


/var/www/html/resources/js/types/models.d.ts
  1:1  error  Definition for rule 'eslint-comments/no-unlimited-disable' was not found  eslint-comments/no-unlimited-disable

โœ– 1 problem (1 error, 0 warnings)

If I do what is on this page I get

/var/www/html/resources/js/types/models.d.ts
  1:19  error  Requires 'eslint-enable' directive for 'eslint-comments/no-unlimited-disable'  eslint-comments/disable-enable-pair
  2:0   error  Requires 'eslint-enable' directive                                             eslint-comments/disable-enable-pair

How to reproduce the bug

Just install the package

Package Version

latest

PHP Version

8.1.0

Which operating systems does with happen with?

Windows

Notes

No response

[Bug]: Package incompatible with spatie/laravel-permissions

What happened?

I get this error when I run sail artisan typescriptable:models

Kiwilan\Typescriptable\Typed\Eloquent\Utils\EloquentProperty::__construct(): Argument #3 ($type) must be of type string, null given, called in /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/EloquentItem.php on line 135 {"exception":"[object] (TypeError(code: 0): Kiwilan\\Typescriptable\\Typed\\Eloquent\\Utils\\EloquentProperty::__construct(): Argument #3 ($type) must be of type string, null given, called in /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/EloquentItem.php on line 135 at /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/Utils/EloquentProperty.php:10)
[stacktrace]
#0 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/EloquentItem.php(135): Kiwilan\\Typescriptable\\Typed\\Eloquent\\Utils\\EloquentProperty->__construct()
#1 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/EloquentItem.php(63): Kiwilan\\Typescriptable\\Typed\\Eloquent\\EloquentItem->setProperties()
#2 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Utils/ClassItem.php(42): Kiwilan\\Typescriptable\\Typed\\Eloquent\\EloquentItem::make()
#3 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/Utils/ClassItem.php(68): Kiwilan\\Typescriptable\\Typed\\Utils\\ClassItem::make()
#4 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typed/EloquentType.php(44): Kiwilan\\Typescriptable\\Typed\\Utils\\ClassItem::list()
#5 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Typescriptable.php(13): Kiwilan\\Typescriptable\\Typed\\EloquentType::make()
#6 /var/www/html/vendor/kiwilan/typescriptable-laravel/src/Commands/TypescriptableModelsCommand.php(28): Kiwilan\\Typescriptable\\Typescriptable::models()
#7 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Kiwilan\\Typescriptable\\Commands\\TypescriptableModelsCommand->handle()
#8 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod()
#11 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
#12 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\\Container\\Container->call()
#13 /var/www/html/vendor/symfony/console/Command/Command.php(326): Illuminate\\Console\\Command->execute()
#14 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(181): Symfony\\Component\\Console\\Command\\Command->run()
#15 /var/www/html/vendor/symfony/console/Application.php(1081): Illuminate\\Console\\Command->run()
#16 /var/www/html/vendor/symfony/console/Application.php(320): Symfony\\Component\\Console\\Application->doRunCommand()
#17 /var/www/html/vendor/symfony/console/Application.php(174): Symfony\\Component\\Console\\Application->doRun()
#18 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(201): Symfony\\Component\\Console\\Application->run()
#19 /var/www/html/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle()
#20 {main}
"} 

How to reproduce the bug

Just install the mentioned package and give the HasRoles trait to the user model.

Package Version

latest

PHP Version

8.1.0

Which operating systems does with happen with?

Windows, Linux

Notes

Putting an

Log::debug($this->relations);

at vendor/kiwilan/typescriptable-laravel/src/Typed/Eloquent/EloquentItem.php:126 I was able to found that this package returns

array (
  'roles' => 
  Kiwilan\Typescriptable\Typed\Eloquent\Utils\EloquentRelation::__set_state(array(
     'model' => 'App\\Models\\User',
     'field' => 'roles',
     'isArray' => true,
     'isMorph' => false,
     'type' => NULL,
     'typeTs' => '[]',
  )),
  'permissions' => 
  Kiwilan\Typescriptable\Typed\Eloquent\Utils\EloquentRelation::__set_state(array(
     'model' => 'App\\Models\\User',
     'field' => 'permissions',
     'isArray' => true,
     'isMorph' => false,
     'type' => NULL,
     'typeTs' => '[]',
  )),
)  

Idk how to reproduce the error in laravel without this package, but I think this should help.

[Bug]: Missing model columns

What happened?

The generated types only include some table columns.

Let's say we have this users table columns:

Screen Shot 2024-01-10 at 16 45 31

User's model:

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory;
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    /**
     * Get the user's responses.
     */
    public function responses(): HasMany
    {
        return $this->hasMany(Response::class);
    }
}

And it is what we get:

Screen Shot 2024-01-10 at 16 46 53

How to reproduce the bug

  1. Just generate TS types for models
  2. Generated type only contains some columns

Package Version

^1.11.33

PHP Version

8.2.10

Which operating systems does with happen with?

macOS

Notes

No response

Postgres database not supported for autogeneration

It looks like the process for getting the columns uses a MySQL specific dialect, which means it doesn't work for Laravel projects using postgres.

The rough equivalent to SHOW COLUMNS FROM <table> would be SELECT * FROM information_schema.columns WHERE table_name = <table>.

[Bug]: trait InteractsWithMedia produces invalid typescript

What happened?

When a model uses the trait Spatie\MediaLibrary\InteractsWithMedia, the output looks like this:

media?: App.Models.$this->getMediaModel[]
media_count?: number

How to reproduce the bug

follow the installation instructions: https://github.com/kiwilan/typescriptable-laravel
Install: https://github.com/spatie/laravel-medialibrary

run php artisan make:model DemoModel
Add the InteractsWithMedia trait, and add "use Spatie\Medialibrary\InteractsWithMedia", file should look like this:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\InteractsWithMedia;

class DemoModel extends Model
{
    use HasFactory, InteractsWithMedia;
}

run php artisan typescriptable

Generated output:

  export interface DemoModel {
    media?: App.Models.$this->getMediaModel[]
    media_count?: number
    id?: number
  }

Package Version

1.12.03

PHP Version

8.3.4

Which operating systems does with happen with?

Windows

Notes

There is currently a workaround by adding a file like so:

<?php

declare(strict_types=1);

namespace App\Concerns;

use Illuminate\Database\Eloquent\Relations\MorphMany;
use Spatie\MediaLibrary\InteractsWithMedia as BaseInteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

/**
 * Wrapper for "spatie/laravel-medialibrary" `InteractsWithMedia` trait
 * `kiwilan/typescriptable-laravel` unfortuneatly does not support dynamic lookup of the
 * model for the media relation, so we override the media relation with a hardcoded value.
 *
 * If the model is changed here, remember to change it in the media-library config file as well.
 *
 * @mixin \Spatie\MediaLibrary\HasMedia
 */
trait InteractsWithMedia
{
    use BaseInteractsWithMedia;

    public function media(): MorphMany
    {
        return $this->morphMany(Media::class, 'model');
    }
}

And then change
use Spatie\MediaLibrary\InteractsWithMedia To use that file instead in your models.

php artisan about:
Environment ......................................................................................................................................
Application Name ......................................................................................................................... Laravel
Laravel Version .......................................................................................................................... 10.48.9
PHP Version ................................................................................................................................ 8.3.4
Composer Version ........................................................................................................................... 2.7.2
Environment ................................................................................................................................ local
Debug Mode ............................................................................................................................... ENABLED
URL .................................................................................................................................... localhost
Maintenance Mode ............................................................................................................................. OFF

Spatie Permissions ...............................................................................................................................

Features Enabled ......................................................................................................................... Default
Version .................................................................................................................................... 6.7.0

composer info spatie/laravel-medialibrar:
name : spatie/laravel-medialibrary
descrip. : Associate files with Eloquent models
keywords : cms, conversion, downloads, images, laravel, laravel-medialibrary, media, spatie
versions : * 11.4.7
released : 2024-04-24, this week
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : https://github.com/spatie/laravel-medialibrary
source : [git] https://github.com/spatie/laravel-medialibrary.git 85f5f8284f827b8f2b426943e357e3df117ad1f5
dist : [zip] https://api.github.com/repos/spatie/laravel-medialibrary/zipball/85f5f8284f827b8f2b426943e357e3df117ad1f5 85f5f8284f827b8f2b426943e357e3df117ad1f5
path : C:\Users\Dennis\Herd\tid\vendor\spatie\laravel-medialibrary
names : spatie/laravel-medialibrary

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.