text:
Script completed
Wall time 0.1 seconds
Output:

text:
Warning: truncated output (original token count: 18030)
Total output lines: 184

Warning: truncated output (original token count: 629218)
... 1468296 bytes omitted ...

vendor/livewire/livewire/src/Livewire.php:17: * @method static void setUpdateRoute($callback)
vendor/livewire/livewire/src/LivewireManager.php:158:    function setUpdateRoute($callback)
vendor/livewire/livewire/src/LivewireManager.php:160:        return app(HandleRequests::class)->setUpdateRoute($callback);
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:18:    protected $updateRoute;
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:24:        if (! $this->updateRoute && ! $this->updateRouteExists()) {
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:25:            app($this::class)->setUpdateRoute(function ($handle) {
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:35:    protected function updateRouteExists()
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:47:        // When routes are cached, $this->updateRoute may be null because
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:48:        // setUpdateRoute() was never called (the route already existed).
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:50:        $route = $this->updateRoute ?? $this->findUpdateRoute();
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:90:    function setUpdateRoute($callback)
vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:99:        $this->updateRoute = $route;
vendor/livewire/livewire/dist/livewire.min.js.map:4:  "sourcesContent": ["/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress\n * @license MIT */\n\n;(function(root, factory) {\n\n  if (typeof define === 'function' && define.amd) {\n    define(factory);\n  } else if (typeof exports === 'object') {\n    module.exports = factory();\n  } else {\n    root.NProgress = factory();\n  }\n\n})(this, function() {\n  var NProgress = {};\n\n  NProgress.version = '0.2.0';\n\n  var Settings = NProgress.settings = {\n    minimum: 0.08,\n    easing: 'ease',\n    positionUsing: '',\n    speed: 200,\n    trickle: true,\n    trickleRate: 0.02,\n    trickleSpeed: 800,\n    showSpinner: true,\n    barSelector: '[role=\"bar\"]',\n    spinnerSelector: '[role=\"spinner\"]',\n    parent: 'body',\n    template: '

'\n  };\n\n  /**\n   * Updates configuration.\n   *\n   *     NProgress.configure({\n   *       minimum: 0.1\n   *     });\n   */\n  NProgress.configure = function(options) {\n    var key, value;\n    for (key in options) {\n      value = options[key];\n      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n    }\n\n    return this;\n  };\n\n  /**\n   * Last number.\n   */\n\n  NProgress.status = null;\n\n  /**\n   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n   *\n   *     NProgress.set(0.4);\n   *     NProgress.set(1.0);\n   */\n\n  NProgress.set = function(n) {\n    var started = NProgress.isStarted();\n\n    n = clamp(n, Settings.minimum, 1);\n    NProgress.status = (n === 1 ? null : n);\n\n    var progress = NProgress.render(!started),\n        bar      = progress.querySelector(Settings.barSelector),\n        speed    = Settings.speed,\n        ease     = Settings.easing;\n\n    progress.offsetWidth; /* Repaint */\n\n    queue(function(next) {\n      // Set positionUsing if it hasn't already been set\n      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n      // Add transition\n      css(bar, barPositionCSS(n, speed, ease));\n\n      if (n === 1) {\n        // Fade out\n        css(progress, { \n          transition: 'none', \n          opacity: 1 \n        });\n        progress.offsetWidth; /* Repaint */\n\n        setTimeout(function() {\n          css(progress, { \n            transition: 'all ' + speed + 'ms linear', \n            opacity: 0 \n          });\n          setTimeout(function() {\n            NProgress.remove();\n            next();\n          }, speed);\n        }, speed);\n      } else {\n        setTimeout(next, speed);\n      }\n    });\n\n    return this;\n  };\n\n  NProgress.isStarted = function() {\n    return typeof NProgress.status === 'number';\n  };\n\n  /**\n   * Shows the progress bar.\n   * This is the same as setting the status to 0%, except that it doesn't go backwards.\n   *\n   *     NProgress.start();\n   *\n   */\n  NProgress.start = function() {\n    if (!NProgress.status) NProgress.set(0);\n\n    var work = function() {\n      setTimeout(function() {\n        if (!NProgress.status) return;\n        NProgress.trickle();\n        work();\n      }, Settings.trickleSpeed);\n    };\n\n    if (Settings.trickle) work();\n\n    return this;\n  };\n\n  /**\n   * Hides the progress bar.\n   * This is the *sort of* the same as setting the status to 100%, with the\n   * difference being `done()` makes some placebo effect of some realistic motion.\n   *\n   *     NProgress.done();\n   *\n   * If `true` is passed, it will show the progress bar even if its hidden.\n   *\n   *     NProgress.done(true);\n   */\n\n  NProgress.done = function(force) {\n    if (!force && !NProgress.status) return this;\n\n    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n  };\n\n  /**\n   * Increments by a random amount.\n   */\n\n  NProgress.inc = function(amount) {\n    var n = NProgress.status;\n\n    if (!n) {\n      return NProgress.start();\n    } else {\n      if (typeof amount !== 'number') {\n        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n      }\n\n      n = clamp(n + amount, 0, 0.994);\n      return NProgress.set(n);\n    }\n  };\n\n  NProgress.trickle = function() {\n    return NProgress.inc(Math.random() * Settings.trickleRate);\n  };\n\n  /**\n   * Waits for all supplied jQuery promises and\n   * increases the progress as the promises resolve.\n   *\n   * @param $promise jQUery Promise\n   */\n  (function() {\n    var initial = 0, current = 0;\n\n    NProgress.promise = function($promise) {\n      if (!$promise || $promise.state() === \"resolved\") {\n        return this;\n      }\n\n      if (current === 0) {\n        NProgress.start();\n      }\n\n      initial++;\n      current++;\n\n      $promise.always(function() {\n        current--;\n        if (current === 0) {\n            initial = 0;\n            NProgress.done();\n        } else {\n            NProgress.set((initial - current) / initial);\n        }\n      });\n\n      return this;\n    };\n\n  })();\n\n  /**\n   * (Internal) renders the progress bar markup based on the `template`\n   * setting.\n   */\n\n  NProgress.render = function(fromStart) {\n    if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n    addClass(document.documentElement, 'nprogress-busy');\n    \n    var progress = document.createElement('div');\n    progress.id = 'nprogress';\n    progress.innerHTML = Settings.template;\n\n    var bar      = progress.querySelector(Settings.barSelector),\n        perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n        parent   = document.querySelector(Settings.parent),\n        spinner;\n    \n    css(bar, {\n      transition: 'all 0 linear',\n      transform: 'translate3d(' + perc + '%,0,0)'\n    });\n\n    if (!Settings.showSpinner) {\n      spinner = progress.querySelector(Settings.spinnerSelector);\n      spinner && removeElement(spinner);\n    }\n\n    if (parent != document.body) {\n      addClass(parent, 'nprogress-custom-parent');\n    }\n\n    parent.appendChild(progress);\n    return progress;\n  };\n\n  /**\n   * Removes the element. Opposite of render().\n   */\n\n  NProgress.remove = function() {\n    removeClass(document.documentElement, 'nprogress-busy');\n    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n    var progress = document.getElementById('nprogress');\n    progress && removeElement(progress);\n  };\n\n  /**\n   * Checks if the progress bar is rendered.\n   */\n\n  NProgress.isRendered = function() {\n    return !!document.getElementById('nprogress');\n  };\n\n  /**\n   * Determine which positioning CSS rule to use.\n   */\n\n  NProgress.getPositioningCSS = function() {\n    // Sniff on document.body.style\n    var bodyStyle = document.body.style;\n\n    // Sniff prefixes\n    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n                       ('MozTransform' in bodyStyle) ? 'Moz' :\n                       ('msTransform' in bodyStyle) ? 'ms' :\n                       ('OTransform' in bodyStyle) ? 'O' : '';\n\n    if (vendorPrefix + 'Perspective' in bodyStyle) {\n      // Modern browsers with 3D support, e.g. Webkit, IE10\n      return 'translate3d';\n    } else if (vendorPrefix + 'Transform' in bodyStyle) {\n      // Browsers without 3D support, e.g. IE9\n      return 'translate';\n    } else {\n      // Browsers without translate() support, e.g. IE7-8\n      return 'margin';\n    }\n  };\n\n  /**\n   * Helpers\n   */\n\n  function clamp(n, min, max) {\n    if (n < min) return min;\n    if (n > max) return max;\n    return n;\n  }\n\n  /**\n   * (Internal) converts a percentage (`0..1`) to a bar translateX\n   * percentage (`-100%..0%`).\n   */\n\n  function toBarPerc(n) {\n    return (-1 + n) * 100;\n  }\n\n\n  /**\n   * (Internal) returns the correct CSS for changing the bar's\n   * position given an n percentage, and speed and ease from Settings\n   */\n\n  function barPositionCSS(n, speed, ease) {\n    var barCSS;\n\n    if (Settings.positionUsing === 'translate3d') {\n      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n    } else if (Settings.positionUsing === 'translate') {\n      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n    } else {\n      barCSS = { 'margin-left': toBarPerc(n)+'%' };\n    }\n\n    barCSS.transition = 'all '+speed+'ms '+ease;\n\n    return barCSS;\n  }\n\n  /**\n   * (Internal) Queues a function to be executed.\n   */\n\n  var queue = (function() {\n    var pending = [];\n    \n    function next() {\n      var fn = pending.shift();\n      if (fn) {\n        fn(next);\n      }\n    }\n\n    return function(fn) {\n      pending.push(fn);\n      if (pending.length == 1) next();\n    };\n  })();\n\n  /**\n   * (Internal) Applies css properties to an element, similar to the jQuery \n   * css method.\n   *\n   * While this helper does assist with vendor prefixed property names, it \n   * does not perform any manipulation of values prior to setting styles.\n   */\n\n  var css = (function() {\n    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n        cssProps    = {};\n\n    function camelCase(string) {\n      return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n        return letter.toUpperCase();\n      });\n    }\n\n    function getVendorProp(name) {\n      var style = document.body.style;\n      if (name in style) return name;\n\n      var i = cssPrefixes.length,\n          capName = name.charAt(0).toUpperCase() + name.slice(1),\n          vendorName;\n      while (i--) {\n        vendorName = cssPrefixes[i] + capName;\n        if (vendorName in style) return vendorName;\n      }\n\n      return name;\n    }\n\n    function getStyleProp(name) {\n      name = camelCase(name);\n      return cssProps[name] || (cssProps[name] = getVendorProp(name));\n    }\n\n    function applyCss(element, prop, value) {\n      prop = getStyleProp(prop);\n      element.style[prop] = value;\n    }\n\n    return function(element, properties) {\n      var args = arguments,\n          prop, \n          value;\n\n      if (args.length == 2) {\n        for (prop in properties) {\n          value = properties[prop];\n          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n        }\n      } else {\n        applyCss(element, args[1], args[2]);\n      }\n    }\n  })();\n\n  /**\n   * (Internal) Determines if an element or space separated list of class names contains a class name.\n   */\n\n  function hasClass(element, name) {\n    var list = typeof element == 'string' ? element : classList(element);\n    return list.indexOf(' ' + name + ' ') >= 0;\n  }\n\n  /**\n   * (Internal) Adds a class to an element.\n   */\n\n  function addClass(element, name) {\n    var oldList = classList(element),\n        newList = oldList + name;\n\n    if (hasClass(oldList, name)) return; \n\n    // Trim the opening space.\n    element.className = newList.substring(1);\n  }\n\n  /**\n   * (Internal) Removes a class from an element.\n   */\n\n  function removeClass(element, name) {\n    var oldList = classList(element),\n        newList;\n\n    if (!hasClass(element, name)) return;\n\n    // Replace the class name.\n    newList = oldList.replace(' ' + name + ' ', ' ');\n\n    // Trim the opening and closing spaces.\n    element.className = newList.substring(1, newList.length - 1);\n  }\n\n  /**\n   * (Internal) Gets a space separated list of the class names on the element. \n   * The list is wrapped with a single space on each end to facilitate finding \n   * matches within the list.\n   */\n\n  function classList(element) {\n    return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n  }\n\n  /**\n   * (Internal) Removes an element from the DOM.\n   */\n\n  function removeElement(element) {\n    element && element.parentNode && element.parentNode.removeChild(element);\n  }\n\n  return NProgress;\n});\n\n", "\nexport class Bag {\n    constructor() { this.arrays = {} }\n\n    add(key, value) {\n        if (! this.arrays[key]) this.arrays[key] = []\n        this.arrays[key].push(value)\n    }\n\n    remove(key) {\n        if (this.arrays[key]) delete this.arrays[key]\n    }\n\n    get(key) { return this.arrays[key] || [] }\n\n    each(key, callback) { return this.get(key).forEach(callback) }\n}\n\nexport class WeakBag {\n    constructor() { this.arrays = new WeakMap }\n\n    add(key, value) {\n        if (! this.arrays.has(key)) this.arrays.set(key, [])\n        this.arrays.get(key).push(value)\n    }\n\n    remove(key) {\n        if (this.arrays.has(key)) this.arrays.delete(key, [])\n    }\n\n    get(key) { return this.arrays.has(key) ? this.arrays.get(key) : [] }\n\n    each(key, callback) { return this.get(key).forEach(callback) }\n}\n\nexport function dispatch(target, name, detail = {}, bubbles = true) {\n    target.dispatchEvent(\n        new CustomEvent(name, {\n            detail,\n            bubbles,\n            // Allows events to pass the shadow DOM barrier.\n            composed: true,\n            cancelable: true,\n        })\n    )\n}\n\nexport function listen(target, name, handler) {\n    target.addEventListener(name, handler)\n\n    return () => target.removeEventListener(name, handler)\n}\n\n/**\n * Type-checking in JS is weird and annoying, these are better.\n */\nexport function isObjecty(subject) { return (typeof subject === 'object' && subject !== null) }\nexport function isObject(subject) { return (isObjecty(subject) && ! isArray(subject)) }\nexport function isArray(subject) { return Array.isArray(subject) }\nexport function isFunction(subject) { return typeof subject === 'function' }\nexport function isPrimitive(subject) { return typeof subject !== 'object' || subject === null }\n\n/**\n * Clone an object deeply to wipe out any shared references.\n */\nexport function deepClone(obj) { return JSON.parse(JSON.stringify(obj)) }\n\n/**\n * Determine if two objects take the exact same shape.\n */\nexport function deeplyEqual(a, b) { return JSON.stringify(a) === JSON.stringify(b) }\n\n/**\n * An easy way to loop through arrays and objects.\n */\nexport function each(subject, callback) {\n    Object.entries(subject).forEach(([key, value]) => callback(key, value))\n}\n\n/**\n * Parse a path string into segments, supporting dot and bracket notation.\n * e.g. \"foo.bar\", \"foo[0].bar\", \"foo['hey'].baz\"\n */\nfunction parsePathSegments(path) {\n    if (path === '') return []\n\n    return path\n        .replace(/\\[(['\"]?)(.+?)\\1\\]/g, '.$2')  // Convert brackets to dots: foo['bar'] \u2192 foo.bar, foo[0] \u2192 foo.0\n        .replace(/^\\./, '')                      // Remove leading dot if present\n        .split('.')\n}\n\n/**\n * Get a property from an object with support for dot-notation and bracket-notation.\n */\nexport function dataGet(object, key) {\n    if (key === '') return object\n\n    return parsePathSegments(key).reduce((carry, i) => {\n        return carry?.[i]\n    }, object)\n}\n\n/**\n * Set a property on an object with support for dot-notation and bracket-notation.\n */\nexport function dataSet(object, key, value) {\n    let segments = parsePathSegments(key)\n\n    if (segments.length === 1) {\n        return object[segments[0]] = value\n    }\n\n    let firstSegment = segments.shift()\n    let restOfSegments = segments.join('.')\n    let nextSegment = segments[0]\n\n    if (object[firstSegment] === undefined) {\n        object[firstSegment] = {}\n    }\n\n    // If we're about to set a numeric key that would create null gaps, convert to object.\n    // This prevents JavaScript from filling intermediate indices with nulls\n    // (e.g., arr[1000] = true creates 1000 null entries in a JS array).\n    // We only convert when the key would create gaps (key > length), not when appending.\n    if (isArray(object[firstSegment]) && isNumeric(nextSegment) && parseInt(nextSegment) > object[firstSegment].length) {\n        object[firstSegment] = { ...object[firstSegment] }\n    }\n\n    dataSet(object[firstSegment], restOfSegments, value)\n}\n\nfunction isNumeric(subject) {\n    return ! isNaN(parseInt(subject))\n}\n\n/**\n * Delete a property from an object with support for dot-notation and bracket-notation.\n */\nexport function dataDelete(object, key) {\n    let segments = parsePathSegments(key)\n\n    if (segments.length === 1) {\n        if (Array.isArray(object)) {\n            object.splice(segments[0], 1)\n        } else {\n            delete object[segments[0]]\n        }\n        return\n    }\n\n    let firstSegment = segments.shift()\n    let restOfSegments = segments.join('.')\n\n    if (object[firstSegment] !== undefined) {\n        dataDelete(object[firstSegment], restOfSegments)\n    }\n}\n\n/**\n * Create a flat, dot-notated diff of two objects.\n * @deprecated Use diffAndConsolidate instead for smarter update consolidation\n */\nexport function diff(left, right, diffs = {}, path = '') {\n    // Are they the same?\n    if (left === right) return diffs\n\n    // Are they COMPLETELY different?\n    if (typeof left !== typeof right || (isObject(left) && isArray(right)) || (isArray(left) && isObject(right))) {\n        diffs[path] = right;\n        return diffs\n    }\n\n    // Is the right or left side a primitive value (a leaf node)?\n    if (isPrimitive(left) || isPrimitive(right)) {\n        diffs[path] = right\n        return diffs\n    }\n\n    // We now know both are objects...\n    let leftKeys = Object.keys(left)\n\n    // Recursively diff the object's properties...\n    Object.entries(right).forEach(([key, value]) => {\n        diffs = {...diffs, ...diff(left[key], right[key], diffs, path === '' ? key : `${path}.${key}`)}\n        leftKeys = leftKeys.filter(i => i !== key)\n    })\n\n    // Mark any items for removal...\n    leftKeys.forEach(key => {\n        diffs[`${path}.${key}`] = '__rm__'\n    })\n\n    return diffs\n}\n\n/**\n * Create a flat, dot-notated diff of two objects with automatic consolidation.\n * When multiple items in an array/object change or the size changes,\n * the diff is consolidated to the parent level instead of individual items.\n */\nexport function diffAndConsolidate(left, right) …8030 tokens truncated… } from '@/request'\nimport Alpine from 'alpinejs'\n\ndirective('model', ({ el, directive, component, cleanup }) => {\n    // @todo: will need to probaby do this further upstream i just don't want to bog down the entire lifecycle right now...\n    // this is to support slots properly...\n    component = findComponentByEl(el)\n\n    let { expression, modifiers } = directive\n\n    if (! expression) {\n        return console.warn('Livewire: [wire:model] is missing a value.', el)\n    }\n\n    if (componentIsMissingProperty(component, expression)) {\n        return console.warn('Livewire: [wire:model=\"'+expression+'\"] property does not exist on component: ['+component.name+']', el)\n    }\n\n    // Handle file uploads differently...\n    if (el.type && el.type.toLowerCase() === 'file') {\n        return handleFileUpload(el, expression, component, cleanup)\n    }\n\n    // Split modifiers at .live boundary\n    // Modifiers BEFORE .live control client-side (x-model) sync timing\n    // Modifiers AFTER .live control network request timing\n    let liveIndex = modifiers.indexOf('live')\n    let isLive = liveIndex !== -1\n\n    // Backwards compatibility: .lazy without .live implies .change.live\n    let hasLazyWithoutLive = modifiers.includes('lazy') && ! isLive\n    let shouldSendNetwork = isLive || hasLazyWithoutLive\n\n    let ephemeralModifiers = isLive && ! hasLazyWithoutLive ? modifiers.slice(0, liveIndex) : modifiers.slice()\n    let networkModifiers = isLive && ! hasLazyWithoutLive ? modifiers.slice(liveIndex + 1) : []\n\n    // For .lazy backwards compat, trigger network on change\n    if (hasLazyWithoutLive) {\n        // Remove 'lazy' from ephemeralModifiers for .lazy backwards compat\n        ephemeralModifiers = ephemeralModifiers.filter(m => m !== 'lazy')\n        networkModifiers.push('change')\n    }\n\n    // Add self/deep modifier for event propagation control\n    if (! (ephemeralModifiers.includes('deep') || networkModifiers.includes('deep'))) {\n        if (! ephemeralModifiers.includes('self')) {\n            ephemeralModifiers.push('self')\n        }\n    }\n\n    // Extract ephemeral trigger modifiers (these control when x-model syncs)\n    let ephemeralOnBlur = ephemeralModifiers.includes('blur')\n    let ephemeralOnChange = ephemeralModifiers.includes('change') || ephemeralModifiers.includes('lazy')\n    let ephemeralOnEnter = ephemeralModifiers.includes('enter')\n    let hasEphemeralTriggers = ephemeralOnBlur || ephemeralOnChange || ephemeralOnEnter\n\n    // Extract network trigger modifiers\n    let networkOnBlur = networkModifiers.includes('blur')\n    let networkOnChange = networkModifiers.includes('change') || networkModifiers.includes('lazy')\n    let networkOnEnter = networkModifiers.includes('enter')\n    let hasNetworkTriggers = networkOnBlur || networkOnChange || networkOnEnter\n    let isDebounced = networkModifiers.includes('debounce')\n    let isThrottled = networkModifiers.includes('throttle')\n\n    // Trigger a network request\n    let update = () => {\n        setNextActionOrigin({ el, directive })\n\n        if (isLive || isDebounced) {\n            setNextActionMetadata({ type: 'model.live' })\n        }\n\n        expression.startsWith('$parent')\n            ? component.$wire.$parent.$commit()\n            : component.$wire.$commit()\n    }\n\n    let debouncedUpdate = update\n\n    // Apply debounce/throttle from network modifiers\n    if ((shouldSendNetwork && ! hasNetworkTriggers && isRealtimeInput(el)) || isDebounced) {\n        debouncedUpdate = debounce(debouncedUpdate, parseModifierDuration(networkModifiers, 'debounce') || 150)\n    }\n\n    if (isThrottled) {\n        debouncedUpdate = throttle(debouncedUpdate, parseModifierDuration(networkModifiers, 'throttle') || 150)\n    }\n\n    // Build the bindings object\n    let bindings = {}\n\n    // Network event listeners (for modifiers after .live, or .lazy backwards compat)\n    if (shouldSendNetwork && networkOnBlur) {\n        bindings['@blur'] = () => update()\n    }\n\n    if (shouldSendNetwork && networkOnChange) {\n        bindings['@change'] = () => update()\n    }\n\n    if (shouldSendNetwork && networkOnEnter) {\n        bindings['@keydown.enter'] = () => update()\n    }\n\n    // Build x-model modifier tail from ephemeral modifiers\n    let xModelTail = getModifierTail(ephemeralModifiers)\n\n    bindings['x-model' + xModelTail] = () => {\n        return {\n            get() {\n                return dataGet(component.$wire, expression)\n            },\n            set(value) {\n                dataSet(component.$wire, expression, value)\n\n                // If .live is present and no specific network triggers, fire on every ephemeral sync\n                if (shouldSendNetwork && ! hasNetworkTriggers) {\n                    debouncedUpdate()\n                }\n            },\n        }\n    }\n\n    Alpine.bind(el, bindings)\n})\n\nfunction getModifierTail(modifiers) {\n    // Filter out Livewire-specific modifiers that shouldn't go to x-model\n    // Keep: blur, change, lazy, enter, self, deep, number, boolean, trim, fill\n    // Remove: defer, live, debounce, throttle (and their durations)\n    modifiers = modifiers.filter(i => ! [\n        'defer', 'live'\n    ].includes(i))\n\n    if (modifiers.includes('debounce')) {\n        let index = modifiers.indexOf('debounce')\n        let hasDuration = parseModifierDuration(modifiers, 'debounce') !== undefined\n\n        // Delete the subsequent modifier if it's a duration...\n        modifiers.splice(index, hasDuration ? 2 : 1)\n    }\n\n    if (modifiers.includes('throttle')) {\n        let index = modifiers.indexOf('throttle')\n        let hasDuration = parseModifierDuration(modifiers, 'throttle') !== undefined\n\n        // Delete the subsequent modifier if it's a duration...\n        modifiers.splice(index, hasDuration ? 2 : 1)\n    }\n\n    if (modifiers.length === 0) return ''\n\n    return '.' + modifiers.join('.')\n}\n\nfunction isRealtimeInput(el) {\n    return (\n        ['INPUT', 'TEXTAREA'].includes(el.tagName.toUpperCase()) &&\n        !['checkbox', 'radio'].includes(el.type)\n    )\n        || el.tagName.toUpperCase() === 'UI-SLIDER' // Flux UI\n        || el.tagName.toUpperCase() === 'UI-COMPOSER' // Flux UI\n}\n\nfunction isDirty(subject, dirty) {\n    // Check for exact match: wire:model=\"bob\" in ['bob']\n    if (dirty.includes(subject)) return true\n\n    // Check case of parent: wire:model=\"bob.1\" in ['bob']\n    return dirty.some(i => subject.startsWith(i))\n}\n\nfunction componentIsMissingProperty(component, property) {\n    if (property.startsWith('$parent')) {\n        let parent = findComponentByEl(component.el.parentElement, false)\n\n        if (! parent) return true\n\n        return componentIsMissingProperty(parent, property.slice(7).replace(/^\\./, ''))\n    }\n\n    // Extract base property, handling both \"foo.bar\" and \"['foo'].bar\"\n    let match = property.match(/^\\[['\"]?([^\\]'\"]+)['\"]?\\]/) || property.match(/^([^.\\[]+)/)\n    let baseProperty = match[1]\n\n    return ! Object.keys(component.canonical).includes(baseProperty)\n}\n\nfunction debounce(func, wait) {\n    var timeout;\n\n    return function() {\n      var context = this, args = arguments;\n\n      var later = function() {\n            timeout = null\n\n            func.apply(context, args)\n      }\n\n      clearTimeout(timeout)\n\n      timeout = setTimeout(later, wait)\n    }\n}\n\nfunction throttle(func, limit) {\n    let inThrottle\n\n    return function() {\n        let context = this, args = arguments\n\n        if (! inThrottle) {\n            func.apply(context, args)\n\n            inThrottle = true\n\n            setTimeout(() => inThrottle = false, limit)\n        }\n    }\n}\n\nfunction parseModifierDuration(modifiers, key) {\n    let index = modifiers.indexOf(key)\n    if (index === -1) return undefined\n\n    let nextModifier = modifiers[modifiers.indexOf(key)+1] || 'invalid-wait'\n    let duration = nextModifier.split('ms')[0]\n\n    return ! isNaN(duration) ? duration : undefined\n}", "import { directive } from \"@/directives\"\nimport { evaluateActionExpression } from '../evaluator'\nimport { setNextActionOrigin } from \"@/request\"\n\ndirective('init', ({ component, el, directive }) => {\n    let fullMethod = directive.expression ? directive.expression : '$refresh'\n\n    setNextActionOrigin({ el, directive })\n\n    evaluateActionExpression(el, fullMethod)\n})\n", "import { directive, getDirectives } from \"@/directives\"\nimport { setNextActionMetadata, setNextActionOrigin } from '@/request'\nimport { evaluateActionExpression } from '../evaluator'\n\ndirective('poll', ({ el, directive, component }) => {\n    let interval = extractDurationFrom(directive.modifiers, 2000)\n\n    let { start, pauseWhile, throttleWhile, stopWhen } = poll(() => {\n        triggerComponentRequest(el, directive, component)\n    }, interval)\n\n    start()\n\n    throttleWhile(() => theTabIsInTheBackground() && theDirectiveIsMissingKeepAlive(directive))\n    pauseWhile(() => theDirectiveHasVisible(directive) && theElementIsNotInTheViewport(el))\n    pauseWhile(() => theDirectiveIsOffTheElement(el))\n    pauseWhile(() => livewireIsOffline())\n    stopWhen(() => theElementIsDisconnected(el))\n})\n\nfunction triggerComponentRequest(el, directive, component) {\n    // Set targetEl to null to prevent data-loading on poll actions\n    setNextActionOrigin({ el, directive, targetEl: null })\n    setNextActionMetadata({ type: 'poll' })\n\n    let fullMethod = directive.expression ? directive.expression : '$refresh'\n\n    evaluateActionExpression(el, fullMethod)\n}\n\nexport function poll(callback, interval = 2000) {\n    let pauseConditions = []\n    let throttleConditions = []\n    let stopConditions = []\n\n    return {\n        start() {\n            let clear = syncronizedInterval(interval, () => {\n                if (stopConditions.some(i => i())) return clear()\n                if (pauseConditions.some(i => i())) return\n                if (throttleConditions.some(i => i()) && Math.random() < .95) return\n\n                callback()\n            })\n        },\n        pauseWhile(condition) {\n            pauseConditions.push(condition)\n        },\n        throttleWhile(condition) {\n            throttleConditions.push(condition)\n        },\n        stopWhen(condition) {\n            stopConditions.push(condition)\n        }\n    }\n}\n\nlet clocks = []\n\nfunction syncronizedInterval(ms, callback) {\n    if (! clocks[ms]) {\n        let clock = {\n            timer: setInterval(() => clock.callbacks.forEach(i => i()), ms),\n            callbacks: new Set,\n        }\n\n        clocks[ms] = clock\n    }\n\n    clocks[ms].callbacks.add(callback)\n\n    return () => {\n        clocks[ms].callbacks.delete(callback)\n\n        if (clocks[ms].callbacks.size === 0) {\n            clearInterval(clocks[ms].timer)\n            delete clocks[ms]\n        }\n    }\n}\n\nlet isOffline = false\n\nwindow.addEventListener('offline', () => isOffline = true)\nwindow.addEventListener('online', () => isOffline = false)\n\nexport function livewireIsOffline() {\n    return isOffline\n}\n\nlet inBackground = false\n\ndocument.addEventListener('visibilitychange', () => { inBackground = document.hidden }, false)\n\nfunction theTabIsInTheBackground() {\n    return inBackground\n}\n\nfunction theDirectiveIsOffTheElement(el) {\n    return ! getDirectives(el).has('poll')\n}\n\nfunction theDirectiveIsMissingKeepAlive(directive) {\n    return ! directive.modifiers.includes('keep-alive')\n}\n\nfunction theDirectiveHasVisible(directive) {\n    return directive.modifiers.includes('visible')\n}\n\nfunction theElementIsNotInTheViewport(el) {\n    let bounding = el.getBoundingClientRect()\n\n    return ! (\n        bounding.top < (window.innerHeight || document.documentElement.clientHeight) &&\n        bounding.left < (window.innerWidth || document.documentElement.clientWidth) &&\n        bounding.bottom > 0 &&\n        bounding.right > 0\n    )\n}\n\nexport function theElementIsDisconnected(el) {\n    return el.isConnected === false\n}\n\nexport function extractDurationFrom(modifiers, defaultDuration) {\n    let durationInMilliSeconds\n    let durationInMilliSecondsString = modifiers.find(mod => mod.match(/([0-9]+)ms/))\n    let durationInSecondsString = modifiers.find(mod => mod.match(/([0-9]+)s/))\n\n    if (durationInMilliSecondsString) {\n        durationInMilliSeconds = Number(durationInMilliSecondsString.replace('ms', ''))\n    } else if (durationInSecondsString) {\n        durationInMilliSeconds = Number(durationInSecondsString.replace('s', '')) * 1000\n    }\n\n    return durationInMilliSeconds || defaultDuration\n}\n", "import { evaluateActionExpression } from '../evaluator'\nimport Alpine from 'alpinejs'\n\nAlpine.interceptInit(el => {\n    for (let i = 0; i < el.attributes.length; i++) {\n        if (el.attributes[i].name.startsWith('wire:show')) {\n            let { name, value } = el.attributes[i]\n\n            let modifierString = name.split('wire:show')[1]\n\n            let expression = value.trim()\n\n            Alpine.bind(el, {\n                ['x-show' + modifierString]() {\n                    return evaluateActionExpression(el, expression)\n                }\n            })\n        }\n    }\n})", "import Alpine from 'alpinejs'\nimport { evaluateActionExpression } from '../evaluator'\n\nAlpine.interceptInit(el => {\n    for (let i = 0; i < el.attributes.length; i++) {\n        if (el.attributes[i].name.startsWith('wire:text')) {\n            let { name, value } = el.attributes[i]\n\n            let modifierString = name.split('wire:text')[1]\n\n            let expression = value.trim()\n\n            Alpine.bind(el, {\n                ['x-text' + modifierString]() {\n                    return evaluateActionExpression(el, expression)\n                }\n            })\n        }\n    }\n})\n", "import Alpine from 'alpinejs'\nimport { evaluateActionExpression } from '../evaluator'\n\nAlpine.interceptInit(el => {\n    for (let i = 0; i < el.attributes.length; i++) {\n        if (el.attributes[i].name.startsWith('wire:bind:')) {\n            let { name, value } = el.attributes[i]\n\n            let remainder = name.split('wire:bind')[1]\n\n            let expression = value.trim()\n\n            Alpine.bind(el, {\n                ['x-bind' + remainder]() {\n                    return evaluateActionExpression(el, expression)\n                }\n            })\n        }\n    }\n})\n"],
<?php

namespace App\Providers;

use App\Auth\CustomerUserProvider;
use App\Contracts\PaymentProvider as PaymentProviderContract;
use App\Models\Product;
use App\Observers\ProductObserver;
use App\Services\MockPaymentProvider;
use Carbon\CarbonImmutable;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->bind(PaymentProviderContract::class, MockPaymentProvider::class);
        Auth::provider('customer', fn ($app, array $config): CustomerUserProvider => new CustomerUserProvider($app['hash'], $config['model']));
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureDefaults();
        Model::preventLazyLoading(! app()->isProduction());
        Product::observe(ProductObserver::class);
        RateLimiter::for('login', fn (Request $request): Limit => Limit::perMinute(5)->by($request->ip()));
        RateLimiter::for('api.storefront', fn (Request $request): Limit => Limit::perMinute(120)->by($request->ip()));
        RateLimiter::for('checkout', fn (Request $request): Limit => Limit::perMinute(10)->by($request->hasSession() ? $request->session()->getId() : $request->ip()));
    }

    /**
     * Configure default behaviors for production-ready applications.
     */
    protected function configureDefaults(): void
    {
        Date::use(CarbonImmutable::class);

        DB::prohibitDestructiveCommands(
            app()->isProduction(),
        );

        Password::defaults(fn (): ?Password => app()->isProduction()
            ? Password::min(12)
                ->mixedCase()
                ->letters()
                ->numbers()
                ->symbols()
                ->uncompromised()
            : null
        );
    }
}
<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Fortify\Fortify;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureActions();
        $this->configureViews();
        $this->configureRateLimiting();
    }

    /**
     * Configure Fortify actions.
     */
    private function configureActions(): void
    {
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
        Fortify::createUsersUsing(CreateNewUser::class);
    }

    /**
     * Configure Fortify views.
     */
    private function configureViews(): void
    {
        Fortify::loginView(fn () => view('livewire.auth.login'));
        Fortify::verifyEmailView(fn () => view('livewire.auth.verify-email'));
        Fortify::twoFactorChallengeView(fn () => view('livewire.auth.two-factor-challenge'));
        Fortify::confirmPasswordView(fn () => view('livewire.auth.confirm-password'));
        Fortify::registerView(fn () => view('livewire.auth.register'));
        Fortify::resetPasswordView(fn () => view('livewire.auth.reset-password'));
        Fortify::requestPasswordResetLinkView(fn () => view('livewire.auth.forgot-password'));
    }

    /**
     * Configure rate limiting.
     */
    private function configureRateLimiting(): void
    {
        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });

        RateLimiter::for('login', function (Request $request) {
            $throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip());

            return Limit::perMinute(5)->by($throttleKey);
        });
    }
}
<?php

