react-magic-search-params
Version:
Type-safe React hook to manage URL query/search params with React Router useSearchParams.
2 lines (1 loc) • 11.2 kB
JavaScript
;var L=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Me=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var ke=(m,d)=>{for(var p in d)L(m,p,{get:d[p],enumerable:!0})},Ae=(m,d,p,P)=>{if(d&&typeof d=="object"||typeof d=="function")for(let g of Me(d))!Re.call(m,g)&&g!==p&&L(m,g,{get:()=>d[g],enumerable:!(P=Ke(d,g))||P.enumerable});return m};var Se=m=>Ae(L({},"__esModule",{value:!0}),m);var Ce={};ke(Ce,{useMagicSearchParams:()=>ne});module.exports=Se(Ce);var ae=require("react-router-dom"),f=require("react"),ne=({mandatory:m={},optional:d={},defaultParams:p={},arraySerialization:P="csv",forceParams:g={},omitParamsByValues:se=[],coerceParams:N={},codecs:I={},protectedParams:j={},historyMode:q="push",resetOnChange:oe={},paginationStrategy:w,unknownParamsPolicy:S="drop"})=>{let[i,z]=(0,ae.useSearchParams)(),U=(0,f.useRef)({}),v=(0,f.useRef)({}),_=(0,f.useCallback)((e,r)=>{z(e,{replace:(r??q)==="replace"})},[z,q]),l=(0,f.useMemo)(()=>({...m,...d}),[m,d]),H=(0,f.useMemo)(()=>Array.from(Object.keys(l)),[l]),C=(0,f.useCallback)(e=>Object.prototype.hasOwnProperty.call(l,e),[l]),ce=e=>!Array.isArray(l[e])||P==="csv"?i.get(e):P==="repeat"?i.getAll(e):i.getAll(`${e}[]`),$=(0,f.useCallback)(()=>{if(S==="drop")return[];let e=[];for(let[r,a]of i.entries()){let t=r.endsWith("[]")?r.replace("[]",""):r;C(t)||e.push([r,a])}return e},[S,i,C]),D=(0,f.useCallback)(e=>{if(S==="drop")return e;let r=new URLSearchParams(e.toString()),a=$();for(let[t,n]of a)r.append(t,n);return r},[S,$]),W=(e,r)=>Array.isArray(e)&&Array.isArray(r)?e.length!==r.length?!1:e.every((a,t)=>a===r[t]):e===r,V=(0,f.useMemo)(()=>Object.keys(l).filter(e=>Array.isArray(l[e])),[l]),ie=(e,r)=>{let a={...e};return V.length===0||V.forEach(t=>{let n=[];switch(P){case"csv":{n=(i.get(t)||"").split(",").map(o=>o.trim()).filter(Boolean);break}case"repeat":{let s=i.getAll(t);n=s.length>0?s:[];break}case"brackets":{let s=i.getAll(`${t}[]`);n=s.length>0?s:[];break}default:n=(i.get(t)??"").split(",").map(o=>o.trim()).filter(Boolean)}if(r[t]!==void 0){let s=r[t],o=[];typeof s=="string"?o=n.includes(s)?n.filter(u=>u!==s):[...n,s]:Array.isArray(s)?o=Array.from(new Set([...s.map(String)])):o=n,a[t]=o}}),a},T=globalThis.Buffer,ue=e=>{if(T)return T.from(e,"utf8").toString("base64");if(typeof btoa<"u"&&typeof TextEncoder<"u"){let r=new TextEncoder().encode(e),a="";for(let t of r)a+=String.fromCharCode(t);return btoa(a)}throw new Error("Base64 encoding is not supported in this environment")},me=e=>{if(T)return T.from(e,"base64").toString("utf8");if(typeof atob<"u"&&typeof TextDecoder<"u"){let r=atob(e),a=Uint8Array.from(r,t=>t.charCodeAt(0));return new TextDecoder().decode(a)}throw new Error("Base64 decoding is not supported in this environment")},Q=e=>ue(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,""),fe=e=>{let r=e.replace(/-/g,"+").replace(/_/g,"/"),a=r.padEnd(r.length+(4-r.length%4)%4,"=");return me(a)},Y=e=>e==null?e:Array.isArray(e)?e.map(r=>Q(String(r))):Q(String(e)),G=e=>{let r=a=>{if(a==="")return"";try{return fe(a)}catch{return a}};return e==null?"":Array.isArray(e)?e.map(a=>r(a)):r(e)},J=(0,f.useMemo)(()=>{let e={...I};for(let r of Object.keys(j)){let a=j[r];if(a){if(a===!0){e[r]={parse:t=>G(t),serialize:t=>Y(t)};continue}e[r]={parse:a.parse??(t=>G(t)),serialize:a.serialize??(t=>Y(t))}}}return e},[I,j]),h=e=>{let r=new URLSearchParams,a=Object.keys(e);for(let t of a){let n=J[t];if(n?.serialize){let s=n.serialize(e[t],{key:t});if(s==null)continue;if(Array.isArray(s))if(Array.isArray(l[t]))if(P==="csv")r.set(t,s.join(","));else if(P==="repeat")for(let o of s)r.append(t,String(o));else for(let o of s)r.append(`${t}[]`,String(o));else s.length>0&&r.set(t,String(s[0]));else r.set(t,String(s));continue}if(Array.isArray(l[t])){let s=e[t];switch(P){case"csv":{r.set(t,s.join(","));break}case"repeat":{for(let o of s)r.append(t,String(o));break}case"brackets":{for(let o of s)r.append(`${t}[]`,String(o));break}default:r.set(t,s.join(","))}}else r.set(t,String(e[t]))}return r},O=(e,r)=>Object.prototype.hasOwnProperty.call(m,e)?m[e]:Object.prototype.hasOwnProperty.call(p,e)?p[e]:r,X=e=>Object.prototype.hasOwnProperty.call(d,e)?d[e]==="":!1,E=(e,r)=>{let a=Array.isArray(r)?r[0]:r,t=a==null?"":String(a).trim().toLowerCase();if(t==="true")return!0;if(t==="false")return!1;if(X(e))return"";let n=O(e,!1);return typeof n=="boolean"?n:!1},Z=({paramsForced:e,compareParams:r})=>Object.entries(e).every(([t,n])=>r[t]===n),B=e=>{let r=ce(e),a=J[e];if(a?.parse)return a.parse(r,{key:e,searchParams:i});let t=N[e];if(t==="number"){let n=Number.parseInt(String(r??""),10);if(Number.isNaN(n)){let s=O(e,0);return typeof s=="number"?s:0}return n}if(t==="boolean")return E(e,r);if(t==="array")return P==="csv"?String(r??"").split(",").filter(Boolean):Array.isArray(r)?r:r?[r]:[];if(t==="string")return Array.isArray(r)?r[0]??"":r??"";if(typeof l[e]=="number"){let n=Number.parseInt(String(r??""),10);if(Number.isNaN(n)){let s=O(e,0);return typeof s=="number"?s:0}return n}return typeof l[e]=="boolean"?E(e,r):Array.isArray(l[e])?P==="csv"?String(r??"").split(",").filter(Boolean):Array.isArray(r)?r:r?[r]:[]:Array.isArray(r)?r[0]??"":r??""},ee=(e,r)=>{let a=N[e];if(!a)return r;if(a==="boolean")return E(e,r);if(a==="number"){if(typeof r=="number"&&Number.isFinite(r))return r;let t=Number.parseInt(String(r??""),10);if(Number.isNaN(t)){let n=O(e,0);return typeof n=="number"?n:0}return t}return a==="array"?Array.isArray(r)?r:r==null||r===""?[]:[String(r)]:a==="string"?Array.isArray(r)?r[0]??"":r==null?"":String(r):r},re=(e,r)=>{if(Array.isArray(l[e])){if(P==="brackets"){let n=i.getAll(`${e}[]`),s=h({[e]:n}).toString();return decodeURIComponent(s)}if(P==="csv"){let n=i.getAll(e),s=h({[e]:n}).toString();return decodeURIComponent(s)}let t=i.getAll(e);return h({[e]:t}).toString()}return r[e]},Pe=e=>{let r={};for(let[a,t]of e.entries())if(a.endsWith("[]")){let n=a.replace("[]","");r[n]?r[n].push(t):r[n]=[t]}else r[a]?Array.isArray(r[a])?r[a].push(t):r[a]=[r[a],t]:r[a]=t;return r},le=e=>Object.entries(e).reduce((r,[a,t])=>(t===""||t==null||(r[a]=t),r),{}),k=(0,f.useMemo)(()=>P==="brackets"?Pe(i):Object.fromEntries(i.entries()),[i,P]);function M({convert:e=!0,forRequest:r=!1}={}){let a=(e===!0?H:Object.keys(k)).reduce((t,n)=>{if(Object.prototype.hasOwnProperty.call(l,n)){let s=P==="brackets"?n.replace("[]",""):n;if(e===!0){let o=Object.prototype.hasOwnProperty.call(m,s),u=Object.prototype.hasOwnProperty.call(k,s),c=Object.prototype.hasOwnProperty.call(d,s)&&N[s]==="boolean"&&X(s);if(!o&&!u&&!c)return t;let b=B(s);t[s]=ee(s,b)}else t[s]=re(n,k)}return t},{});return e===!0&&r===!0?le(a):a}let K=(e,r)=>{let a=String(e);return r?.convert!==!1?ee(a,B(a)):re(a,k)},de=e=>e==null||typeof e!="object"?!1:Object.prototype.hasOwnProperty.call(e,"newParams")||Object.prototype.hasOwnProperty.call(e,"keepParams")||Object.prototype.hasOwnProperty.call(e,"historyMode"),pe=e=>{let r=M({convert:!0});if(typeof e=="function"){let a=e(r);return de(a)?{newParams:typeof a.newParams=="function"?a.newParams(r):a.newParams??{},keepParams:a.keepParams??{},historyMode:a.historyMode}:{newParams:a,keepParams:{},historyMode:void 0}}return e?{newParams:typeof e.newParams=="function"?e.newParams(r):e.newParams??{},keepParams:e.keepParams??{},historyMode:e.historyMode}:{newParams:{},keepParams:{},historyMode:void 0}},ye=({currentParams:e,newParams:r,keepParams:a})=>{let t={...r},n={...a};for(let[s,o]of Object.entries(oe))if(!(!o||o.length===0||!Object.prototype.hasOwnProperty.call(t,s)||W(t[s],e[s]))){for(let c of o)if(!Object.prototype.hasOwnProperty.call(g,c)){if(Object.prototype.hasOwnProperty.call(m,c)){t[c]=m[c],delete n[c];continue}if(Object.prototype.hasOwnProperty.call(p,c)){t[c]=p[c],delete n[c];continue}delete t[c],n[c]=!1}}return{newParams:t,keepParams:n}},ge=(e,r)=>{let a=M(),t=Object.entries(e).filter(([o])=>!Array.isArray(l[o])),n=Object.assign({...a,...Object.fromEntries(t)},g),s=Object.keys(n).reduce((o,u)=>{if(Object.prototype.hasOwnProperty.call(r,u)&&r[u]===!1)return o;let c=n[u],b=typeof c=="string"&&se.includes(c);return c!=null&&c!==""&&!b&&(o[u]=c),o},{});return{...m,...s}},we=e=>H.reduce((a,t)=>(Object.prototype.hasOwnProperty.call(e,t)&&(a[t]=e[t]),a),{}),Oe=()=>{let e=V.length>0,r=M({convert:e});return Object.keys(r).reduce((t,n)=>(Object.prototype.hasOwnProperty.call(m,n)&&(t[n]=r[n]),t),{})},te=({keepMandatoryParams:e=!0,historyMode:r}={})=>{let a=h({...m,...e&&{...Oe()},...g}),t=D(a);_(t,r)},y=e=>{let r=pe(e),a=M({convert:!0}),t=ye({currentParams:a,newParams:r.newParams,keepParams:r.keepParams}),n=t.newParams,s=t.keepParams;if(Object.keys(n).length===0&&Object.keys(s).length===0){te({historyMode:r.historyMode});return}let o=ge(n,s),u=ie(o,n),c=we(u),b=h(c),F=D(b);_(F,r.historyMode)},R=w?.mode==="page"?w:void 0,A=w?.mode==="offset"?w:void 0,x=w?.mode==="cursor"?w:void 0,be={mode:w?.mode??"page",next:e=>{let r=w?.mode??"page";if(r==="cursor"){let s=x?.cursorKey??"cursor";typeof e=="string"&&y({newParams:{[s]:e}});return}if(r==="offset"){let s=A?.offsetKey??"offset",o=A?.limitKey??"limit",u=Number(K(s,{convert:!0})??0),c=Number(K(o,{convert:!0})??O(String(o),10)),b=Number.isFinite(u)?u:0,F=Number.isFinite(c)&&c>0?c:10;y({newParams:{[s]:b+F}});return}let a=R?R.pageKey??"page":"page",t=Number(K(a,{convert:!0})??O(String(a),1)),n=Number.isFinite(t)&&t>0?t:1;y({newParams:{[a]:n+1}})},prev:()=>{let e=w?.mode??"page";if(e==="cursor"){let n=x?.cursorKey??"cursor";y({keepParams:{[n]:!1}});return}if(e==="offset"){let n=A?.offsetKey??"offset",s=A?.limitKey??"limit",o=Number(K(n,{convert:!0})??0),u=Number(K(s,{convert:!0})??O(String(s),10)),c=Number.isFinite(o)?o:0,b=Number.isFinite(u)&&u>0?u:10;y({newParams:{[n]:Math.max(0,c-b)}});return}let r=R?R.pageKey??"page":"page",a=Number(K(r,{convert:!0})??O(String(r),1)),t=Number.isFinite(a)&&a>0?a:1;y({newParams:{[r]:Math.max(1,t-1)}})},reset:()=>{let e=w?.mode??"page";if(e==="cursor"){let t=x?.cursorKey??"cursor";y({keepParams:{[t]:!1}});return}if(e==="offset"){let t=A?.offsetKey??"offset",n=Number(O(String(t),0));y({newParams:{[t]:Number.isFinite(n)?n:0}});return}let r=R?R.pageKey??"page":"page",a=Number(O(String(r),1));y({newParams:{[r]:Number.isFinite(a)&&a>0?a:1}})},setCursor:e=>{let a=(w?.mode??"page")==="cursor"?x?.cursorKey??"cursor":"cursor";if(e==null||e===""){y({keepParams:{[a]:!1}});return}y({newParams:{[a]:e}})}},he=(0,f.useCallback)((e,r)=>{let a=String(e);return U.current[a]=r,()=>{delete U.current[a],delete v.current[a]}},[]);return(0,f.useEffect)(()=>{for(let[e,r]of Object.entries(U.current)){let a=C(e)?B(e):i.get(e),t=v.current[e]??null;if(!W(a,t))for(let n of r)n({key:e,previousValue:t,currentValue:a});v.current[e]=a}},[k,C,i]),(0,f.useEffect)(()=>{let e=Object.keys(p),r=Object.keys(g);if(e.length===0&&r.length===0)return;function a(){let t=h(p).toString(),n=M(),s=h(n).toString();if(!Z({paramsForced:g,compareParams:n})){y({newParams:{...p,...g},historyMode:"replace"});return}let u=Z({paramsForced:g,compareParams:p});if(e.length>0&&u){if(t===s)return;y({newParams:p,historyMode:"replace"})}}a()},[]),{searchParams:i,updateParams:y,clearParams:te,getParams:M,getParam:K,onChange:he,pagination:be}};0&&(module.exports={useMagicSearchParams});