phpmystic/laravel-trpc

tRPC for Laravel

Maintainers

Package info

github.com/rootartisan/laravel-trpc

pkg:composer/phpmystic/laravel-trpc

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-03-16 15:36 UTC

This package is auto-updated.

Last update: 2026-03-16 15:38:40 UTC


README

Bring the end-to-end typesafe API experience of tRPC to your Laravel applications.

Laravel tRPC allows you to build APIs in PHP with the same developer experience as tRPC in the TypeScript ecosystem. Define your procedures in Laravel, and automatically generate TypeScript types for your frontend client.

Features

  • Full TypeScript Safety: Synchronize your backend routes and frontend types instantly.
  • Fluent Action Classes: Keep your logic clean with dedicated procedure classes.
  • Artisan Helpers: Quickly scaffold new procedure classes with php artisan make:trpc.
  • Native Laravel Integration: Works seamlessly with Laravel Validation, FormRequests, Auth, and Request context.
  • tRPC Protocol Compliant: Supports single requests, batching (?batch=1), and standard error formatting.
  • Automatic Type Generation: Reflection-based return type inference and Zod schema generation.

Installation

composer require phpmystic/laravel-trpc

Then, publish the configuration file:

php artisan vendor:publish --tag=trpc-config

Quick Start

1. Define your Procedures

You can define procedures using dedicated Action Classes (recommended) or Closures.

Option A: Action Classes

namespace App\Trpc;

class ListUsers
{
    /**
     * Define validation rules (optional)
     */
    public function rules(): array
    {
        return [
            'search' => 'nullable|string',
        ];
    }

    /**
     * Handle the procedure logic
     */
    public function handle(array $input)
    {
        return \App\Models\User::where('name', 'like', "%{$input['search']}%")->get();
    }
}

Option B: Inline Closures

use Phpmystic\Trpc\Facades\Trpc;

Trpc::router('ping')
    ->query('hello', function (array $input) {
        return "Hello " . ($input['name'] ?? 'World');
    });

2. Register Routers

Register your procedures in a route file (e.g., routes/web.php or a dedicated routes/trpc.php).

use Phpmystic\Trpc\Facades\Trpc;
use App\Trpc\ListUsers;
use App\Trpc\StoreUser;

Trpc::router('users')
    ->query('list', ListUsers::class)
    ->mutation('store', StoreUser::class);

3. Setup the HTTP Endpoint

Map the tRPC controller to a route:

Route::any('/trpc/{path}', \Phpmystic\Trpc\Controllers\TrpcController::class)
    ->where('path', '.*');

4. Generate TypeScript Types

Run the artisan command to generate the _app.ts router file for your frontend:

php artisan trpc:generate --output=resources/ts/trpc/_app.ts

High Performance Watcher

Instead of running the command manually every time you make a change, you can use the --watch flag to automatically keep your types in sync:

php artisan trpc:generate --watch

The watcher is optimized to use minimal CPU and only regenerates when it detects changes in your procedure classes or route files.

Scaffolding

You can quickly create a new tRPC Action Class using the artisan helper:

php artisan make:trpc ListUsers

This will create a new file in app/Trpc/ListUsers.php with the standard rules() and handle() methods.

Frontend Usage

1. Install Dependencies

In your frontend project (React, Vue, etc.), install the tRPC client:

npm install @trpc/client @trpc/server zod

2. Configure the Client

Import the AppRouter type generated by the artisan command to initialize your client.

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './trpc/_app'; // Path to generated file

const trpc = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'http://your-laravel-app.test/trpc',
    }),
  ],
});

3. Usage with Full Type Safety

// Queries
const users = await trpc.users.list.query({ search: 'John' });

// Mutations
const newUser = await trpc.users.store.mutate({
    name: 'Jane Doe',
    email: 'jane@example.com'
});

4. Handling Validation Errors

Laravel validation errors are automatically mapped to a format compatible with Zod's fieldErrors.

try {
    await trpc.users.store.mutate({ email: 'invalid' });
} catch (error) {
    if (error.data?.zodError) {
        // { email: ['The email field must be a valid email address.'] }
        const fieldErrors = error.data.zodError.fieldErrors;
        console.log(fieldErrors);
    }
}

Advanced Usage

Context and Middleware

Procedures have access to the Context, which contains the current Request and User.

Trpc::router('secure')
    ->query('secretData', function ($input, $ctx) {
        return "Secret for user: " . $ctx->getUser()->name;
    })
    ->use(function ($ctx, $next) {
        if (!$ctx->getUser()) {
            abort(401);
        }
        return $next($ctx);
    });

Native FormRequests

You can pass a Laravel FormRequest class directly to the input() method.

Trpc::router('profile')
    ->mutation('update', UpdateProfileAction::class)
    ->input(\App\Http\Requests\UpdateProfileRequest::class);

Explicit Output Typing

While the package uses reflection to infer return types, you can override them manually:

Trpc::router('stats')
    ->query('count', fn() => 100)
    ->output('number'); // Explicitly set TS type to number

Configuration

Publish the configuration file to customize the package behavior:

php artisan vendor:publish --tag=trpc-config

In config/trpc.php, you can:

  • Change the default TypeScript output path.
  • Define Global Middleware that runs on every tRPC request.
  • Toggle stack traces in error responses.

Data Transformation

Laravel tRPC automatically transforms common Laravel objects into tRPC-friendly formats:

  • Carbon / DateTime: Automatically formatted as ISO 8601 strings.
  • Eloquent Models & Collections: Automatically converted to serializable arrays.
  • Paginators: Transformed into a standard structure:
{
  "items": [...],
  "meta": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 15,
    "total": 75
  }
}

License

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