use App\Livewire\Settings\Appearance;
use App\Livewire\Settings\Password;
use App\Livewire\Settings\Profile;
use App\Livewire\Settings\TwoFactor;
use Illuminate\Support\Facades\Route;
use Laravel\Fortify\Features;

Route::middleware(['auth'])->group(function () {
    Route::redirect('settings', 'settings/profile');

    Route::livewire('settings/profile', Profile::class)->name('profile.edit');
});

Route::middleware(['auth', 'verified'])->group(function () {
    Route::livewire('settings/password', Password::class)->name('user-password.edit');
    Route::livewire('settings/appearance', Appearance::class)->name('appearance.edit');

    Route::livewire('settings/two-factor', TwoFactor::class)
        ->middleware(
            when(
                Features::canManageTwoFactorAuthentication()
                && Features::optionEnabled(Features::twoFactorAuthentication(), 'confirmPassword'),
                ['password.confirm'],
                [],
            ),
        )
        ->name('two-factor.show');
});


exec

status: completed

input:
const r = await tools.exec_command({cmd:"sed -n '1,125p' vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php && sed -n '1,120p' vendor/livewire/livewire/src/LivewireServiceProvider.php 2>/dev/null || true && rg -n \"LivewireServiceProvider\" vendor/livewire/livewire/src -g'*.php' | head","workdir":"/Users/wesner/Herd/shop","yield_time_ms":10000,"max_output_tokens":10000});
text(r.output);


