Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oi Laravel Ts Laravel Package

oi-lab/oi-laravel-ts

A Laravel package that automatically generates TypeScript interfaces from your Eloquent models, with relationship support, custom casts, DataObjects, PHPDoc types, watch mode, and namespace filters for customization.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a code-generation tool, not a runtime dependency. It reads Eloquent model metadata (casts, relationships, key types, PHPDoc) and emits a single interfaces.ts artifact consumed by the frontend. That puts it in the same architectural slot as generated API clients or GraphQL codegen: a build-time contract-enforcement layer between Laravel and TypeScript. For a TPM this is attractive because it is additive — no changes to model code, no service provider bootstrapping in the request path, no middleware. The two-pipeline design (Eloquent analysis → TypeScript emission) with an intermediate schema is a sound separation, and the save_schema toggle gives a debuggable inspection point when the output looks wrong. The data_replaces_model option is the strategically interesting one: it lets a DTO become the single source of truth for its model's wire shape, which is the correct model for APIs that return shaped payloads rather than raw rows.

Integration feasibility. Low friction. Composer install, publish one config file, run one artisan command. The documented surface is unusually complete for a package of this age: namespace filters, custom props, external type imports, UUID/ULID key detection, enum literal unions, nested DTOs, and a watch mode. The DTO support is structural rather than coupled to spatie/laravel-data, which removes a hard transitive dependency — a genuine plus. The Inertia.js example in the README is the obvious first target if the frontend is Inertia-based.

Technical risk. The dominant risk is not the code, it is the supply chain. The package has 1 star, 0 dependents, and a single maintainer. It targets Laravel 11/12/13 and PHP 8.2+, which is forward-looking but means it is tracking framework versions that are still moving. Eloquent internals — cast resolution, relationship reflection, trait-provided key types — are among the more brittle parts of Laravel to introspect, and a framework minor release can silently change behavior. The README itself flags a sharp edge: with data_replaces_model enabled, relationships pointing at a replaced model will reference an interface that is no longer generated. That is a compile-time break in the frontend caused by a backend config change, which is precisely the failure mode you do not want in a contract generator. The "142 tests / 344 assertions" figure is respectable but self-reported and small for a tool whose correctness is the entire product.

Key questions.

  • Is there a CI-verifiable guarantee that generated output is byte-stable across runs? Non-deterministic output (ordering, import statements) creates noisy diffs and erodes trust.
  • What is the maintainer's commitment and bus factor mitigation? One person, one repo, MIT — what happens if they stop?
  • Does it handle the parts of our schema we actually care about: accessors/Attribute casts, computed properties, $appends, enum casts, collection casts?
  • How does it behave on polymorphic (morphTo) relationships, and does it fail loudly or emit any?
  • Is there a validation command (generate-and-diff) suitable for CI gating, or only a write command?
  • What happens when a model can't be analyzed — silent skip, warning, or hard failure?

Integration Approach

Stack fit. Requires PHP 8.2+, Laravel 11–13, and a TypeScript frontend. It is indifferent to the frontend framework — the output is plain .ts interfaces — so it fits Vue/Inertia, React, or anything else. The only structural prerequisite is that the frontend consumes Laravel-backed JSON that is shaped like the models, which is the normal case for Inertia apps and for API resources that don't aggressively transform payloads.

Migration path. Greenfield or additive. Nothing must be removed to adopt it. The realistic sequence is: install → publish config → point output_path at the existing hand-written types directory under a distinct filename → run the generator → diff generated interfaces against the hand-written ones. That diff is the value: it surfaces every place where the frontend's assumed types have drifted from the backend's actual models. Where generated output is wrong, custom_props and props_with_types provide corrections without forking. Only after the diff is clean across the models that matter should hand-written interfaces be deleted in favor of the generated ones.

Compatibility. Two compatibility axes matter. First, framework upgrades: because the package introspects Eloquent internals, a Laravel minor bump is a real re-test event, so it should be treated as a dependency to be upgraded deliberately, not floated. Second, the DTO layer: data_replaces_model and data_for_model change the shape of the generated graph, so flipping them is a breaking change to the artifact, not a config tweak. Pin the package version in composer.json rather than accepting caret ranges.

