abetwothree / laravel-ts-publish
Create TypeScript declaration types from your PHP models, enums, and other cast classes
Fund package maintenance!
Requires
- php: ^8.4
- composer/class-map-generator: ^1.7.2
- illuminate/contracts: ^13.0||^12.0
- laravel/prompts: ^0.3.21
- nikic/php-parser: ^5.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- archtechx/enums: ^1.1
- awobaz/compoships: ^2.5 || ^3.0
- inertiajs/inertia-laravel: ^3.3
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0||^10.0.0
- pestphp/pest: ^5.0
- pestphp/pest-plugin-arch: ^5.0.0
- pestphp/pest-plugin-laravel: ^5.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.x-dev
- v2.6.0
- v2.5.2
- v2.5.1
- v2.5.0
- v2.4.0
- v2.3.0
- v2.2.0
- v2.1.0
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- 1.x-dev
- v1.5.1
- v1.5.0
- v1.4.7
- v1.4.6
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.1
- v1.3.0
- v1.2.1
- v1.2.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.1
- v1.0.0
- v0.0.11
- v0.0.10
- v0.0.9
- v0.0.8
- v0.0.7
- v0.0.6
- v0.0.5
- v0.0.4
- V0.0.3
- v0.0.2
- v0.0.1
- v0.0.0
- dev-fix/class-names-in-generated-files
- dev-develop
- dev-fix/pr63-model-metadata-review
- dev-feature/php-functions-return-types
- dev-copilot/update-user-profile-system
This package is auto-updated.
Last update: 2026-10-03 10:00:30 UTC
README
This package generates TypeScript from your Laravel app: model and API resource interfaces, enums, route helpers, form request payloads, broadcast channels and events, Inertia props, and Vite env variables.
Enums and routes become functional objects. Enums get PHP-like .from(), .tryFrom(), and .cases(), and can include your own methods.
You can override anything the package infers. By default, types republish after migrate, and the @tolki/ts Vite plugin republishes them when your PHP changes, so your frontend stays in sync.
To see what the package writes, browse the generated output examples.
Also by me
Table of contents
- ๐ฆ Installation
- ๐ Usage
- ๐ท๏ธ Enums
- ๐๏ธ Models
- ๐งพ Model metadata
- ๐ก API resources
- ๐ Routes
- ๐ Form requests
- ๐ก Broadcast channels
- ๐ค Broadcast events
- ๐ Inertia
- ๐ Vite env
- ๐งฌ Extending interfaces
- โ Excluding content
- ๐ค Casing configurations
- ๐ Enum API resource
- ๐ Modular publishing
- ๐ง Customizing the pipeline
- ๐ Analyzer API
- โก Pre-command hook
- ๐พ Cache generation
- ๐ค Output options
- โ๏ธ Configuration reference
Installation
The package requires PHP 8.4+ and Laravel 12 or 13. Install it with Composer:
composer require abetwothree/laravel-ts-publish
Publish the config file:
php artisan vendor:publish --tag="ts-publish-config"
To edit the Blade templates that render each file, also publish the views with php artisan vendor:publish --tag="laravel-ts-publish-views".
Installation & Usage covers installing @tolki/ts, setting up import aliases, and adding the Vite plugin. If you're upgrading from an earlier version, follow the upgrade guide.
Usage
Run the ts:publish Artisan command to generate your types:
php artisan ts:publish
It finds classes in Laravel's standard directories, such as app/Models and app/Enums, and writes to resources/js/types/data/.
These options cover the common cases:
| Option | Effect |
|---|---|
--fresh |
Rebuilds every file. Without it, a run rebuilds only the classes whose source changed. |
--preview=true |
Prints the output without writing files. A bare --preview doesn't preview, and writes real files. |
--source= |
Republishes one class, given as a class name or a file path. |
--only-enums, --only-models, and the other --only-* flags |
Publishes one feature for this run. These flags can't be combined with each other. |
--only-functional |
Publishes every enabled feature except model and resource interfaces. It overrides any other --only-* flag. |
-v, --quiet |
-v adds detailed tables of the published classes and extra files. --quiet prints only errors. |
By default, types republish after each migrate that runs migrations. To turn this off, set run_after_migrate to false, or TS_PUBLISH_RUN_AFTER_MIGRATE=false in .env.
Models, enums, resources, form requests, and broadcast events each take included, excluded, and additional_directories settings to choose which classes publish. For those settings, partial runs, output files, and console output, see the Publishing Types documentation.
Enums
PHP enums become TypeScript objects that behave like the PHP enum, with .from(), .tryFrom(), and .cases() from @tolki/ts. This enum publishes its cases and its label() method:
enum Status: string { case Active = 'active'; case Inactive = 'inactive'; #[TsEnumMethod] public function label(): string { return match($this) { self::Active => 'Active User', self::Inactive => 'Inactive User', }; } }
On the frontend, you use the published enum much like the PHP one:
import { Status } from '@data/app/enums'; Status.Active; // 'active' Status.label.Active; // 'Active User' Status.from('active').label; // 'Active User', a PHP-like enum "instance"
Key capabilities include:
- Your own methods: publish them with
#[TsEnumMethod]and#[TsEnumStaticMethod], or auto-include public ones. - Renames and descriptions:
#[TsEnum]and#[TsCase]rename an enum or a case, or add a JSDoc description. - Type aliases:
{Name}Typetypes a raw case value, and a backed enum's{Name}Kindtypes a case name. - PHPDoc carried over: class, case, and method doc blocks become JSDoc comments.
For every attribute option, the auto-include settings, and the runtime helpers, see the Enums documentation.
Models
Eloquent models become TypeScript interfaces for their columns, accessors, and relations, typed from your schema, casts, and docblocks. Each model splits into separate interfaces by default, so a page imports only the parts it uses, and models.template can combine them into one. This model has a cast, an accessor, and a relation:
class User extends Model { public function casts(): array { return ['status' => Status::class]; } protected function initials(): Attribute { return Attribute::get(fn (): string => /* ... */); } public function posts(): HasMany { return $this->hasMany(Post::class); } }
Its columns, accessors, and relations publish as three separate interfaces:
import type { User, UserMutators, UserRelations } from '@data/app/models'; // User โ id: number; status: StatusType; ... // UserMutators โ initials: string // UserRelations โ posts: Post[]; posts_count: number; posts_exists: boolean
Key capabilities include:
- Docblock-aware:
@property,@phpstan-type, andAttribute<>docblocks sharpen types, and PHPStan reads them too. - Accessor getter bodies: an accessor with a vague signature is typed from the value its getter returns.
- Nullable relations: singular relations get
| nullfrom their type and foreign key, configurable per type. - Overrides:
#[TsCasts]retypes a property, and#[TsType]types every column that uses a custom cast class. - Enum columns: a parallel
{Model}Resourceinterface types each enum column as a resolvedAsEnum<>instance. - Hidden columns:
$hiddenattributes publish unless you turn onmodels.exclude_hidden. - Laravel 13 attributes:
#[Table],#[Hidden],#[Visible],#[Appends], and#[Connection]apply with no setup.
For templates, relation strategies, and type mappings, see the Models documentation. If a property still publishes unknown, the annotation checklist names the fix.
Model metadata
This opt-in feature writes a runtime companion, {model}_meta.ts, beside each model interface. Unlike the interface, the companion is a real module, so the frontend can read values the backend owns instead of hard-coding them. Turn it on in the config:
// config/ts-publish.php 'model_metadata' => [ 'enabled' => true, ],
With the default provider, each companion holds the model's morph class:
// resources/js/types/data/app/models/user_meta.ts export const UserModelMetadata = { morphClass: 'App\\Models\\User', } as const satisfies { morphClass: string; };
morphClass holds what getMorphClass() returns: the class name, or its alias once you register a morph map. Read it for a polymorphic field such as commentable_type instead of typing the PHP class name.
Key capabilities include:
- Own switches:
model_metadata.enabledand--only-model-metadatacontrol it, and--only-functionalincludes it. - Custom providers: implement
ModelMetadataProviderand setmodel_metadata.provider_classto add values. - Typed values: each key is typed from
#[TsCasts], a@return array{...}shape, or the method body. - Checked values: a value TypeScript can't hold fails its companion, and the error names the model and path.
- Contained failures: a provider that throws keeps the model's last good companion, and the run exits non-zero.
- Inherited filters:
included,excluded, andadditional_directoriesfall back to themodels.*values. - Cache-aware: a morph-map change or a new value republishes only the affected companions, without
--fresh.
For the provider contract, value rules, and failure handling, see the Model Metadata documentation.
API resources
The package reads each JsonResource's toArray() without calling it, and generates an interface for what it returns. You don't maintain a second type for your API's JSON. This resource reads columns, an enum, and a relation from its User model:
/** @mixin User */ class UserResource extends JsonResource { public function toArray(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, 'role' => EnumResource::make($this->role), 'posts' => PostResource::collection($this->whenLoaded('posts')), ]; } }
The package publishes this interface:
import { type AsEnum } from '@tolki/ts'; import { Role } from '../../enums'; import type { PostResource } from '.'; export interface UserResource { id: number; name: string; role: AsEnum<typeof Role> | null; posts?: PostResource[]; }
Key capabilities include:
- Model-aware types: properties are typed from the backing model's columns, casts, accessors, and relations.
- Conditional methods:
when(),whenLoaded(),whenCounted(), and the rest publish optional properties. - Nested resources:
::make(),::collection(),new, andtoResource()publish the imported resource type. - Computed values: method calls, local variables,
instanceofnarrowing, and collection chains keep their types. - Spreads and inheritance:
merge(), parenttoArray()spreads, and trait method spreads add their keys. - Attribute filters:
only([...])andexcept([...]), on the resource or on a relation, are typed from the model. - Overrides:
#[TsResource]sets the name or model, and#[TsCasts]overrides or adds property types.
For every supported toArray() pattern and the attribute reference, see the API Resources documentation.
Routes
Every routed controller action gets a helper that builds its URL, binds its parameters, adds query strings, and spoofs form methods. The helpers follow Laravel Wayfinder's conventions, and their logic lives once in defineRoute() from @tolki/ts. A controller's generated file holds one call per action:
// resources/js/types/data/app/http/controllers/post-controller.ts (generated) import { defineRoute, annotateRequestPayload } from '@tolki/ts'; import type { UpdatePostRequest } from '../requests/update-post-request'; export const update = annotateRequestPayload<UpdatePostRequest>()(defineRoute({ name: 'posts.update', url: '/posts/{post}', methods: ['put'] as const, args: [{ name: 'post', required: true, _routeKey: 'id' }] as const, }));
Your frontend calls the helper:
import { PostController } from '@data/app/http/controllers'; PostController.update({ post: 42 }); // { url: '/posts/42', method: 'put' } PostController.update(post); // pass a Post object directly PostController.update.form({ post: 42 }); // { action: '/posts/42?_method=PUT', method: 'post' }
Key capabilities include:
- Structural typing: model and enum route bindings are typed without importing the model or enum.
- Calling conventions: pass a named object, positional arguments, an array, or a model object.
- Query strings: extra keys become query parameters, and
mergeQueryupdates the current page's query string. - Form helpers:
.form()builds{ action, method }for HTML forms, with Laravel's_methodspoofing. - Inertia page props: an action's
Inertia::render()component and props are typed, Inertia UI Table included. - Form request payloads: an action that type-hints a
FormRequestgets that request's interface. - Filtering:
#[TsExclude], route-name patterns, middleware exclusion, and a named-routes-only mode.
For every calling convention, binding rule, and the Inertia and form request helpers, see the Routing documentation.
Form requests
A form request's rules() becomes a TypeScript interface for its payload, so your useForm() calls and request bodies match your validation rules. This request mixes plain, wildcard, and nested rules:
class StorePostRequest extends FormRequest { public function rules(): array { return [ 'title' => ['required', 'string', 'max:255'], 'rating' => ['nullable', 'numeric'], 'tags' => ['array'], 'tags.*' => ['string'], 'order.items.*.sku' => ['required', 'string'], ]; } }
The generated interface has this shape:
import type { StorePostRequest } from '@data/app/http/requests'; // { title: string; rating?: number | null; tags?: string[]; order?: { items?: { sku: string }[] }; }
Key capabilities include:
- Rule-aware types: scalar, array, file,
in:, andRule::enum()rules, among others, map to TypeScript types. - Nested rules: dot-notation and wildcard keys, such as
tags.*, compose into nested shapes. - Presence rules:
requiredandsometimesdecide the?,nullableadds| null, andprohibiteddrops a field. - JSDoc hints: rules such as
email,uuid, andexistsadd JSDoc tags such as@format email. - Overrides and extends:
#[TsCasts]overrides a field's type, and#[TsExtends]extends shared interfaces. - Dynamic fallback: a
rules()that can't run during a publish givesRecord<string, unknown>, not an error.
For the full rule-to-type mapping and the JSDoc annotations, see the Form Requests documentation.
Broadcast channels
Every channel in routes/channels.php compiles into one broadcast-channels.ts file, with a BroadcastChannel union type and a BroadcastChannels object of accessors. You never hand-type a {placeholder} channel string. These channels are registered:
// routes/channels.php Broadcast::channel('orders.{orderId}', function ($user, $orderId) { return true; }); Broadcast::channel('public-announcements', PublicAnnouncementsChannel::class);
The frontend builds channel names from the accessors:
import { BroadcastChannels } from '@data/broadcast-channels'; BroadcastChannels.orders(42); // 'orders.42' BroadcastChannels["public-announcements"]; // 'public-announcements'
Key capabilities include:
- Nested accessors: dot-notation names such as
user.{userId}.notificationsbecome nested accessor functions. - Both registration styles: closures and channel classes publish alike, because only the name matters.
- Channel name type:
BroadcastChanneltypes a helper that accepts any registered channel name. - One combined file: every registered channel lands in one file, with no per-channel filters or attributes.
For how names become accessors and how quoted keys work, see the Broadcast Channels documentation.
Broadcast events
Every ShouldBroadcast and ShouldBroadcastNow event gets an interface built from its broadcastWith() return shape or, when there is none, its public properties. A combined broadcast-events.ts adds a BroadcastEvent union and a BroadcastEvents const of every Echo event name. This event has three promoted properties:
class OrderShipped implements ShouldBroadcast { public function __construct( public int $orderId, public string $trackingNumber, public string $carrier, ) {} public function broadcastOn(): Channel { return new PrivateChannel("orders.{$this->orderId}"); } }
It publishes this interface:
/** @see App\Events\OrderShipped */ export interface OrderShipped { orderId: number; trackingNumber: string; carrier: string; }
Key capabilities include:
- Models and enums: a model property publishes
Partial<Model>, and an enum property uses the enum's{Name}Type. - Custom event names: a literal
broadcastAs()name replaces Laravel's default dotted class name. - Overrides and extends:
#[TsCasts]overrides property types, and#[TsExtends]extends shared interfaces. - Echo typing:
echo-broadcast-events.d.tsaugments Laravel Echo, so.listen()callbacks get typed payloads. - Name clashes: two events with the same class name get namespace-prefixed aliases in the combined file.
For property resolution rules and Echo setup, see the Broadcast Events documentation.
Inertia
With inertia.enabled on, the default, the package reads the share() method of your HandleInertiaRequests middleware and writes inertia-config.d.ts. That file declares a global Inertia.SharedData type and augments @inertiajs/core, so every page gets typed shared props. This middleware shares three keys:
class HandleInertiaRequests extends Middleware { public function share(Request $request): array { return [ ...parent::share($request), 'name' => config('app.name'), 'auth' => ['user' => $request->user()], 'sidebarOpen' => ! $request->hasCookie('sidebar_state'), ]; } }
The package writes this declaration file:
import type { User } from './app/models'; declare global { namespace Inertia { type SharedData = { name: string, auth: { user: User | null }, sidebarOpen: boolean }; } } declare module '@inertiajs/core' { export interface InertiaConfig { sharedPageProps: { name: string, auth: { user: User | null }, sidebarOpen: boolean }; } }
Key capabilities include:
- Static
share()analysis: every key is typed from your code, up the parent middleware chain, with no request. - Typed user:
$request->user()andAuth::user()publish your auth provider's model asUser | null. - Live config values: a literal
config('some.key')is typed from its value in your booted app. - Prop wrappers:
Inertia::defer(),optional(),merge(), and the other v2 wrappers type as the value they wrap. - Overrides:
#[TsCasts]or a@return array{...}docblock onshare()types a key the package can't infer. - Validation errors:
errorsis left to@inertiajs/core, and$withAllErrorsadds anerrorValueType.
For middleware discovery and the override priority, see the Inertia documentation.
Vite env
By default, the package reads the VITE_ variables in your .env and writes a vite-env.d.ts that augments Vite's ImportMetaEnv interface. import.meta.env.VITE_APP_NAME is then typed with no declaration file to maintain. For example, your .env holds these variables:
VITE_APP_NAME=MyApp VITE_APP_URL=https://example.test
The package writes this file:
/// <reference types="vite/client" /> interface ImportMetaEnv { readonly VITE_APP_NAME: string; readonly VITE_APP_URL: string; } interface ImportMeta { readonly env: ImportMetaEnv; }
Key capabilities include:
VITE_variables only: other variables stay out, matching what Vite exposes to client code.- Source file order:
vite_env.source_fileif you set it, then.env, then.env.exampleas a fallback. - Always
string: every variable is typedstring, which is what Vite provides at runtime. - No empty file: with no
VITE_variables, or no source file, nothing is written.
For the parsing rules and source-file order, see the Vite Env documentation.
Extending interfaces with #[TsExtends] & configs
#[TsExtends] and the ts_extends.* config arrays add your own interfaces to a generated interface's extends clause. Use them for properties the package can't infer, or to share fields across many classes. This model extends a hand-written HasTimestamps interface:
#[TsExtends('HasTimestamps', import: '@/types/common')] class Warehouse extends Model {}
The model's interface then extends yours:
import type { HasTimestamps } from '@/types/common'; export interface Warehouse extends HasTimestamps { /* columns */ }
Key capabilities include:
- Four features: works on models, resources, form requests, and broadcast events, by attribute or config.
- Inherited: an attribute on a parent class or a trait applies to every class that extends or uses it.
- Repeatable: stack several
#[TsExtends]attributes to extend several interfaces. - Generic helpers: wrap a type in
Pick<>,Omit<>, orPartial<>, and list the names to import intypes. - Deduplication and aliasing: a clause reached twice appears once, and clashing type names get aliases.
For inheritance order, config syntax, and alias rules, see the Extending Interfaces documentation.
Excluding with #[TsExclude]
#[TsExclude] keeps a class out of the TypeScript output, or one of its methods, accessors, relations, or controller actions. It works on enums, models, resources, form requests, broadcast events, and controllers. Key capabilities include:
- Whole classes: an excluded class publishes nothing, and it's left out of barrels and combined files.
- Single members: on a method, accessor, relation, or action, it removes only that member.
- Always wins: it overrides
#[TsEnumMethod],#[TsEnumStaticMethod], and the enum auto-include settings.
For every target and a worked example of each, see the Excluding Content documentation.
Casing configurations
Three config keys set the casing of generated names, and each accepts 'snake', 'camel', or 'pascal'. Relations default to 'snake', and enum methods and route actions default to 'camel'. Key capabilities include:
- Relation names:
models.relationship_casesets relation names, and their_countand_existsproperties follow. - Enum method keys:
enums.method_casesets the keys of published enum methods. - Route exports:
routes.method_casingsets each action's export name, never the Laravel route name. - Independent settings: each key affects only its own feature, and there's no global casing setting.
For worked examples of each setting, see the Casing Configurations documentation.
JSON enum HTTP API resource
EnumResource is a Laravel JSON resource that returns one enum case as a flat object. It follows the same rules as ts:publish, so the methods you publish appear in the response. This returns a case of a PostStatus enum that publishes icon() and color() methods:
return new EnumResource(PostStatus::Published);
The response is one flat object:
{ "name": "Published", "value": 1, "backed": true, "icon": "check", "color": "green" }
Key capabilities include:
- Same rules as
ts:publish: the same methods, with the sameenums.method_casecasing, appear in the response. - Standalone or embedded: return it from a route, or use
EnumResource::make()inside another resource. AsEnumtype:AsEnum<typeof PostStatus>from@tolki/tstypes the response on the frontend.- Unit enums: a unit enum's
valuerepeats its case name, andbackedisfalse.
For the response shape and unit enum behavior, see the Enum API Resource documentation.
Modular publishing
Generated files always mirror your PHP namespaces as a directory tree, with no flat-output mode. Accounting\Models\Invoice publishes to accounting/models/invoice.ts, so modular and domain-driven apps stay organized, and a single-namespace app gets one app/ tree. Key capabilities include:
- Every feature: models, enums, resources, form requests, broadcast events, and routes follow the same rule.
- Relative imports: files import each other through computed relative paths, with no path alias needed.
- Barrel files: each namespace directory gets an
index.tsthat re-exports its files. - Prefix stripping:
namespace_strip_prefixremoves a shared prefix, such asModules\, from every output path.
For the path rules, import paths, and barrel format, see the Modular Publishing documentation.
Extending & customizing the pipeline
Features run through a pipeline of collector, generator, transformer, writer, and Blade template, though not every feature uses all five. To replace a class stage, extend its built-in class and point the feature's config key at yours, such as models.transformer_class. Key capabilities include:
- Swappable stages: the collector, generator, transformer, and writer each have a
{feature}.{stage}_classkey. - Base classes: abstract collector, generator, transformer, and writer classes define each stage's contract.
- Cached custom generators: add the
RehydratesFromCachetrait to a custom generator to cache it. - Template-only changes: publish and edit the Blade templates to change formatting without writing PHP.
For each feature's stages, the base class contracts, and the template keys, see the Customizing the Pipeline documentation.
Analyzer API
AstEngine::analyze() runs the package's type inference on a class method and returns the typed properties and the imports they need. Call it from your own code, such as a custom Artisan command, without running a publish:
use AbeTwoThree\LaravelTsPublish\Ast\AstEngine; $result = resolve(AstEngine::class)->analyze(App\Http\Resources\PostResource::class); // $result->properties, $result->typeImports, $result->valueImports
Key capabilities include:
- Ready to render: the properties and both import maps agree, so a module that renders all three compiles.
- Any class, any method:
toArray()by default, or another method, such asanalyze($event, 'broadcastWith'). - Resource semantics: conditional methods, nested resources, and relation filters type as they do in a publish.
- Public API:
analyze()andAnalysisResultare supported, and every other engine class is internal.
For the arguments, the result's fields, and what it can't analyze, see the Analyzer API documentation.
Pre-command hook
LaravelTsPublish::callCommandUsing() registers a closure that runs right before ts:publish does its work. It runs only when the command runs, so it adds nothing to a normal request. Register it in a service provider's boot() method:
LaravelTsPublish::callCommandUsing(function () { config()->set('ts-publish.models.additional_directories', ['modules/Blog/Models']); });
Key capabilities include:
- Every invocation: a full publish, a
--sourcererun, a preview, and the post-migration run all call it. - One closure: calling
callCommandUsing()again replaces the closure instead of adding a second one. - Any config key: the closure can set any
ts-publish.*key, including a pipeline*_classoverride. - Dynamic directories: scan the filesystem or a module registry to build
additional_directorieslists.
For worked examples and how to reset the hook between tests, see the Pre-Command Hook documentation.
Cache generation
After the first full publish, ts:publish reuses the output of every class whose source file and dependencies haven't changed. The cache clears itself when the package version or your output-affecting config changes. Key capabilities include:
- Dependency-aware: a class rebuilds when its file, a parent, a trait, a related model, or its routes change.
- Bypassed by single-class and preview runs:
--sourceand--preview=truenever read or write the cache. - File or Laravel store: files by default, or any Laravel cache store you name in
cache.store. - Signed entries: entries are signed with
cache.key, or your app key when it's unset, and checked before use.
For what triggers a rebuild, what the cache can't detect, and the storage options, see the Cache Generation documentation.
Output options
Besides the .ts files, ts:publish can write three extra files, each with its own enabled key. The watcher list is on by default, and the globals and JSON files are off. Key capabilities include:
globals.enabled: writeslaravel-ts-global.ts, which declares every published type in a global namespace.json.enabled: writeslaravel-ts-definitions.json, every published class as data, keyed by full class name.watcher.enabled: writes the list of collected PHP files that file watchers, such as the Vite plugin, read.output_to_files:falseskips the automatic publish aftermigrate, and doesn't stopts:publishfrom writing.
For each file's format, see Output Files in the Publishing Types documentation.
Configuration reference
Every option lives in config/ts-publish.php, grouped by feature, such as models.*, enums.*, routes.*, and cache.*. Publish the file with the vendor:publish command in Installation. Key capabilities include:
- General settings:
output_directory,timestamps_as_date, andcustom_ts_mappingsapply across features. - Per-feature blocks: each feature's settings, such as
enabled,included, andtemplate, live in its own block. - Environment variables:
TS_PUBLISH_RUN_AFTER_MIGRATEand theTS_PUBLISH_CACHE_*variables set keys from.env.
For every key, its type, and its default, see the Configuration Reference.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.