type: CommandExecution

command: sed -n '1,125p' vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php && sed -n '1,120p' vendor/livewire/livewire/src/LivewireServiceProvider.php 2>/dev/null || true && rg -n "LivewireServiceProvider" vendor/livewire/livewire/src -g'*.php' | head

type: unknown

status: completed

stdout:
<?php

namespace Livewire\Mechanisms\HandleRequests;

use Illuminate\Http\Response;
use Illuminate\Support\Facades\Route;
use Livewire\Features\SupportScriptsAndAssets\SupportScriptsAndAssets;
use Livewire\Mechanisms\HandleRequests\EndpointResolver;
use Livewire\Exceptions\PayloadTooLargeException;
use Livewire\Exceptions\TooManyComponentsException;

use Livewire\Mechanisms\Mechanism;

use function Livewire\trigger;

class HandleRequests extends Mechanism
{
    protected $updateRoute;

    function boot()
    {
        // Register the default route immediately (before routes files load)
        // so it's positioned before any catch-all routes.
        if (! $this->updateRoute && ! $this->updateRouteExists()) {
            app($this::class)->setUpdateRoute(function ($handle) {
                return Route::post(EndpointResolver::updatePath(), $handle)
                    ->middleware('web')
                    ->name('default-livewire.update');
            });
        }

        $this->skipRequestPayloadTamperingMiddleware();
    }