Sequencing.

  1. Spike (1 sprint, timeboxed). Install in a branch. Run against 5–10 representative models — including one UUID-keyed model, one with a custom cast, one with a polymorphic relation, one with an enum cast. Compare output to existing hand-written types. The goal is a go/no-go on the diff, not production rollout.
  2. Config hardening. Settle output_path, excluded_namespaces (every vendor package model that shouldn't leak into frontend types), and discover_related_models. Decide data_replaces_model up front — do not flip it later.
  3. CI gate. Wire php artisan oi:gen-ts into CI followed by a git diff --exit-code on the generated file. This makes the artifact's freshness a build-enforced invariant and catches accidental model changes that were never reflected in the frontend types. Without this step the generated file goes stale within weeks.
  4. Adopt in the frontend, model by model. Replace hand-written interfaces, starting with the highest-traffic domain (auth/user, then the primary resource).
  5. Watch mode for local dev only. --watch is a developer convenience; it should never be a deployment mechanism.

Operational Impact

Maintenance. Low ongoing effort, with one caveat. Regeneration is automatic and cheap; the human cost is in the exceptions — every custom_props entry and every namespace exclusion is a small piece of documentation debt that lives in a config file instead of being self-evident from the models. Budget for a short comment convention in config/oi-laravel-ts.php explaining why each override exists. The larger maintenance question is the dependency itself: a 1-star, single-maintainer package with 0 dependents has no community to absorb a break. Assume we may need to vendor it or fork it, and confirm the MIT license and the small codebase make that cheap — it does.

Support. Self-support only. GitHub issues with one maintainer; no commercial backing, no SLA. That is acceptable for a build-time tool that never touches production traffic and can be pinned and forked, but it is not acceptable to depend on it for anything on the request path. It isn't, which is the saving grace.

Scaling. Scales trivially in runtime terms because it has no runtime. The scaling limit is repo size: one output file for all interfaces means the generated artifact grows monotonically with the model count, and a large domain will produce a multi-thousand-line interfaces.ts that is slow for editors to index and that produces large diffs on every regeneration. Watch for this past roughly 100 models and plan for splitting output by domain if the package doesn't support it (the config shows a single output_path, so this may be a fork-level change).

Failure modes. Ranked by likelihood and impact:

  • Stale artifact. The generator isn't run, model changes, frontend types silently drift. Mitigation: the CI git diff --exit-code gate — this is the single most important operational control.
  • Silent mistyping. The package emits a wrong type (e.g. any, or string where number is correct) and TypeScript accepts it. This is the worst case because it defeats the tool's purpose while appearing to work. Mitigation: review the first several generated interfaces by hand, not just the diff.
  • Dangling references. data_replaces_model suppressing a model interface that another interface still references — the README documents this and does not prevent it. Mitigation: don't enable the flag until the DTO coverage is complete, or run tsc --noEmit on the generated file in CI.
  • Framework upgrade breakage. Laravel minor bump changes introspection behavior. Mitigation: pin the version; re-run the full test generation on every framework upgrade.
  • Maintainer abandonment. Mitigation: fork readiness, MIT license, small surface.

Ramp-up. Hours, not days. One artisan command and one config file. A mid-level engineer can be productive in an afternoon; the real learning is not the tool but the conventions around it — when to add a custom_prop versus fix the cast in the model, and how the data_* options interact. Those deserve a short internal README before a second engineer touches it.

Bottom line for a TPM. Technically well-suited to the problem, well-documented, and cheap to trial — the spike in step 1 is a few days of work and produces a useful drift report regardless of outcome. The blocker is not technical, it is the 1-star/1-maintainer risk profile, which is mitigated almost entirely by (a) it being build-time only, (b) MIT licensing, and (c) the CI freshness gate. Recommend a timeboxed spike with an explicit evaluation of the diff quality on our hardest models — polymorphic relations, enum casts, and accessor-backed properties — before committing. If the generated output requires more than a handful of custom_props overrides to be correct, the maintenance burden will exceed the value and hand-written types remain the better trade.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource