GithubHelp home page GithubHelp logo

momentum-trail's Introduction

Momentum Trail

Momentum Trail is a Laravel package that provides a TypeScript route() helper function that works like Laravel's, making it easy to use your Laravel named routes in TypeScript with auto-completion and type-safety.

The package is built on top of Ziggy.

Installation

Laravel

Install the package using composer.

composer require based/momentum-trail

You can publish the config file with:

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

This is the contents of the published config file:

return [
    'output' => [
        'routes' => resource_path('scripts/routes/routes.json'),
        'typescript' => resource_path('scripts/types/routes.d.ts'),
    ],
];

Set the paths according to your directory structure. You can set the routes path to null in case you plan to use the Blade directive instead of importing JSON.

Frontend

Install the frontend package.

npm i momentum-trail
# or
yarn add momentum-trail

Usage

Run the following command to generate TypeScript declarations and make your routes available on the frontend.

php artisan trail:generate

Register your routes on the frontend. You can either import the generated JSON definition and pass it to the defineRoutes method within the entry point (app.ts) or use the @trail Blade directive to register routes in the window object and make them available globally.

import { defineRoutes } from "momentum-trail"
import routes from "./routes.json"

defineRoutes(routes)

Vue 3

Alternatively, you can register routes using a Vue 3 plugin.

import { trail } from "momentum-trail"
import routes from "./routes.json"

createInertiaApp({
  setup({ el, app, props, plugin }) {
    createApp({ render: () => h(app, props) })
      .use(trail, { routes })
  }
})

Server-side rendering

The SSR engine doesn't know the current URL you are requesting.

To make the method current work correctly on the initial page load, you must pass the initial URL to the options list.

createServer((page: Page) =>
  createInertiaApp({
    setup({ App, props, plugin }) {
      return createSSRApp({ render: () => h(App, props) })
        .use(trail, {
          routes,
          url: props.initialPage.url
        })
    },
  })
)

Blade

