Puddleglum allows you to automatically generate TypeScript interfaces from your Laravel models and requests as well as a typesafe Axios implementation for your API routes.
This package is based on lepikhinb/laravel-typescript. Special thanks for such an awesome package!
If you, like Calvient, have a Laravel backend with a TS front-end (be it React, Vue, or something else), you might have noticed that you have to manually keep your TypeScript interfaces in sync with your Laravel models and requests. You might also have noticed that you have to manually keep your Axios implementation in sync with your Laravel routes.
Puddleglum is a Laravel package that solves these problems by automatically generating Typescript interfaces and a simple API implementation based on Axios.
Laravel 8 and PHP 8 are required. You can install the package via composer:
composer require --dev calvient/puddleglum
You can publish the config file with:
php artisan vendor:publish --provider="Calvient\Puddleglum\PuddleglumServiceProvider" --tag="puddleglum-config"
This is the contents of the published config file:
return [
'output' => resource_path('ts/puddleglum.ts'),
];
Generate TypeScript interfaces.
php artisan puddleglum:generate
In Laravel, you might define your requests from the command line like this:
php artisan make:request StoreUser
If you do this (i.e., your requests extend FormRequest), Puddleglum will automatically generate TypeScript interfaces for your requests. The program reads the rules from your FormRequest and generates TypeScript interfaces for your requests.
For example:
class UserLogin extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => 'required|email',
'password' => [
'required',
Password::min(8)->mixedCase()->letters()->numbers()->symbols()->uncompromised(),
],
];
}
}
Becomes:
export interface UserLogin {
email: string;
password: string;
}
If you don't want to define a FormRequest (e.g., you want to use a request validator directly in your controller), you can use the GlumRequest attribute before your controller.
Example;
#[GlumRequest(['name' => 'string', 'email' => 'string', 'password' => 'string'])]
public function register(Request $request) {
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised(),
]);
}
Defining a response is a bit trickier, because PHP lacks support for generics. However, Puddleglum can still generate TypeScript interfaces for your responses.
We accomplish this by using a PHP attribute.
Example:
#[GlumResponse(['user' => 'User', 'message' => 'string'])]
public function show(User $user): User
{
return response()->json([
'user' => $user,
'message' => 'Hello, world!',
]);
}
Import the Puddleglum client into your TypeScript code:
import {Puddleglum} from '../../puddleglum';
Then, you can use the Puddleglum client to make API calls:
const login = async (email: string, password: string) => {
const reply = await Puddleglum.Auth.LoginController.login({email, password});
setUser(reply.data.user);
};
The API client mirrors the PHP namespace. So, in the example
above, the login controller is at \App\Http\Controllers\Auth
and the method is named login
.
You can also import various models and requests.
import {User} from '../../puddleglum';
const [user, setUser] = React.useState<User>();
The MIT License (MIT). Please see License File for more information.