Nuxt 2 is reaching End-of-Life on June 30th, 2024.

laravel-precognition
laravel-precognition

Nuxt module to work with Laravel Precognition and $fetch

Nuxt Laravel Precognition

npm versionnpm downloadsLicenseNuxt

Module for Nuxt3, supporting Laravel Precognition using native $fetch.

This is opinionated module. Although most functionalities have been replicated to work with $fetch API, there are minor differences

Features

  • base functionalities of official modules
  • Better typescript support for objects with nested keys
  • Added queryAs and bodyAs for sending data as FormData or URLSearchParams...

Quick Setup

  1. Add nuxt-laravel-precognition dependency to your project
npx nuxi@latest module add laravel-precognition
  1. Add nuxt-laravel-precognition to the modules section of nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    'nuxt-laravel-precognition'
  ]
})
  1. Create one plugin where you initialize the $fetch client, and then use it as precognition client:
import { defineNuxtPlugin, useCookie, useNuxtApp } from '#app'

export default defineNuxtPlugin(() => {
  function getCsrfToken() {
    // grab sanctum headers
    return useCookie('XSRF-TOKEN', { default: () => '' }).value
  }

  function mergeHeaders(options: { headers?: HeadersInit }, newHeaders: HeadersInit) {
    const headersToBeMerged = new Headers(newHeaders) // cast newHeaders to Headers instance

    // check if request has headers to be merged with newHeaders
    if (!options.headers) { 
      options.headers = headersToBeMerged
      return
    }

    options.headers = new Headers(options.headers) // cast requestHeaders to Headers instance

    // merge the newHeaders with requestHeaders
    Array.from([...headersToBeMerged.entries()]).forEach(([key, value]) => {
      (options.headers as Headers).set(key, value)
    })
  }

  const api = $fetch.create({
    baseURL: 'http://localhost',
    headers: {
      Accept: 'application/json',
    },
    credentials: 'include',
    onRequest: ({ options }) => {
      const csrfToken = getCsrfToken() // read sanctum csrf token

      if (!csrfToken)
        return

      mergeHeaders(options,  ['X-XSRF-TOKEN', csrfToken]) // attach the csrf token as X-XSRF-TOKEN header
    },
  })

  const { $precognition } = useNuxtApp()

  $precognition.client.use(api)

  function fetchCsrfToken() {
    return api('/sanctum/csrf-cookie')
  }

  return {
    provide: {
      api,
      fetchCsrfToken,
    },
  }
})
  1. Remember to expose laravel Precognition Headers in your config/cors.php laravel file:
return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    */

    'paths' => ['*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [env('FRONTEND_URL', 'http://localhost:3000')],

    'allowed_headers' => ['*'],

    'exposed_headers' => ['Precognition', 'Precognition-Success'],

    'max_age' => 0,

    'supports_credentials' => true,

];
  1. You can use the useForm composable that is autoimported by this module.