Optionally, add the @trail Blade directive to your main layout (before your application's JavaScript).

By default, the output of the @trail Blade directive includes a list of all your application's routes and their parameters. This route list is included in the HTML of the page and can be viewed by end users.

<html>
<head>
  @trail
</head>
</html>

Import the helper in your .vue files and enjoy perfect autocompletion and type-safety for both route and current methods.

<script lang="ts" setup>
import { route, current } from "momentum-trail"

const submit = () => form.put(route("profile.settings.update"))
</script>

<template>
  <a
    :class="[current('users.*') ? 'text-black' : 'text-gray-600']"
    :href="route('users.index')">
    Users
  </a>
</template>

The route helper function works like Laravel's — you can pass it the name of one of your routes, and the parameters you want to pass to the route, and it will return a URL.

// Generate a URL
route("jobs.index")
route("jobs.show", 1)
route("jobs.show", [1])
route("jobs.show", { job: 1 })

// Check the current route
current("jobs.*")
current("jobs.show")
current("jobs.show", 1)

For the complete documentation please refer to Ziggy.

Auto-generation

The package works best with vite-plugin-watch plugin. You can set up the watcher to run the command on every file change.

import { defineConfig } from "vite"
import { watch } from "vite-plugin-watch"

export default defineConfig({
  plugins: [
    watch({
      pattern: "routes/*.php",
      command: "php artisan trail:generate",
    }),
  ],
})

Advanced Inertia

Take your Inertia.js skills to the next level with my book Advanced Inertia. Learn advanced concepts and make apps with Laravel and Inertia.js a breeze to build and maintain.

Momentum

Momentum is a set of packages designed to improve your experience building Inertia-powered apps.

  • Modal — Build dynamic modal dialogs for Inertia apps
  • Preflight — Realtime backend-driven validation for Inertia apps
  • Paginator — Headless wrapper around Laravel Pagination
  • Trail — Frontend package to use Laravel routes with Inertia
  • Lock — Frontend package to use Laravel permissions with Inertia
  • Layout — Persistent layouts for Vue 3 apps
  • Vite Plugin Watch — Vite plugin to run shell commands on file changes

Credits

License

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

momentum-trail's People

Contributors

daronspence avatar lepikhinb avatar michaeldyrynda avatar studnitz avatar sweptsquash avatar ycs77 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

momentum-trail's Issues

Route Params

The docs say refer to Ziggy docs, but many features are missing ...

Is there plan to add these missing features?

Retrieving the current route params: route().params

// Route called 'events.venues.show', with URI '/events/{event}/venues/{venue}'
// Current window URL is https://myapp.com/events/1/venues/2?authors=all

route().params; // { event: '1', venue: '2', authors: 'all' }

Laravel 10, release

Any chance you can tag a version of the master branch which contains the Laravel 10 upgrade?

ts(7016) error: The library may need to update its package.json or typings

I've been trying to get Momentum Trail working but I keep getting the follow error:

Could not find a declaration file for module 'momentum-trail'. '[..]/node_modules/momentum-trail/dist/momentum-trail.js' implicitly has an 'any' type. There are types at '[..]/node_modules/momentum-trail/dist/types/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'momentum-trail' library may need to update its package.json or typings.ts(7016)

While looking for a fix I see a couple of packages with this problem. I temporarily fixed it by adding a types/momentum-trail.d.ts with declare module 'momentum-trail'; as its content.
Problem with this is that it works locally, but when deploying it will error out.
A fix for that I read is to set the following in my jsconfig.json but that looks like a very nasty workaround that could have some other implications.

"compilerOptions": {
  "noImplicitAny": false
}

Can you fix this problem on your end, or at least document how to best go about this on the frontend for Vue 3 in the docs?

How to supply url defaults when using SSR?

I have defined a few default bindings for my app routes, which depend on the currently logged in user.

How can I supply them to trail when using SSR? For the regular app, I have set up a watcher like the one below, but it does not seem to have any effect on SSR, as I get errors like Error: Ziggy error: 'user' parameter is required for route 'user.profile'

import { defineRoutes, store } from 'momentum-trail'
import { RouteCollection } from 'momentum-trail/dist/types/types'

declare global {
    interface Window {
        trail: RouteCollection
    }
}

/**
 * This composable is used by page layout components to watch for changes in URL defaults, which
 * are provided by the HandleInertiaRequests middleware. This allows switching app context from
 * one company to another, or from guest to authenticated user without a full page reload and
 * ensures Trail/Ziggy has the correct URL defaults available at all times.
 */
export const useUrlDefaultsWatcher = () => {
    watch(
        () => usePage().props.urlDefaults,
        (defaults: object) => {
            if (typeof window !== 'undefined' && window.trail) {
                window.trail.defaults = defaults
            } else {
                defineRoutes(Object.assign(store.getRoutes(), defaults))
            }
        },
        { immediate: true },
    )
}

Issues with Laravel Vapor

Hook: trail:generate

In Filesystem.php line 190:
                                                                               
  file_put_contents(/var/task/resources/scripts/routes/routes.json): Failed to open stream: Read-only file system   

is it possible to have relative paths

Hi,

is it possible to have relative paths rather than absolute paths.

my use case is an app which can be accessed via multiple domains.

Many thanks

[Question] trail:generate VS @trail directive

Great package, thanks!

What is the difference between using the @trail directive VS the php artisan trail:generate command?
Performance? Security? ...?

Using the directive seems like the easiest option, but the fact that you didn't write it as first default solution makes me think it has some hidden downsides?
You mentioned that using the directive makes all application routes available in the window object, making them visible to end users. However, when generating the routes.json, aren't these routes also included in the final output bundle (.js) file?

I'm considering both options, so any info would be appreciated :)
Thanks

How does SSR work with momentum-trail and svelte?

Server-side rendering

The SSR engine doesn't know the current URL you are requesting.

To make the method current work correctly on the initial page load, you must pass the initial URL to the options list.

createServer((page: Page) =>
  createInertiaApp({
    setup({ App, props, plugin }) {
      return createSSRApp({ render: () => h(App, props) })
        .use(trail, {
          routes,
          url: props.initialPage.url
        })
    },
  })
)

my current SSR.ts looks like this

import { createInertiaApp } from '@inertiajs/svelte';
import createServer from '@inertiajs/svelte/server';
import type { Page } from '@inertiajs/inertia';

createServer((page: Page) =>
	createInertiaApp({
		page,
		resolve: (name) => {
			const pages = import.meta.glob('./Pages/**/*.svelte', {
				eager: true
			});
			return pages[`./Pages/${name}.svelte`];
		}
	})
);

generate routes for production

my hosting does not allow the assets to be generated in production, so I have to generate these assets on localhost, for this reason I encountered problems when using the package, having to go to the env and change the url before doing the build. Is there any way to make this process automatic?

defineRoutes export is missing

The usage section mentions using defineRoutes. However, when I try the following, I get an error: Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/momentum-trail.js?v=a54a38ca' does not provide an export named 'defineRoutes'

import { defineRoutes } from "momentum-trail"

Related to this, would it be possible to expose the store, altogether, so it's possible to get the current list of routes, defaults, etc and update them? My use-case is that I want to update the URL defaults in a multi-tenant app when the user switches the current tenant.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.