@rzl-zone/ziggy-route
Version:
Typed Laravel route generator for any frontend — works with React, Vue, Vanilla JS, and other JavaScript-based stacks.
2 lines (1 loc) • 14 kB
JavaScript
;var k=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var K=(o,e)=>{for(var t in e)k(o,t,{get:e[t],enumerable:!0})},W=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of V(e))!q.call(o,r)&&r!==t&&k(o,r,{get:()=>e[r],enumerable:!(n=B(e,r))||n.enumerable});return o};var Z=o=>W(k({},"__esModule",{value:!0}),o);var J={};K(J,{useRoute:()=>Y});module.exports=Z(J);function c(o){return Array.isArray(o)}var M=o=>typeof o=="number"&&!Number.isNaN(o),l=o=>typeof o=="string";var T=(o,e)=>{if(!l(o))return!0;m(e)||(e={});let{trim:t=!0}=e;return t&&(o=o.trim()),o===""};var P=o=>typeof o=="boolean";var A=o=>o instanceof Error;function m(o){return typeof o=="object"&&!d(o)&&!c(o)}var S=o=>o===null,g=o=>typeof o>"u";var C=o=>o.replace(/([a-z])([A-Z])/g,"$1 $2").replace(/([a-zA-Z])(\d)/g,"$1 $2").replace(/(\d)([a-zA-Z])/g,"$1 $2").replace(/\s+/g," ").trim().replace(/\w\S*/g,e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()),u=o=>{let e={string:"String",number:"Number",boolean:"Boolean",bigint:"BigInt",symbol:"Symbol",undefined:"Undefined",null:"Null",object:"Object",array:"Array",function:"Function",regexp:"RegExp",date:"Date",error:"Error",int8array:"Int8Array",uint8array:"Uint8Array",uint8clampedarray:"Uint8ClampedArray",int16array:"Int16Array",uint16array:"Uint16Array",int32array:"Int32Array",uint32array:"Uint32Array",float32array:"Float32Array",float64array:"Float64Array",bigint64array:"BigInt64Array",biguint64array:"BigUint64Array",arraybuffer:"ArrayBuffer",sharedarraybuffer:"SharedArrayBuffer",dataview:"DataView",map:"Map",set:"Set",weakmap:"WeakMap",weakset:"WeakSet",promise:"Promise",generator:"Generator",generatorfunction:"GeneratorFunction",asyncfunction:"AsyncFunction",finalizationregistry:"FinalizationRegistry",weakref:"WeakRef"};if(o===null)return e.null;let t=typeof o;if(t!=="object"&&t!=="function")return C(e[t]??t);let n=Object.prototype.toString.call(o).slice(8,-1),r=e[n.toLowerCase()];return r&&(n=r),C(n)};function w(o){return typeof o=="object"&&!d(o)}var Q=Function.prototype.toString;function d(o){return o==null}var L=()=>typeof window>"u"||typeof document>"u";var U=require("qs");var x={PACKAGE:{NPM_NAME:"@rzl-zone/ziggy-route",PACKAGIST_NAME:"rzl-zone/ziggy-route",PREFIX:{NAME:"RZL ZIGGY"}},REPO:{LINK:"https://github.com/rzl-zone/ziggy-route"}};var z=require("qs");var s=class extends Error{constructor(t,n,r){let a=r?.trim()||x.PACKAGE.PREFIX.NAME,i=t.trim();super(`${a} - ${i}`);this.originalError=n;this.name="RouterConfigError",Error.captureStackTrace&&Error.captureStackTrace(this,f)}},f=class o extends Error{constructor(t,n,r){let a=r?.trim()||x.PACKAGE.PREFIX.NAME,i=t.trim();super(`${a} - ${i}`);this.originalError=n;this.name="RoutePropsError",Error.captureStackTrace&&Error.captureStackTrace(this,o)}};var h=class{name;definition;config;wheres;bindings={};constructor(e,t,n){this.name=e,this.definition=t,this.bindings=t?.bindings??{},this.wheres=t?.wheres??{},this.config=n}get template(){let e=`${this.origin}/${this.definition?.uri}`.replace(/\/+$/,"");return T(e)?"/":e}get origin(){if(!this.config?.absolute)return"";if(this.definition?.domain){let e=this.config.url.match(/^\w+:\/\//);if(!e)throw new s("Invalid `config.url` missing protocol (e.g., http:// or https://)");return`${e[0]}${this.definition.domain}${this.config.port?`:${this.config.port}`:""}`}return this.config.url}get parameterSegments(){return this.template.match(/{[^}?]+\??}/g)?.map(e=>({name:e.replace(/{|\??}/g,""),required:!/\?}$/.test(e)}))??[]}matchesUrl(e){if(!this.definition?.methods.includes("GET"))return!1;let t=this.template.replace(/[.*+$()[\]]/g,"\\$&").replace(/(\/?){([^}?]*)(\??)}/g,(i,p,b,$)=>{let v=`(?<${b}>${this.wheres[b]?.replace(/(^\^)|(\$$)/g,"")||"[^/?]+"})`;return $?`(${p}${v})?`:`${p}${v}`}).replace(/^\w+:\/\//,""),[n,r]=e.replace(/^\w+:\/\//,"").split("?"),a=new RegExp(`^${t}/?$`).exec(n)??new RegExp(`^${t}/?$`).exec(decodeURI(n));if(a){for(let i in a.groups)a.groups[i]=l(a.groups[i])?decodeURIComponent(a.groups[i]):a.groups[i];return{params:a.groups,query:(0,z.parse)(r)}}return!1}compile(e={}){let t=this.template.replace(/{([^}?]+)(\??)}/g,(r,a,i)=>{let p=e[a];if(!i&&d(p))throw new f(`Invalid \`${a}\` parameter is required for route \`${this.name}\`.`);if(this.wheres[a]){let b=new RegExp(`^${this.wheres[a]}$`);if(l(p)&&!b.test(p))throw new f(`Invalid \`${a}\` parameter \`${p}\` does not match required format \`${this.wheres[a]}\` for route \`${this.name}\`.`)}return encodeURI(l(p)?p:"").replace(/%7C/g,"|").replace(/%25/g,"%").replace(/\$/g,"%24")}),n=t;if(this.config?.absolute&&t.includes("://")){let[r,a]=t.split("://");n=r+"://"+a.replace(/\/{2,}/g,"/")}else n=t.replace(/\/{2,}/g,"/");return n==="/"?"/":n.replace(/\/+$/,"")}};var O=class o{absolute;url;port;defaults;routes;location;constructor(e){this.absolute=e.absolute,this.url=e.url,this.port=e.port,this.defaults=e.defaults,this.routes=e.routes,this.location=e.location}static isRouterConfigRaw(e){if(d(e))return!1;let t=e;if(!m(t))throw new s(`Invalid \`route()\` \`config\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid config object, \`config\` need object type but you passing as \`${u(t)}\`.`);if(!l(t.url))throw new s(`Invalid \`route()\` \`config.url\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.url\`, \`config.url\` need string or null type but you passing as \`${u(t.url)}\`.`);if(!S(t.port)&&!M(t.port))throw new s(`Invalid \`route()\` \`config.port\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.port\`, \`config.port\` need number or null type but you passing as \`${u(t.port)}\`.`);if(!w(t.defaults))throw new s(`Invalid \`route()\` \`config.defaults\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.defaults\`, \`config.defaults\` need array or object type but you passing as \`${u(t.defaults)}\`.`);if(!m(t.routes))throw new s(`Invalid \`route()\` \`config.routes\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.routes\`, \`config.routes\` need object type but you passing as \`${c(t.routes)?"Array":u(t.routes)}\`.`);if("location"in t){let n=t.location;if(l(n))throw new s(`Invalid \`route()\` \`config.location\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid config object, \`config.location\` need object type\`{ host?: string | undefined; pathname?: string | undefined ;search?: string | undefined; }\` but you passing as \`${u(n)}\`.`);if(!m(n))throw new s(`Invalid \`route()\` \`config.location\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.location\`, \`config.location\` need object type but you passing as \`${u(n)}\`.`);let r=n;if("host"in r&&!l(r.host)&&!g(r.host))throw new s(`Invalid \`route()\` \`config.location.host\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.location.host\`, \`config.location.host\` need string or undefined type but you passing as \`${u(r.host)}\`.`);if("pathname"in r&&!l(r.pathname)&&!g(r.pathname))throw new s(`Invalid \`route()\` \`config.location.pathname\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.location.pathname\`, \`config.location.pathname\` need string or undefined type but you passing as \`${u(r.pathname)}\`.`);if("search"in r&&!l(r.search)&&!g(r.search))throw new s(`Invalid \`route()\` \`config.location.search\` properties detected. Ensure that \`appRoutes\` is defined globally or passed as a valid \`config.location.search\`, \`config.location.search\` need string or undefined type but you passing as \`${u(r.search)}\`.`)}return!0}static validateAndWrap(e){try{if(e instanceof o)return e;if(!this.isRouterConfigRaw(e))throw new s("Invalid `route()` config properties detected. Ensure that `appRoutes` is defined globally or passed as a valid config object.");return new o(e)}catch(t){throw t instanceof s?t:new s("Invalid `route()` config properties detected. Ensure that `appRoutes` is defined globally or passed as a valid config object.",A(t)?t:new Error(String(t)))}}};var{REPO:y,PACKAGE:G}=x,I=class extends String{_config;_route;_params={};constructor(e,t,n=!1,r){if(super(),T(e))throw new f(`Invalid \`route()\` "name" value it cannot be an empty string. Use \`undefined\` if you don't want to provide a name. Make sure to call a valid \`Router\` instance method, or you'll encounter an error. Learn more: ${y.LINK}#%EF%B8%8F-warning-calling-route-without-arguments.`);if(!S(n)&&!P(n))throw new f(`Invalid \`route()\` option "absolute" must be a boolean or undefined, but received type "${u(n)}". Learn more: ${y.LINK}#absolute-url.`);n=!!n;let a=this.safeValidateRouterConfig(r||(g(appRoutes)?globalThis.appRoutes:appRoutes));if(this._config={...a,absolute:n},e){if(!this._config.routes[e])throw new f(`Route name '${e}' is not in the route list.`);this._route=new h(e,this._config.routes[e],this._config),this._params=this._parse(t)}}safeValidateRouterConfig(e){try{return O.validateAndWrap(e)}catch(t){throw t instanceof s?t:new Error(`${G.PREFIX.NAME} - Unknown error while validating \`route()\` config`,{cause:A(t)?t:void 0})}}_unresolve(e){e?this._config.absolute&&e.startsWith("/")&&(e=this._location().host+e):e=this._currentUrl();let t={},[n,r]=Object.entries(this._config.routes).find(([a,i])=>t=new h(a,i,this._config).matchesUrl(e))||[void 0,void 0];return{name:n,...t,route:r}}_currentUrl(){let{host:e,pathname:t,search:n}=this._location();return(this._config.absolute?e+t:t.replace(this._config.url.replace(/^\w*:\/\/[^/]+/,""),"").replace(/^\/+/,"/"))+n}_location(){let{host:e="",pathname:t="",search:n=""}=L()?{}:window.location;return{host:this._config.location?.host??e,pathname:this._config.location?.pathname??t,search:this._config.location?.search??n}}_parse(e={},t=this._route){if(!w(e))throw new f(`Invalid \`route()\` \`params\` property detected. Value \`params\` need object or array type but you passing as \`${u(e)}\`. More info \u2192 ${y.LINK}#parameters`);e??={},e=["string","number"].includes(typeof e)?[e]:e;let n=t?.parameterSegments.filter(({name:r})=>!this._config.defaults[r]);return c(e)?e=e.reduce((r,a,i)=>n?.[i]?{...r,[n[i].name]:a}:w(a)?{...r,...a}:{...r,...l(a)?{[a]:""}:{}},{}):n?.length===1&&!e[n?.[0].name]&&(t&&e.hasOwnProperty(Object.values(t.bindings)[0])||e.hasOwnProperty("id"))&&(e={[n?.[0].name]:e}),{...this._defaults(t),...this._substituteBindings(e,t)}}_defaults(e){return e?.parameterSegments.filter(({name:t})=>this._config.defaults[t]).reduce((t,{name:n},r)=>({...t,[n]:this._config.defaults[n]}),{})}_substituteBindings(e,t=this._route){return Object.entries(e).reduce((n,[r,a])=>{if(!a||typeof a!="object"||c(a)||!t?.parameterSegments.some(({name:i})=>i===r))return{...n,[r]:a};if(!a.hasOwnProperty(t.bindings[r]))if(a.hasOwnProperty("id"))t.bindings[r]="id";else throw new f(`Object passed as '${r}' parameter is missing route model binding key '${t.bindings[r]}'. More info \u2192 ${y.LINK}#parameters`);return{...n,[r]:a[t.bindings[r]]}},{})}get params(){let{params:e,query:t}=this._unresolve(),n={};for(let r in t){let a=t[r];l(a)?n[r]=a:c(a)?n[r]=a.filter(l).join(","):a&&m(a)&&(n[r]=JSON.stringify(a))}return{...e,...n}}get routeParams(){return this._unresolve().params||{}}get queryParams(){return this._unresolve().query||{}}has(e){if(!l(e))throw new f(`Invalid \`route().has(...)\` the \`name\` parameter must be a string, but received \`${u(e)}\`.`);return this._config.routes.hasOwnProperty(e)}current(e,t={}){if(e&&!l(e))throw new f(`Invalid \`route().current(...)\` \`name\` property detected. Value \`name\` need string type but you passing as \`${u(e)}\`.`);if(t&&!w(t))throw new f(`Invalid \`params\` value passed to \`route().current(...)\`, expected a object or array (e.g., { foo: "bar" } or [{"foo": "bar"}]), but received \`${u(t)}\`. Learn more: ${y.LINK}#routecurrent-optionally-accepts-parameters-as-its-second-argument-and-will-check-that-their-values-also-match-in-the-current-url.`);t??={};let{name:n,params:r,query:a,route:i}=this._unresolve();if(!e)return n;let p=l(n)&&new RegExp(`^${e.replace(/\./g,"\\.").replace(/\*/g,".*")}$`).test(n);if(d(t)||!p)return p;let b=new h(n,i,this._config);t=this._parse(t,b);let $={...r,...a};if(Object.values(t).every(E=>!E)&&!Object.values($).some(E=>!g(E)))return!0;let v=(E,R)=>Object.entries(E).every(([j,N])=>{if(c(N)&&c(R[j])){let F=R[j];return N.every(_=>F.includes(_))}return m(N)&&m(R[j])?v(N,R[j]):R[j]==N});return v(t,$)}toString(){let e=this._route,t=this._params??={};if(!e)throw new f(`Function route() was called without a name but used as a string. Pass a valid route name, or use route().current() to get the current route name \u2014 or route().current('dashboard') to check if it matches. More info \u2192 ${y.LINK}#%EF%B8%8F-warning-calling-route-without-arguments`);let n=Object.keys(t).filter(a=>!e.parameterSegments.some(({name:i})=>i===a)).filter(a=>a!=="_query").reduce((a,i)=>({...a,[i]:t[i]}),{}),r=t._query;if(!g(r)&&(!m(r)||S(r)||c(r)))throw new f(`Invalid \`params._query\` value passed to \`route()\`, expected a plain object (e.g., { foo: "bar" }), but received \`${u(r)}\`. More info \u2192 ${y.LINK}#query-parameters`);return e.compile(t)+(0,U.stringify)({...n,...r},{addQueryPrefix:!0,arrayFormat:"indices",encodeValuesOnly:!0,skipNulls:!0,encoder:(a,i)=>P(a)?String(+a):i(a)})}valueOf(){return this.toString()}};function D(o,e,t=!1,n){let r=new I(o,e,t,n);return o?r.toString():r}function Y(o){if(!o&&!globalThis.appRoutes&&g(appRoutes))throw new s("Hook `useRouter()` missing configuration. Ensure that a `appRoutes` variable is defined globally or pass a config object into the `useRoute` hook.");return(e,t,n)=>D(e,t,n,o)}0&&(module.exports={useRoute});