    protected function updateRouteExists()
    {
        return $this->findUpdateRoute() !== null;
    }

    function getUriPrefix()
    {
        return EndpointResolver::prefix();
    }

    function getUpdateUri()
    {
        // When routes are cached, $this->updateRoute may be null because
        // setUpdateRoute() was never called (the route already existed).
        // In this case, find the route from the router.
        $route = $this->updateRoute ?? $this->findUpdateRoute();

        return (string) str(app('url')->toRoute($route, [], false))->start('/');
    }

    protected function findUpdateRoute()
    {
        // Find the route with name ending in 'livewire.update'.
        // Custom routes can have prefixes (e.g., 'tenant.livewire.update')
        // so we check for routes ending with 'livewire.update', not just exact matches.
        // Prioritise custom routes over the default route.
        $defaultRoute = null;

        foreach (Route::getRoutes()->getRoutes() as $route) {
            if (str($route->getName())->endsWith('livewire.update')) {
                // If it's the default route, save it but keep looking for a custom one
                if ($route->getName() === 'default-livewire.update') {
                    $defaultRoute = $route;
                    continue;
                }

                // Found a custom route, return it immediately
                return $route;
            }
        }

        return $defaultRoute;
    }

    function skipRequestPayloadTamperingMiddleware()
    {
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::skipWhen(function () {
            return $this->isLivewireRequest();
        });

        \Illuminate\Foundation\Http\Middleware\TrimStrings::skipWhen(function () {
            return $this->isLivewireRequest();
        });
    }

