Skip to content

Commit

Permalink
feat: generate types for ziggy (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
7nohe authored Dec 8, 2022
1 parent 5dc0ef3 commit cf4c5db
Show file tree
Hide file tree
Showing 35 changed files with 780 additions and 35 deletions.
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Generate TypeScript types from Laravel models
- Support Relationhips
- Support Enum (from PHP8.1)
- Generate route.d.ts file for ziggy
- Provide useful types for Laravel (e.g. pagination, etc.)

## Installation
Expand Down Expand Up @@ -90,7 +91,7 @@ export enum GenderType {
```

### Laravel Enum Support
If you use (Laravel Enum)[https://github.com/BenSampo/laravel-enum], use the option `--laravel-enum`.
If you use [Laravel Enum](https://github.com/BenSampo/laravel-enum), use the option `--laravel-enum`.


```json
Expand All @@ -101,6 +102,44 @@ If you use (Laravel Enum)[https://github.com/BenSampo/laravel-enum], use the opt
}
```

### Use strongly typed `route()` function for ziggy

Running the `laravel-typegen` command with the `--ziggy` option will generate route.d.ts.

It helps typing the `route()` function.

```json
{
"scripts": {
"typegen": "laravel-typegen --ziggy"
},
}
```

For example, define the following routes

```php
// routes/web.php
Route::resource('posts', PostsController::class);
```

```bash
$ php artisan route:list
GET|HEAD posts/{post} posts.show › PostsController@show
```

Parameters will be checked strictly based on the route name.

```ts
// in your TypeScript code

// OK
route('posts.show', { post: post.id })

// Error
route('posts.show', { id: post.id })
```

### Useful types for Laravel

We provide useful types for Laravel (especially for Inertia).
Expand Down Expand Up @@ -168,6 +207,7 @@ Options:
-o, --output <value> Output directory (default: "resources/ts/types")
--laravel-enum Use Laravel Enum (default: false)
--enum-path <value> Path to enum files (default: "app/Enums")
-z, --ziggy Generate types for ziggy (default: false)
-h, --help display help for command
```

Expand Down
98 changes: 98 additions & 0 deletions examples/laravel9-app/app/Http/Controllers/PostsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Inertia;

class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();
return Inertia::render(
'Posts/Index',
[
'posts' => $posts
]
);
}

/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}

/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}

/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return Inertia::render(
'Posts/Show',
[
'post' => $post
]
);
}

/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
24 changes: 24 additions & 0 deletions examples/laravel9-app/database/factories/PostFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Post>
*/
class PostFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition()
{
return [
'title' => fake()->text(10),
'body' => fake()->text(),
];
}
}
2 changes: 1 addition & 1 deletion examples/laravel9-app/database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DatabaseSeeder extends Seeder
*/
public function run()
{
\App\Models\User::factory(10)->create();
\App\Models\User::factory(10)->hasPosts(3)->create();

\App\Models\User::factory()->create([
'name' => 'Test User',
Expand Down
2 changes: 1 addition & 1 deletion examples/laravel9-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"dev": "vite",
"build": "vite build",
"type:check": "vue-tsc --noEmit",
"typegen": "node node_modules/@7nohe/laravel-typegen/src/cli.js",
"typegen": "node node_modules/@7nohe/laravel-typegen/src/cli.js --ziggy",
"typegen:laravel-enum": "node node_modules/@7nohe/laravel-typegen/src/cli.js --enum-path 'app/LaravelEnums' --laravel-enum"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import DropdownLink from '@/Components/DropdownLink.vue';
import NavLink from '@/Components/NavLink.vue';
import ResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';
import { Link, usePage } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
import { User } from '@/types/model';
const showingNavigationDropdown = ref(false);
Expand Down Expand Up @@ -42,6 +41,11 @@ const page = usePage<{
Dashboard
</NavLink>
</div>
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<NavLink :href="route('posts.index')" :active="route().current('posts.index')">
Posts
</NavLink>
</div>
</div>

<div class="hidden sm:flex sm:items-center sm:ml-6">
Expand Down Expand Up @@ -125,6 +129,11 @@ const page = usePage<{
Dashboard
</ResponsiveNavLink>
</div>
<div class="pt-2 pb-3 space-y-1">
<ResponsiveNavLink :href="route('posts.index')" :active="route().current('posts.index')">
Posts
</ResponsiveNavLink>
</div>

<!-- Responsive Settings Options -->
<div class="pt-4 pb-1 border-t border-gray-200">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
const form = useForm({
password: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
defineProps({
status: String,
Expand Down
1 change: 0 additions & 1 deletion examples/laravel9-app/resources/js/Pages/Auth/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
defineProps({
canResetPassword: Boolean,
Expand Down
1 change: 0 additions & 1 deletion examples/laravel9-app/resources/js/Pages/Auth/Register.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
const form = useForm({
name: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { Head, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
const props = defineProps({
email: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { computed } from 'vue';
import GuestLayout from '@/Layouts/GuestLayout.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
const props = defineProps({
status: String,
Expand Down
25 changes: 25 additions & 0 deletions examples/laravel9-app/resources/js/Pages/Posts/Index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script setup lang="ts">
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Post } from '@/types/model';
import { Head, Link, usePage } from '@inertiajs/inertia-vue3';
const page = usePage<{ posts: Post[] }>()
</script>
<template>

<Head title="Posts" />

<AuthenticatedLayout>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-12">
<div v-for="post in page.props.value.posts">
<Link :href="route('posts.show', { post: String(post.id) })" class="underline hover:text-blue-500">{{ post.title }}</Link>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>

</template>
24 changes: 24 additions & 0 deletions examples/laravel9-app/resources/js/Pages/Posts/Show.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Post } from '@/types/model';
import { Head, usePage } from '@inertiajs/inertia-vue3';
const page = usePage<{ post: Post }>()
</script>
<template>

<Head title="Post" />

<AuthenticatedLayout>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div>ID: {{ route<'posts.show'>().params.post }}</div>
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-12">
<h2>{{ page.props.value.post.title }}</h2>
<p>{{ page.props.value.post.body }}</p>
</div>
</div>
</div>
</AuthenticatedLayout>

</template>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import SecondaryButton from '@/Components/SecondaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { useForm, usePage } from '@inertiajs/inertia-vue3';
import { nextTick, ref } from 'vue';
import route from 'ziggy-js';
const confirmingUserDeletion = ref(false);
const passwordInput = ref<HTMLInputElement | null>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { useForm } from '@inertiajs/inertia-vue3';
import { ref } from 'vue';
import route from 'ziggy-js';
const passwordInput = ref<HTMLInputElement | null>(null);
const currentPasswordInput = ref<HTMLInputElement | null>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import { User } from '@/types/model';
import { Link, useForm, usePage } from '@inertiajs/inertia-vue3';
import { ref } from 'vue';
import route from 'ziggy-js';
const props = defineProps({
mustVerifyEmail: Boolean,
Expand Down
1 change: 0 additions & 1 deletion examples/laravel9-app/resources/js/Pages/Welcome.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { User } from '@/types/model';
import { Head, Link, usePage } from '@inertiajs/inertia-vue3';
import route from 'ziggy-js';
defineProps({
canLogin: Boolean,
Expand Down
Loading

0 comments on commit cf4c5db

Please sign in to comment.