PHPackages                             rosalana/safepoint - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. rosalana/safepoint

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

rosalana/safepoint
==================

Generate Typescript representation of Laravel models, routes and actions.

v0.0.11(1mo ago)014↓50%[3 issues](https://github.com/rosalana/safepoint/issues)MITPHPPHP ^8.2

Since Mar 4Pushed 1mo agoCompare

[ Source](https://github.com/rosalana/safepoint)[ Packagist](https://packagist.org/packages/rosalana/safepoint)[ RSS](/packages/rosalana-safepoint/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (18)Versions (12)Used By (0)

[![Rosalana](https://raw.githubusercontent.com/rosalana/.github/main/Safepoint_Banner.png)](https://github.com/rosalana)

**Rosalana Safepoint** is a TypeScript type generator for **Laravel + Inertia.js applications.**

It generates a **single TypeScript file** from your Laravel application — models, routes, shared Inertia data, and helper types — all in one flat output optimized for end-to-end type safety.

This package is designed primarily for:

- Laravel developers using **Inertia.js**
- teams who want **type-safe props, route params, and request bodies**
- projects that use **static analysis** over runtime reflection
- monorepo setups with **multiple Laravel apps**

Installation
------------

[](#installation)

```
composer require rosalana/safepoint
```

Why Safepoint?
--------------

[](#why-safepoint)

Inertia.js moves data between PHP and JavaScript — but without types, that boundary is invisible.

Typing it manually means:

- duplicating model definitions
- guessing what props a page receives
- no autocomplete for route params or request bodies
- types going out of sync as the app grows

**Rosalana Safepoint does not require you to write types manually.**It reads your Laravel application using static analysis and generates them for you.

Note

Safepoint uses [`laravel/ranger`](https://github.com/laravel/ranger) and [`laravel/surveyor`](https://github.com/laravel/surveyor) under the hood to inspect your models, routes, and shared data without running the application.

What it generates
-----------------

[](#what-it-generates)

Running `php artisan safepoint:generate` produces `resources/js/safepoint.ts`:

```
/* --- Models --- */

export interface Post {
  id: number
  title: string
  // ...all DB-backed attributes

  user?: User | null  // optional relations
}

/* --- Enums --- */

export type StatusEnum = 'draft' | 'published' | 'archived'

/* --- Routes --- */

export interface Routes {
  'posts.show': {
    method: 'get'
    params: { post: number }
    body: never
    props: { post: RequiredKeys }
  }
  // ...all named app routes
}

/* --- Shared Data --- */

export interface SharedData {
  auth: { user: { id: number; name: string } | null }
  // ...everything returned from HandleInertiaRequests::share()
}

/* --- Route List --- */

export const _routes: { [key in keyof Routes]: { method: Method, uri: string } } = {
  'posts.show': { method: 'get', uri: '/posts/{post}' },
  // ...
}

/* --- Helpers --- */

export type PageProps = ...
export type RouteParams = ...
export type RouteBody = ...
export function route(name: T, ...args): { url: string; method: Method }
```

Usage
-----

[](#usage)

```
php artisan safepoint:generate
```

### Options

[](#options)

OptionDescription`--path=`Custom output path (default: `resources/js/safepoint.ts`)`--base-path=`Comma-separated base paths (default: `base_path()`)`--app-path=`Comma-separated app paths (default: `app_path()`)`--skip-routes`Skip route and route list generation`--skip-models`Skip model interface generation`--skip-enums`Skip enum type generation`--skip-shared-data`Skip shared data interface generation### Multiple paths (monorepo)

[](#multiple-paths-monorepo)

```
php artisan safepoint:generate \
  --base-path=/app,/packages/blog \
  --app-path=/app/app,/packages/blog/src
```

Only models and routes whose source files are under `--app-path` are included. Vendor models (e.g. `DatabaseNotification` from the `Notifiable` trait) are automatically filtered out.

How it works
------------

[](#how-it-works)

Safepoint inspects your application statically — no runtime required:

- **Models** — attributes from DB schema, relations from PHPDoc
- **Enums** — PHP backed enums discovered via static analysis
- **Routes** — HTTP method, URL parameters, request validation rules, Inertia props
- **Shared data** — from `HandleInertiaRequests::share()`
- **Route list** — a runtime-usable `_routes` const and a typed `route()` helper

PHPDoc annotations
------------------

[](#phpdoc-annotations)

Since Safepoint uses static analysis, it can't detect runtime behavior like `$post->load('user')` or manually built responses. Use PHPDoc annotations on controller methods to override or extend the generated types.

AnnotationExampleEffect`@safepoint-ignore``@safepoint-ignore`Skip this route entirely`@safepoint-include``@safepoint-include user, comments`Add relations to the `RequiredKeys` key list for props`@safepoint-prop``@safepoint-prop pagination { current_page: number; total: number }`Add or override a prop's TypeScript type`@safepoint-body``@safepoint-body token string`Add or override a body field's TypeScript type`@safepoint-param``@safepoint-param slug string`Add or override a URL parameter's TypeScript type```
/**
 * @safepoint-include user
 * @safepoint-prop meta { total: number; page: number }
 */
public function show(Post $post): Response
{
    return Inertia::render('Post/Show', [
        'post' => $post->load('user'),
        'meta' => [...],
    ]);
}
```

Note

`@safepoint-include` only adds relations that actually exist on the model — unknown relation names are silently ignored.

Working with generated types
----------------------------

[](#working-with-generated-types)

### PageProps

[](#pageprops)

Use `PageProps` to get fully typed page props in your Inertia pages:

```
import type { PageProps } from '@/safepoint'
import { usePage } from '@inertiajs/vue3'

const { post } = usePage().props
// post is: RequiredKeys & SharedData
```

### RouteParams &amp; RouteBody

[](#routeparams--routebody)

```
import type { RouteParams, RouteBody } from '@/safepoint'

// Typed route parameters
const params: RouteParams = { post: 1 }

// Typed request body
const body: RouteBody = { title: 'Hello', body: 'World' }
```

### route() helper

[](#route-helper)

The generated file includes a typed `route()` helper that builds URLs from route names and parameters:

```

import { route } from '@/safepoint'

const { url, method } = route('posts.show', { post: 42 })
// url: 'https://example.com/posts/42', method: 'get'

router.push(url) // navigate to the route

  View Post

```

### Extending the generated types

[](#extending-the-generated-types)

Since the generated file is overwritten on each run, **do not edit it directly.** Instead, create a separate file and use TypeScript [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html):

```
// resources/js/safepoint-extend.ts
declare module './safepoint' {

  // Add computed or custom fields to a model
  interface Post {
    computed_title?: string
  }

  // Add routes that aren't in Laravel's router (e.g. client-side only)
  interface Routes {
    'frontend.dashboard': {
      method: 'GET'
      params: never
      body: never
      props: { widgets: unknown[] }
    }
  }

  // Add extra keys to shared data
  interface SharedData {
    locale: string
  }

}
```

Import `safepoint-extend.ts` alongside `safepoint.ts` and TypeScript will merge the declarations automatically.

License
-------

[](#license)

Rosalana Safepoint is open-source under the [MIT license](/LICENCE), allowing you to freely use, modify, and distribute it with minimal restrictions.

You may not be able to use our systems but you can use our code to build your own.

For details on how to contribute or how the Rosalana ecosystem is maintained, please refer to each repository's individual guidelines.

**Questions or feedback?**

Feel free to open an issue or contribute with a pull request. Happy coding with Rosalana!

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance89

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

11

Last Release

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c9ccd4c922b657506198515445c7d0ece52b8261178e0490e7ba2a81ca78a915?d=identicon)[michalbany](/maintainers/michalbany)

---

Top Contributors

[![michaelbany](https://avatars.githubusercontent.com/u/117490667?v=4)](https://github.com/michaelbany "michaelbany (34 commits)")

---

Tags

phplaravelroutespackagetypescriptinertiarosalana

### Embed Badge

![Health badge](/badges/rosalana-safepoint/health.svg)

```
[![Health](https://phpackages.com/badges/rosalana-safepoint/health.svg)](https://phpackages.com/packages/rosalana-safepoint)
```

###  Alternatives

[laravel/wayfinder

Generate TypeScript representations of your Laravel actions and routes.

1.7k4.1M69](/packages/laravel-wayfinder)[lord/laroute

Access Laravels URL/Route helper functions, from JavaScript.

8022.0M8](/packages/lord-laroute)[tehwave/laravel-achievements

Simple, elegant Achievements the Laravel way

7012.8k](/packages/tehwave-laravel-achievements)[laravel/ranger

Laravel Ranger is a powerful introspection library for Laravel applications.

5138.9k4](/packages/laravel-ranger)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