    function setUpdateRoute($callback)
    {
        $route = $callback([self::class, 'handleUpdate']);

        // Append `livewire.update` to the existing name, if any.
        if (! str($route->getName())->endsWith('livewire.update')) {
            $route->name('livewire.update');
        }

        $this->updateRoute = $route;
    }

    function isLivewireRequest()
    {
        return request()->hasHeader('X-Livewire');
    }

    function isLivewireRoute()
    {
        // @todo: Rename this back to `isLivewireRequest` once the need for it in tests has been fixed.
        $route = request()->route();

        if (! $route) return false;

        /*
         * Check to see if route name ends with `livewire.update`, as if
         * a custom update route is used and they add a name, then when
         * we call `->name('livewire.update')` on the route it will
         * suffix the existing name with `livewire.update`.
         */
        return $route->named('*livewire.update');
    }

    function handleUpdate()
    {
        // Check payload size limit...
<?php

namespace Livewire;
use Livewire\Finder\Finder;
use Livewire\Factory\Factory;
use Livewire\Compiler\Compiler;
use Illuminate\Foundation\Console\AboutCommand;
use Composer\InstalledVersions;
use Livewire\Compiler\CacheManager;

class LivewireServiceProvider extends \Illuminate\Support\ServiceProvider
{
    public function register()
    {
        $this->registerLivewireServices();
        $this->registerConfig();
        $this->bootEventBus();
        $this->registerMechanisms();
    }

    public function boot()
    {
        $this->bootConfig();
        $this->bootMechanisms();
        $this->bootFeatures();
    }

    protected function registerLivewireServices()
    {
        $this->app->alias(LivewireManager::class, 'livewire');
        $this->app->singleton(LivewireManager::class);

        app('livewire')->setProvider($this);

        $this->app->singleton('livewire.finder', function () {
            $finder = new Finder;

            $finder->addLocation(classNamespace: config('livewire.class_namespace'));

            return $finder;
        });

        $this->app->singleton('livewire.compiler', function () {
            return new Compiler(
                new CacheManager(
                    storage_path('framework/views/livewire')
                )
            );
        });

        $this->app->singleton('livewire.factory', function ($app) {
            return new Factory(
                $app['livewire.finder'],
                $app['livewire.compiler']
            );
        });
    }

    protected function registerConfig()
    {
        $config = __DIR__.'/../config/livewire.php';

        $this->publishes([$config => base_path('config/livewire.php')], ['livewire', 'livewire:config']);

        $this->mergeConfigFrom($config, 'livewire');
    }

    protected function bootEventBus()
    {
        app(EventBus::class)->boot();
    }

    protected function getMechanisms()
    {
        return [
            Mechanisms\PersistentMiddleware\PersistentMiddleware::class,
            Mechanisms\HandleComponents\HandleComponents::class,
            Mechanisms\HandleRequests\HandleRequests::class,
            Mechanisms\HandleRouting\HandleRouting::class,
            Mechanisms\FrontendAssets\FrontendAssets::class,
            Mechanisms\ExtendBlade\ExtendBlade::class,
            Mechanisms\CompileLivewireTags\CompileLivewireTags::class,
            Mechanisms\ClearCachedFiles::class,
            Mechanisms\RenderComponent::class,
            Mechanisms\DataStore::class,
        ];
    }

    protected function registerMechanisms()
    {
        foreach ($this->getMechanisms() as $mechanism) {
            app($mechanism)->register();
        }
    }

    protected function bootConfig()
    {
        // Adapt v4 config to v3 config...

        config()->set(
            'livewire.component_locations',
            config('livewire.component_locations', [
                resource_path('views/components'),
                resource_path('views/livewire'),
            ])
        );

        config()->set(
            'livewire.component_layout',
            config('livewire.component_layout', config('livewire.layout', null))
        );

        config()->set(
            'livewire.component_placeholder',
            config('livewire.component_placeholder', config('livewire.lazy_placeholder', null))
        );

        config()->set(
            'livewire.make_command',
            config('livewire.make_command', [
vendor/livewire/livewire/src/LivewireServiceProvider.php:11:class LivewireServiceProvider extends \Illuminate\Support\ServiceProvider
vendor/livewire/livewire/src/LivewireManager.php:18:    protected LivewireServiceProvider $provider;
vendor/livewire/livewire/src/LivewireManager.php:22:    function setProvider(LivewireServiceProvider $provider)


text:
Script completed
Wall time 0.1 seconds
Output:

text:
<?php

namespace Livewire\Mechanisms\HandleRequests;

use Illuminate\Http\Response;
use Illuminate\Support\Facades\Route;
use Livewire\Features\SupportScriptsAndAssets\SupportScriptsAndAssets;
use Livewire\Mechanisms\HandleRequests\EndpointResolver;
use Livewire\Exceptions\PayloadTooLargeException;
use Livewire\Exceptions\TooManyComponentsException;

use Livewire\Mechanisms\Mechanism;

use function Livewire\trigger;

class HandleRequests extends Mechanism
{
    protected $updateRoute;

    function boot()
    {
        // Register the default route immediately (before routes files load)
        // so it's positioned before any catch-all routes.
        if (! $this->updateRoute && ! $this->updateRouteExists()) {
            app($this::class)->setUpdateRoute(function ($handle) {
                return Route::post(EndpointResolver::updatePath(), $handle)
                    ->middleware('web')
                    ->name('default-livewire.update');
            });
        }

        $this->skipRequestPayloadTamperingMiddleware();
    }

    protected function updateRouteExists()
    {
        return $this->findUpdateRoute() !== null;
    }

    function getUriPrefix()
    {
        return EndpointResolver::prefix();
    }

    function getUpdateUri()
    {
        // When routes are cached, $this->updateRoute may be null because
        // setUpdateRoute() was never called (the route already existed).
        // In this case, find the route from the router.
        $route = $this->updateRoute ?? $this->findUpdateRoute();

        return (string) str(app('url')->toRoute($route, [], false))->start('/');
    }

    protected function findUpdateRoute()
    {
        // Find the route with name ending in 'livewire.update'.
        // Custom routes can have prefixes (e.g., 'tenant.livewire.update')
        // so we check for routes ending with 'livewire.update', not just exact matches.
        // Prioritise custom routes over the default route.
        $defaultRoute = null;

        foreach (Route::getRoutes()->getRoutes() as $route) {
            if (str($route->getName())->endsWith('livewire.update')) {
                // If it's the default route, save it but keep looking for a custom one
                if ($route->getName() === 'default-livewire.update') {
                    $defaultRoute = $route;
                    continue;
                }

                // Found a custom route, return it immediately
                return $route;
            }
        }

        return $defaultRoute;
    }

    function skipRequestPayloadTamperingMiddleware()
    {
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::skipWhen(function () {
            return $this->isLivewireRequest();
        });

        \Illuminate\Foundation\Http\Middleware\TrimStrings::skipWhen(function () {
            return $this->isLivewireRequest();
        });
    }

    function setUpdateRoute($callback)
    {
        $route = $callback([self::class, 'handleUpdate']);

        // Append `livewire.update` to the existing name, if any.
        if (! str($route->getName())->endsWith('livewire.update')) {
            $route->name('livewire.update');
        }

        $this->updateRoute = $route;
    }

    function isLivewireRequest()
    {
        return request()->hasHeader('X-Livewire');
    }

    function isLivewireRoute()
    {
        // @todo: Rename this back to `isLivewireRequest` once the need for it in tests has been fixed.
        $route = request()->route();

        if (! $route) return false;

        /*
         * Check to see if route name ends with `livewire.update`, as if
         * a custom update route is used and they add a name, then when
         * we call `->name('livewire.update')` on the route it will
         * suffix the existing name with `livewire.update`.
         */
        return $route->named('*livewire.update');
    }

    function handleUpdate()
    {
        // Check payload size limit...
<?php

namespace Livewire;
use Livewire\Finder\Finder;
use Livewire\Factory\Factory;
use Livewire\Compiler\Compiler;
use Illuminate\Foundation\Console\AboutCommand;
use Composer\InstalledVersions;
use Livewire\Compiler\CacheManager;

class LivewireServiceProvider extends \Illuminate\Support\ServiceProvider
{
    public function register()
    {
        $this->registerLivewireServices();
        $this->registerConfig();
        $this->bootEventBus();
        $this->registerMechanisms();
    }

    public function boot()
    {
        $this->bootConfig();
        $this->bootMechanisms();
        $this->bootFeatures();
    }

    protected function registerLivewireServices()
    {
        $this->app->alias(LivewireManager::class, 'livewire');
        $this->app->singleton(LivewireManager::class);

        app('livewire')->setProvider($this);

        $this->app->singleton('livewire.finder', function () {
            $finder = new Finder;

            $finder->addLocation(classNamespace: config('livewire.class_namespace'));

            return $finder;
        });

        $this->app->singleton('livewire.compiler', function () {
            return new Compiler(
                new CacheManager(
                    storage_path('framework/views/livewire')
                )
            );
        });

        $this->app->singleton('livewire.factory', function ($app) {
            return new Factory(
                $app['livewire.finder'],
                $app['livewire.compiler']
            );
        });
    }

    protected function registerConfig()
    {
        $config = __DIR__.'/../config/livewire.php';

        $this->publishes([$config => base_path('config/livewire.php')], ['livewire', 'livewire:config']);

        $this->mergeConfigFrom($config, 'livewire');
    }

    protected function bootEventBus()
    {
        app(EventBus::class)->boot();
    }

    protected function getMechanisms()
    {
        return [
            Mechanisms\PersistentMiddleware\PersistentMiddleware::class,
            Mechanisms\HandleComponents\HandleComponents::class,
            Mechanisms\HandleRequests\HandleRequests::class,
            Mechanisms\HandleRouting\HandleRouting::class,
            Mechanisms\FrontendAssets\FrontendAssets::class,
            Mechanisms\ExtendBlade\ExtendBlade::class,
            Mechanisms\CompileLivewireTags\CompileLivewireTags::class,
            Mechanisms\ClearCachedFiles::class,
            Mechanisms\RenderComponent::class,
            Mechanisms\DataStore::class,
        ];
    }

    protected function registerMechanisms()
    {
        foreach ($this->getMechanisms() as $mechanism) {
            app($mechanism)->register();
        }
    }

    protected function bootConfig()
    {
        // Adapt v4 config to v3 config...

        config()->set(
            'livewire.component_locations',
            config('livewire.component_locations', [
                resource_path('views/components'),
                resource_path('views/livewire'),
            ])
        );

        config()->set(
            'livewire.component_layout',
            config('livewire.component_layout', config('livewire.layout', null))
        );

        config()->set(
            'livewire.component_placeholder',
            config('livewire.component_placeholder', config('livewire.lazy_placeholder', null))
        );

        config()->set(
            'livewire.make_command',
            config('livewire.make_command', [
vendor/livewire/livewire/src/LivewireServiceProvider.php:11:class LivewireServiceProvider extends \Illuminate\Support\ServiceProvider
vendor/livewire/livewire/src/LivewireManager.php:18:    protected LivewireServiceProvider $provider;
vendor/livewire/livewire/src/LivewireManager.php:22:    function setProvider(LivewireServiceProvider $provider)


status: completed

input:
const matches = ALL_TOOLS.filter(x => /search.?docs|laravel.*boost|boost.*docs/i.test(x.name+" "+x.description));
text(matches);


text:
Script completed
Wall time 0.0 seconds
Output:

text: [{"name":"mcp__laravel_boost__application_info","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nGet comprehensive application information including PHP version, Laravel version, database engine, and all installed packages with their versions. You should use this tool on each new chat, and use the package & version data to write version specific code for the packages that exist.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__application_info(args: { [key: string]: unknown; }): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__browser_logs","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nRead the last N log entries from the BROWSER log. Very helpful for debugging the frontend and JS/Javascript\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__browser_logs(args: {\n  // Number of log entries to return.\n  entries: number;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__database_connections","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nList the configured database connection names for this application.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__database_connections(args: { [key: string]: unknown; }): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__database_query","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nExecute a read-only SQL query against the configured database.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__database_query(args: {\n  // Optional database connection name to use. Defaults to the application's default connection.\n  database?: string;\n  // The SQL query to execute. Only read-only queries are allowed (i.e. SELECT, SHOW, EXPLAIN, DESCRIBE).\n  query: string;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__database_schema","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nRead the database schema for this application. Returns table names, columns, indexes, and foreign keys. Use \"summary\" mode first to get an overview (table names with column types only), then call again without \"summary\" and with a \"filter\" to get full details for specific tables. Params: \"summary\" (default false) - returns only table names and column types; \"database\" - connection name; \"filter\" - substring match on table names; \"include_column_details\" (default false) - adds nullable, default, auto_increment, comments; \"include_views\" (default false); \"include_routines\" (default false) - stored procedures, functions, sequences.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__database_schema(args: {\n  // Name of the database connection to dump (defaults to app's default connection, often not needed)\n  database?: string;\n  // Filter tables by name (substring match).\n  filter?: string;\n  // Include full column metadata (nullable, default, auto_increment, comments, generation). Defaults to false.\n  include_column_details?: boolean;\n  // Include stored procedures, functions, and sequences. Defaults to false.\n  include_routines?: boolean;\n  // Include database views. Defaults to false.\n  include_views?: boolean;\n  // Return only table names and their column types. Use this first to understand the database structure, then request full details for specific tables using \"filter\". Defaults to false.\n  summary?: boolean;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__get_absolute_url","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nGet the absolute URL for a given relative path or named route. If no arguments are provided, you will get the absolute URL for \"/\"\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__get_absolute_url(args: {\n  // The relative URL/path (e.g. \"/dashboard\") to convert to an absolute URL.\n  path?: string;\n  // The named route to generate an absolute URL for (e.g. \"home\").\n  route?: string;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__last_error","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nGet details of the last error/exception created in this application on the backend. Use browser-log tool for browser errors.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__last_error(args: { [key: string]: unknown; }): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__read_log_entries","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nRead the last N log entries from the application log, correctly handling multi-line PSR-3 formatted logs and JSON-formatted logs. Only works for log files.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__read_log_entries(args: {\n  // Number of log entries to return.\n  entries: number;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__record_rule","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nRecord a durable project rule so the next agent or teammate inherits it instead of working it out again. Use it for a settled decision (why the project does something a certain way), a non-obvious trap, or a standing constraint that must always be followed. Pass a glob for the files it applies to (e.g. app/Http/Controllers/**) and Boost files it into a shared, committed markdown note grouped by area. Keep it to a few lines; only record what you would want to read in three months. Do not record secrets, transient state, or anything already obvious from the code.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__record_rule(args: {\n  // Glob for the files this rule applies to, for example \"app/Http/Controllers/**\" or \"app/Models/*.php\". This routes the rule into a shared area file and is how agents find it later.\n  glob: string;\n  // A few lines stating the rule plainly. No essays.\n  note: string;\n  // A short, specific heading, for example \"Extend BaseController for tenant scoping\".\n  title: string;\n}): Promise<CallToolResult>; };\n```"},{"name":"mcp__laravel_boost__search_docs","description":"Laravel ecosystem MCP server offering database schema access, error logs, semantic documentation search, and more. Boost helps with code generation.\n\nSearch for up-to-date version-specific documentation related to this project and its packages. This tool will search Laravel hosted documentation based on the packages installed and is perfect for all Laravel ecosystem packages. Laravel, Inertia, Pest, Livewire, Filament, Nova, Tailwind, and more. You must use this tool to search for Laravel-ecosystem docs before using other approaches. The results provided are for this project's package version and does not cover all versions of the package.\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__laravel_boost__search_docs(args: {\n  // Package names to limit searching to from application-info. Useful if you know the package(s) you need. i.e. laravel/framework, inertiajs/inertia-laravel, @inertiajs/react\n  packages?: Array<string>;\n  // List of queries to perform, pass multiple if you aren't sure if it is \"toggle\" or \"switch\", for example\n  queries: Array<string>;\n  // Maximum number of tokens to return in the response. Defaults to 3,000 tokens, maximum 1,000,000 tokens. If results are truncated, or you need more complete documentation, increase this value (e.g.5000, 10000)\n  token_limit?: number;\n}): Promise<CallToolResult>; };\n```"}]


status: completed

input:
const r = await tools.mcp__laravel_boost__search_docs({packages:["livewire/livewire","laravel/framework"],queries:["custom Livewire update route middleware","Livewire setUpdateRoute"],token_limit:5000});
text(r);


type: McpToolCall

server: laravel-boost

tool: search-docs

packages: livewire/livewire laravel/framework

queries:
custom Livewire update route middleware
Livewire setUpdateRoute

type: text

text:
# Search Results

## Upgrading Low-impact changes
Upgrading | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/upgrading

## Low-impact changes

These changes only affect applications using advanced features or customization.

### `wire:model` now supports bracket notation

`wire:model` expressions now support bracket notation for accessing nested properties:

```blade
<input type="text" wire:model="foo['bar']['baz']">

<input type="text" wire:model="items[0].name">
```

This means square brackets (`[` and `]`) in `wire:model` values are now interpreted as property accessors. In v3, they were treated as literal characters. If your property keys contain square brackets, rename them to avoid conflicts.

[Learn more about wire:model →](/docs/4.x/wire-model#accessing-nested-properties)

### Livewire Asset and Endpoint URL Changes

All Livewire URLs now include a unique hash derived from your `APP_KEY`. The prefix changed from `/livewire/` to `/livewire-{hash}/`:

```
# v3                          # v4
/livewire/update        →     /livewire-{hash}/update
/livewire/upload-file   →     /livewire-{hash}/upload-file
/livewire/livewire.js   →     /livewire-{hash}/livewire.js
```

If your firewall rules, CDN config, or middleware reference `/livewire/` paths, update them to account for the new prefix.

If you're using `setUpdateRoute`, use the `$path` parameter to preserve the hash-based endpoint:

```php
// Before (v3)
Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

// After (v4)
Livewire::setUpdateRoute(function ($handle, $path) {
    return Route::post($path, $handle);
});
```

[Learn more about customizing Livewire's endpoints →](/docs/4.x/installation#customizing-livewires-update-endpoint)

### JavaScript deprecations

#### Removed: internal `upload:generatedSignedUrl` events

The file-upload internals now negotiate a single server-decided `upload:plan` event instead of the old `upload:generatedSignedUrl` / `upload:generatedSignedUrlForS3` events. These were undocumented internal events, but if you had custom JavaScript listening for them via `$wire.$on('upload:generatedSignedUrl', ...)`, it will silently stop firing. The public upload API (`Livewire.upload`, `livewire-upload-start` / `-progress` / `-finish` / `-error` / `-cancel` DOM events) is unchanged — and the progress event now additionally carries `loaded` and `total` byte counts.

#### Deprecated: `$wire.$js()` method

The `$wire.$js()` method for defining JavaScript actions has been deprecated:

```js
// Deprecated (v3)
$wire.$js('bookmark', () => {
    // Toggle bookmark...
})

// New (v4)
$wire.$js.bookmark = () => {
    // Toggle bookmark...
}
```

The new syntax is cleaner and more intuitive.

#### Deprecated: `$js` without prefix

The use of `$js` in scripts without `$wire.$js` or `this.$js` prefix has been deprecated:

```js
// Deprecated (v3)
$js('bookmark', () => {
    // Toggle bookmark...
})

// New (v4)
$wire.$js.bookmark = () => {
    // Toggle bookmark...
}
// Or
this.$js.bookmark = () => {
    // Toggle bookmark...
}
```

> [!tip] Old syntax still works
> Both `$wire.$js('bookmark', ...)` and `$js('bookmark', ...)` will continue to work in v4 for backward compatibility, but you should migrate to the new syntax when convenient.

#### Deprecated: `commit` and `request` hooks

The `commit` and `request` hooks have been deprecated in favor of a new interceptor system that provides more granular control and better performance.

> [!tip] Old hooks still work
> The deprecated hooks will continue to work in v4 for backward compatibility, but you should migrate to the new system when convenient.

#### Migrating from `commit` hook

The old `commit` hook:

```js
// OLD - Deprecated
Livewire.hook('commit', ({ component, commit, respond, succeed, fail }) => {
    respond(() => {
        // Runs after response received but before processing
    })

    succeed(({ snapshot, effects }) => {
        // Runs after successful response
    })

    fail(() => {
        // Runs if request failed
    })
})
```

Should be replaced with the new `interceptMessage`:

```js
// NEW - Recommended
Livewire.interceptMessage(({ component, message, onFinish, onSuccess, onError, onFailure }) => {
    onFinish(() => {
        // Equivalent to respond()
    })

    onSuccess(({ payload }) => {
        // Equivalent to succeed()
        // Access snapshot via payload.snapshot
        // Access effects via payload.effects
    })

    onError(() => {
        // Equivalent to fail() for server errors
    })

    onFailure(() => {
        // Equivalent to fail() for network errors
    })
})
```

#### Migrating from `request` hook

The old `request` hook:

```js
// OLD - Deprecated
Livewire.hook('request', ({ url, options, payload, respond, succeed, fail }) => {
    respond(({ status, response }) => {
        // Runs when response received
    })

    succeed(({ status, json }) => {
        // Runs on successful response
    })

    fail(({ status, content, preventDefault }) => {
        // Runs on failed response
    })
})
```

Should be replaced with the new `interceptRequest`:

```js
// NEW - Recommended
Livewire.interceptRequest(({ request, onResponse, onSuccess, onError, onFailure }) => {
    // Access url via request.uri
    // Access options via request.options
    // Access payload via request.payload

    onResponse(({ response }) => {
        // Equivalent to respond()
        // Access status via response.status
    })

    onSuccess(({ response, responseJson }) => {
        // Equivalent to succeed()
        // Access status via response.status
        // Access json via responseJson
    })

    onError(({ response, responseBody, preventDefault }) => {
        // Equivalent to fail() for server errors
        // Access status via response.status
        // Access content via responseBody
    })

    onFailure(({ error }) => {
        // Equivalent to fail() for network errors
    })
})
```

#### Key differences

1. **More granular error handling**: The new system separates network failures (`onFailure`) from server errors (`onError`)
2. **Better lifecycle hooks**: Message interceptors provide additional hooks like `onSync`, `onMorph`, and `onRender`
3. **Cancellation support**: Both messages and requests can be cancelled/aborted
4. **Component scoping**: Message interceptors can be scoped to specific components using `$wire.intercept(...)`

For complete documentation on the new interceptor system, see the [JavaScript Interceptors documentation](/docs/4.x/javascript#interceptors).

---

## Security Middleware
Security | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/security

## Middleware

When a Livewire component is loaded on a page containing route-level [Authorization Middleware](https://laravel.com/docs/authorization#via-middleware), like so:

```php
Route::livewire('/post/{post}', App\Livewire\UpdatePost::class)
    ->middleware('can:update,post'); // [tl! highlight]
```

Livewire will ensure those middlewares are re-applied to subsequent Livewire network requests. This is referred to as "Persistent Middleware" in Livewire's core.

Persistent middleware protects you from scenarios where the authorization rules or user permissions have changed after the initial page-load.

Here's a more in-depth example of such a scenario:

```php
Route::livewire('/post/{post}', App\Livewire\UpdatePost::class)
    ->middleware('can:update,post'); // [tl! highlight]
```

```php
<?php

use App\Models\Post;
use Livewire\Component;
use Livewire\Attributes\Validate;

class UpdatePost extends Component
{
    public Post $post;

    #[Validate('required|min:5')]
    public $title = '';

    public $content = '';

    public function mount()
    {
        $this->title = $this->post->title;
        $this->content = $this->post->content;
    }

    public function update()
    {
        $this->post->update([
            'title' => $this->title,
            'content' => $this->content,
        ]);
    }
}
```

As you can see, the `can:update,post` middleware is applied at the route-level. This means that a user who doesn't have permission to update a post cannot view the page.

However, consider a scenario where a user:
* Loads the page
* Loses permission to update after the page loads
* Tries updating the post after losing permission

Because Livewire has already successfully loaded the page you might ask yourself: "When Livewire makes a subsequent request to update the post, will the `can:update,post` middleware be re-applied? Or instead, will the un-authorized user be able to update the post successfully?"

Because Livewire has internal mechanisms to re-apply middleware from the original endpoint, you are protected in this scenario.

### Configuring persistent middleware

By default, Livewire persists the following middleware across network requests:

```php
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Laravel\Jetstream\Http\Middleware\AuthenticateSession::class,
\Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\RedirectIfAuthenticated::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Auth\Middleware\Authorize::class,
```

If any of the above middlewares are applied to the initial page-load, they will be persisted (re-applied) to any future network requests.

However, if you are applying a custom middleware from your application on the initial page-load, and want it persisted between Livewire requests, you will need to add it to this list from a [Service Provider](https://laravel.com/docs/providers#main-content) in your app like so:

```php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Livewire;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Livewire::addPersistentMiddleware([ // [tl! highlight:2]
            App\Http\Middleware\EnsureUserHasRole::class,
        ]);
    }
}
```

If a Livewire component is loaded on a page that uses the `EnsureUserHasRole` middleware from your application, it will now be persisted and re-applied to any future network requests to that Livewire component.

> [!warning] Middleware arguments are not supported
> Livewire currently doesn't support middleware arguments for persistent middleware definitions.
>
> ```php
> // Bad...
> Livewire::addPersistentMiddleware(AuthorizeResource::class.':admin');
>
> // Good...
> Livewire::addPersistentMiddleware(AuthorizeResource::class);
> ```

### Applying global Livewire middleware

Alternatively, if you wish to apply specific middleware to every single Livewire update network request, you can do so by registering your own Livewire update route with any middleware you wish:

```php
Livewire::setUpdateRoute(function ($handle, $path) {
	return Route::post($path, $handle)
        ->middleware(App\Http\Middleware\LocalizeViewPaths::class);
});
```

Any Livewire AJAX/fetch requests made to the server will use the above endpoint and apply the `LocalizeViewPaths` middleware before handling the component update.

Learn more about [customizing the update route on the Installation page](https://livewire.laravel.com/docs/installation#configuring-livewires-update-endpoint).

---

## Installation Customizing Livewire's update endpoint
Installation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/installation

## Customizing Livewire's update endpoint

**When you need this:** If your application uses route prefixes for localization (like `/en/`, `/fr/`) or multi-tenancy (like `/tenant-1/`, `/tenant-2/`), you may need to customize Livewire's update endpoint to match your routing structure.

By default, Livewire sends component updates to a hash-based endpoint like `/livewire-{hash}/update`, where `{hash}` is derived from your application's `APP_KEY`. To customize this, register your own route in a service provider (typically `App\Providers\AppServiceProvider`):

```php
use Livewire\Livewire;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Livewire::setUpdateRoute(function ($handle, $path) {
            return Route::post('/custom' . $path, $handle);
        });
    }
}
```

The `$path` parameter contains the hash-based path (e.g., `/livewire-{hash}/update`), preserving the unique-per-installation endpoint.

You can also add middleware to the update route:

```php
Livewire::setUpdateRoute(function ($handle, $path) {
    return Route::post('/custom' . $path, $handle)
        ->middleware(['web', 'auth']);
});
```

---

## Cashier Paddle Handling Paddle Webhooks
Cashier Paddle | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/cashier-paddle.md

## Handling Paddle Webhooks

Paddle can notify your application of a variety of events via webhooks. By default, a route that points to Cashier's webhook controller is registered by the Cashier service provider. This controller will handle all incoming webhook requests.

By default, this controller will automatically handle canceling subscriptions that have too many failed charges, subscription updates, and payment method changes; however, as we'll soon discover, you can extend this controller to handle any Paddle webhook event you like.

To ensure your application can handle Paddle webhooks, be sure to [configure the webhook URL in the Paddle control panel](https://vendors.paddle.com/notifications-v2). By default, Cashier's webhook controller responds to the `/paddle/webhook` URL path. The full list of all webhooks you should enable in the Paddle control panel are:

- Customer Updated
- Transaction Completed
- Transaction Updated
- Subscription Created
- Subscription Updated
- Subscription Paused
- Subscription Canceled

> [!WARNING]
> Make sure you protect incoming requests with Cashier's included [webhook signature verification](/docs/{{version}}/cashier-paddle#verifying-webhook-signatures) middleware.

---

## Billing Handling Stripe Webhooks
Billing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/billing.md

## Handling Stripe Webhooks

> [!NOTE]
> You may use [the Stripe CLI](https://stripe.com/docs/stripe-cli) to help test webhooks during local development.

Stripe can notify your application of a variety of events via webhooks. By default, a route that points to Cashier's webhook controller is automatically registered by the Cashier service provider. This controller will handle all incoming webhook requests.

By default, the Cashier webhook controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings), customer updates, customer deletions, subscription updates, and payment method changes; however, as we'll soon discover, you can extend this controller to handle any Stripe webhook event you like.

To ensure your application can handle Stripe webhooks, be sure to configure the webhook URL in the Stripe control panel. By default, Cashier's webhook controller responds to the `/stripe/webhook` URL path. The full list of all webhooks you should enable in the Stripe control panel are:

- `customer.subscription.created`
- `customer.subscription.updated`
- `customer.subscription.deleted`
- `customer.updated`
- `customer.deleted`
- `payment_method.automatically_updated`
- `invoice.payment_action_required`
- `invoice.payment_succeeded`

For convenience, Cashier includes a `cashier:webhook` Artisan command. This command will create a webhook in Stripe that listens to all of the events required by Cashier:

```shell
php artisan cashier:webhook
```

By default, the created webhook will point to the URL defined by the `APP_URL` environment variable and the `cashier.webhook` route that is included with Cashier. You may provide the `--url` option when invoking the command if you would like to use a different URL:

```shell
php artisan cashier:webhook --url "https://example.com/stripe/webhook"
```

The webhook that is created will use the Stripe API version that your version of Cashier is compatible with. If you would like to use a different Stripe version, you may provide the `--api-version` option:

```shell
php artisan cashier:webhook --api-version="2019-12-03"
```

After creation, the webhook will be immediately active. If you wish to create the webhook but have it disabled until you're ready, you may provide the `--disabled` option when invoking the command:

```shell
php artisan cashier:webhook --disabled
```

> [!WARNING]
> Make sure you protect incoming Stripe webhook requests with Cashier's included [webhook signature verification](#verifying-webhook-signatures) middleware.

---

## Wire Transition Customizing animations with CSS
Wire Transition | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/wire-transition

## Customizing animations with CSS

View Transitions are controlled entirely through CSS. You can customize the animation by targeting the view-transition pseudo-elements:

```css
/* Customize the transition for a specific element */
::view-transition-old(sidebar) {
    animation: 300ms ease-out both slide-out;
}

::view-transition-new(sidebar) {
    animation: 300ms ease-in both slide-in;
}

@keyframes slide-out {
    to { transform: translateX(-100%); }
}

@keyframes slide-in {
    from { transform: translateX(100%); }
}
```

The View Transitions API provides three pseudo-elements you can style:
- `::view-transition-old(name)` — The outgoing element's snapshot
- `::view-transition-new(name)` — The incoming element's snapshot
- `::view-transition-group(name)` — Container for both snapshots

---

## Wire Model Customizing update timing
Wire Model | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/wire-model

## Customizing update timing

By default, Livewire will only send a network request when an action is performed (like `wire:click` or `wire:submit`), NOT when a `wire:model` input is updated.

This drastically improves the performance of Livewire by reducing network requests and provides a smoother experience for your users.

However, there are occasions where you may want to update the server more frequently for things like real-time validation.

### Live updating

To send property updates to the server as a user types into an input-field, you can append the `.live` modifier to `wire:model`:

```html
<input type="text" wire:model.live="title">
```

#### Customizing the debounce

By default, when using `wire:model.live`, Livewire adds a 150 millisecond debounce to server updates. This means if a user is continually typing, Livewire will wait until the user stops typing for 150 milliseconds before sending a request.

You can customize this timing by appending `.debounce.Xms` after `.live`. Here is an example of changing the debounce to 250 milliseconds:

```html
<input type="text" wire:model.live.debounce.250ms="title">
```

### Updating on "blur" event

The `.blur` modifier delays syncing until the user clicks away from the input:

```html
<input type="text" wire:model.blur="title">
```

To also send a network request on blur, add `.live`:

```html
<input type="text" wire:model.blur.live="title">
```

### Updating on "change" event

The `.change` modifier triggers on the change event, which is useful for select elements:

```html
<select wire:model.change="state">...</select>

<!-- With network request -->
<select wire:model.change.live="state">...</select>
```

### Updating on "enter" key

The `.enter` modifier syncs when the user presses the Enter key:

```html
<input type="text" wire:model.enter="search">

<!-- With network request -->
<input type="text" wire:model.enter.live="search">
```

_[Truncated]_