@symbo.ls/fetch 3.14.661 → 3.14.662

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- import{isArray as Q,isFunction as l,isObject as V,isString as H,exec as Pt}from"@symbo.ls/utils";const zt=["select","rpc","insert","update","upsert","delete","subscribe"],jt={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},ut=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),X=(()=>{if(typeof globalThis<"u"&&globalThis[ut])return globalThis[ut];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ut,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[ut]}catch{}return t})(),lt=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),bt=(()=>{if(typeof globalThis<"u"&&globalThis[lt])return globalThis[lt];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,lt,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[lt]}catch{}return t})(),Bt=5e3,Gt=t=>new Promise(e=>{if(X[t])return e(X[t]);const s=bt[t]||=[];let r=!1;const o=()=>{r||(r=!0,e(X[t]||null))};s.push(o),setTimeout(o,Bt)}),re=(t,e)=>{X[t]=e;const s=bt[t];if(s&&s.length){bt[t]=[];for(const r of s)r()}},ne=t=>{const e={};for(const s of zt)t[s]&&(e[s]=t[s]);return e.name=t.name||"custom",e},Qt=async t=>{if(!t)return null;if(typeof t.select=="function")return t;const{adapter:e,...s}=t,r=typeof e=="string"?e:typeof t=="string"?t:null;if(!r)return null;let o=X[r]||jt[r];if(!o&&(o=await Gt(r),!o))throw new Error(`Unknown db adapter: "${r}". Use registerAdapter() for adapters with optional deps.`);const n=await o();if(!n||typeof n.setup!="function")throw new Error(`Adapter "${r}" loader returned a module without a setup() function. Got keys: [${Object.keys(n||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return n.setup(s)},Z=t=>{if(!t)return 0;if(typeof t=="number")return t;const e=t.match(/^(\d+)(ms|s|m|h)$/);if(!e)return 0;const s=parseInt(e[1]),r=e[2];return r==="ms"?s:r==="s"?s*1e3:r==="m"?s*6e4:r==="h"?s*36e5:0},T=new Map,U=new Map,W=new Map,Wt=(t,e,s)=>{if(t.cache?.key)return t.cache.key;const r=Kt(t.params),o=s?`${s}:`:"",n=`${t.from}:${t.method}:${o}${JSON.stringify(r||"")}`;return e?`${n}:${e}`:n},tt=t=>T.get(t)||null,et=(t,e,s)=>{const r=T.get(t),o={data:e,error:s,time:Date.now(),stale:!1};T.set(t,o);const n=U.get(t);if(n)for(const a of n)l(a)&&a(o);return o},st=t=>{if(t){const e=T.get(t);e&&(e.stale=!0);return}for(const[,e]of T)e.stale=!0},dt=t=>{if(t){T.delete(t);return}T.clear()},oe=(t,e)=>(U.has(t)||U.set(t,new Set),U.get(t).add(e),()=>{const s=U.get(t);s&&(s.delete(e),s.size===0&&U.delete(t))}),wt=t=>!t&&t!==!1?{staleTime:6e4,gcTime:3e5}:t===!1?null:t===!0?{staleTime:6e4,gcTime:3e5}:typeof t=="number"?{staleTime:t,gcTime:Math.max(t*5,3e5)}:H(t)?{staleTime:Z(t),gcTime:3e5}:{staleTime:Z(t.stale||t.staleTime)||6e4,gcTime:Z(t.gc||t.gcTime||t.expire)||3e5,key:t.key};let ht=null;const Yt=()=>{ht||(ht=setInterval(()=>{const t=Date.now();for(const[e,s]of T){const r=U.get(e);!(r&&r.size>0)&&t-s.time>(s.gcTime||3e5)&&T.delete(e)}},3e4),ht.unref&&ht.unref())};Yt();const At=3,Tt=t=>Math.min(1e3*2**t,3e4),Lt=t=>{const e=t.retry;return e===!1?{count:0}:e===!0||e===void 0?{count:At,delay:Tt}:typeof e=="number"?{count:e,delay:Tt}:{count:e.count??At,delay:l(e.delay)?e.delay:typeof e.delay=="number"?()=>e.delay:Tt}},Ot=async(t,e)=>{const{count:s,delay:r}=e;let o;for(let n=0;n<=s;n++)try{const a=await t();if(a?.error){if(o=a.error,n<s){const c=l(r)?r(n,o):r;await new Promise(i=>setTimeout(i,c));continue}return a}return a}catch(a){if(o=a,n<s){const c=l(r)?r(n,a):r;await new Promise(i=>setTimeout(i,c));continue}throw a}return{data:null,error:o}},Y={focus:new Set,online:new Set};let Rt=!1;const xt=()=>{if(Rt||typeof window>"u")return;Rt=!0;const t=()=>{for(const s of Y.focus)s()},e=()=>{for(const s of Y.online)s()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&t()}),window.addEventListener("focus",t),window.addEventListener("online",e)},kt=(t,e)=>{const s=e.__ref;if(t===!0)return{from:s.__state||e.key,method:"select",query:!0,on:"create"};if(H(t))return{from:t,method:"select",query:!0,on:"create"};if(V(t)){const r={...t};return r.from=r.from||s.__state||e.key,r.method=r.method||"select",r.on=r.on||"create",r.query===void 0&&(r.query=!0),r}return null},Kt=t=>(!t||l(t),t),pt=(t,e)=>{const s=t?.state?.root||e?.state?.root;if(s?.lang)return s.lang},mt=(t,e)=>{const r=(t?.state?.root||e?.state?.root)?.__fetchScope;return r?String(r):void 0},$t=(t,e,s)=>{let r;if(!t)r=void 0;else if(l(t))r=t(e,e.state);else{r={};for(const o in t){const n=t[o];r[o]=l(n)?n(e,e.state):n}}return r},vt=async(t,e)=>{if(!t||t.__authInitialized||(t.__authInitialized=!0,!t.getSession))return;const s=(r,o)=>{const n=e.state?.root;n?.update&&n.update({auth:{user:r,session:o,loading:!1}})};try{const r=await t.getSession();s(r?.user||null,r)}catch(r){console.warn("[fetch] Failed to restore auth session:",r.message)}t.onAuthStateChange&&t.onAuthStateChange((r,o)=>{s(o?.user||null,o)})},Ft=async(t,e)=>{if(l(t.select))return t.auth!==!1&&await vt(t,e),t;if(t.__resolved)return t.auth!==!1&&await vt(t.__resolved,e),t.__resolved;if(t.__resolving)return t.__resolving;t.__resolving=Qt(t);const s=await t.__resolving;return delete t.__resolving,s?(s.auth=t.auth,s.url=t.url,s.key=t.key,t.__resolved=s,e.fetch=s,t.auth!==!1&&await vt(s,e),s):null},E=(t,e,...s)=>{const r=l(t[e])?t[e]:null;r&&r.call(t,...s,t,t.state,t.context)},A=(t,e,s,...r)=>{const o=t&&l(t[s])?t[s]:null;o&&o.call(e,...r,e,e.state,e.context)},rt=t=>{const e={},s=t.node;if(!s)return e;if(s.tagName==="FORM"){const o=new FormData(s);for(const[n,a]of o.entries())e[n]=a;return e}const r=s.querySelectorAll("input, textarea, select");for(let o=0;o<r.length;o++){const n=r[o],a=n.name||n.getAttribute("name");a&&(n.type==="checkbox"?e[a]=n.checked:n.type==="file"?e[a]=n.files:e[a]=n.value)}return e},Et=t=>t.responseType==="stream"||t.responseType==="response",Jt=["Blob","File","ArrayBuffer","ReadableStream","Response"],Dt=t=>t!==null&&typeof t=="object"&&(ArrayBuffer.isView(t)||Jt.includes(Object.prototype.toString.call(t).slice(8,-1))),q=(t,e,s,r={})=>{if(!s&&Dt(e))return;const o=s&&s.startsWith("~/"),n=o&&t.state?.root||t.state;if(n?.update)if(o){const a=s.slice(2);e&&typeof e=="object"&&!Array.isArray(e)&&!Dt(e)&&a in e?n.update(e,{preventFetch:!0,...r}):n.update({[a]:e},{preventFetch:!0,...r})}else{const a=s?{[s]:e}:e;n.update(a,{preventFetch:!0,...r})}},L=(t,e)=>{const s=t?.__ref;s&&(s.__fetchStatus=e,s.__fetching=e.isFetching,s.__fetchError=e.error)},N=async(t,e,s,r={})=>{const o=s?.fetch;if(!o||!e||!e.__ref)return;const n=e.__ref,a=mt(e,s);(!n.__fetchScopeOwner||n.__fetchScopeOwner.scope!==a)&&(n.__fetchScopeOwner={scope:a});const c=n.__fetchScopeOwner,i=()=>e.__ref===n&&n.__fetchScopeOwner===c&&mt(e,s)===a;if(t.enabled===!1||l(t.enabled)&&!t.enabled(e,e.state)||t.skip===!0||l(t.skip)&&t.skip(e,e.state))return;const h=await Ft(o,s);if(!h||!i())return;const{from:g,method:S,query:R,params:x,cache:nt,transform:D,single:z,auth:ot,fields:j,as:k,limit:I,offset:$,order:b,headers:K,baseUrl:C,responseType:B,page:p,cursor:P,getNextPageParam:J,getPreviousPageParam:it,infinite:at,placeholderData:v,initialData:F,select:m,keepPreviousData:M}=t;let G=H(m)?m:void 0;if(R&&l(e.getQuery)){const d=e.getQuery(h.name||"paths");d&&(G=d.select||d.length&&d.join(",")||G)}const ft=$t(x,e,s),ct=Et(t)?null:wt(nt),Nt=Lt(t),_t=pt(e,s),It=_t?`:${_t}`:"",Ut=a?`${a}:`:"",_=ct?nt?.key||`${g}:${S}:${Ut}${JSON.stringify(ft||"")}${at?":infinite":""}${p?":p"+JSON.stringify(p):""}${It}`:null;if(!n.__fetchInitialized&&_&&(n.__fetchInitialized=!0,F!==void 0)){const d=l(F)?F():F;et(_,d,null)}if((S==="select"||S==="rpc")&&_&&ct){const d=tt(_);if(d&&!d.error){const u=Date.now()-d.time,y=d.stale||u>(ct.staleTime||0);let f=d.data;if(l(m)&&(f=m(f,e,e.state)),D&&(f=D(f,e,e.state)),!i())return;if(q(e,f,k),!y){L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"});return}}else if(v!==void 0){const u=l(v)?v(e,e.state):v;u!==void 0&&q(e,u,k)}}if(_&&W.has(_)&&!r.force){const d=W.get(_);try{const u=await Promise.race([d,new Promise((y,f)=>setTimeout(()=>f("DEDUP_TIMEOUT"),15e3))]);if(!i())return;if(u?.data!==void 0){let y=u.data;if(l(m)&&(y=m(y,e,e.state)),D&&(y=D(y,e,e.state)),!i())return;q(e,y,k),E(e,"onFetchComplete",y),A(t,e,"onFetchComplete",y)}}catch{if(!i())return}return}const qt=!tt(_)?.data;L(e,{isFetching:!0,isLoading:qt,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const O=s?.analyze?.emitNetwork,yt=O?typeof performance<"u"?performance.now():Date.now():0;O&&O({phase:"start",mode:"query",from:g,method:S,cacheKey:_,lang:_t});const gt=Ot(async()=>{if(!i())return;if(ot!==!1&&h.auth!==!1&&h.getSession){const f=await h.getSession();if(!i())return;if(ot===!0&&!f){const w={message:"Not authenticated"};return L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:w,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",w),A(t,e,"onFetchError",w),{data:null,error:w}}}const d=h[S];if(!l(d))return{data:null,error:{message:`Method "${S}" not found on adapter`}};const u={from:g,select:G,params:ft,single:z,limit:I,offset:$,order:b,headers:K,baseUrl:C};B!==void 0&&(u.responseType=B);const y=pt(e,s);if(y&&(u.headers={...u.headers,"Accept-Language":y}),p!==void 0){if(V(p))p.offset!==void 0&&(u.offset=p.offset),p.limit!==void 0&&(u.limit=p.limit),p.cursor!==void 0&&(u.params={...u.params,cursor:p.cursor});else if(typeof p=="number"){const f=t.pageSize||I||20;u.offset=(p-1)*f,u.limit=f}}if(P!==void 0&&(u.params={...u.params,cursor:P}),S==="insert"||S==="update"||S==="upsert"){let f;if(j===!0||t.on==="submit")f=rt(e);else if(Q(j)){const w=rt(e);f={};for(const St of j)f[St]=w[St]}else e.state?.parse?f=e.state.parse():V(e.state)&&(f={...e.state});D&&(f=D(f,e,e.state)),u.data=f}if(S==="rpc"){let f=ft;if(t.on==="submit"){const w=rt(e);f=t.transformParams?t.transformParams(w,e,e.state):w}u.params=f}if(S==="subscribe"){const f=h.subscribe({from:g,params:ft,on:t.subscribeOn},(w,St,ee)=>{i()&&(q(e,w,k),E(e,"onFetchComplete",w),A(t,e,"onFetchComplete",w))});return i()?(n.__unsubscribe=f,{data:null,error:null,subscribed:!0}):(l(f)&&f(),{data:null,error:null,subscribed:!0})}return d(u)},Nt);_&&W.set(_,gt);try{const d=await gt;if(!i()||d?.subscribed)return;const{data:u,error:y}=d||{};if(y){_&&et(_,null,y),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:y,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",y),A(t,e,"onFetchError",y),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:y.message||y,durationMs:(typeof performance<"u"?performance.now():Date.now())-yt});return}if(u!==void 0){if((S==="select"||S==="rpc")&&_){const w=et(_,u,null);w.gcTime=ct?.gcTime||3e5}let f=u;if(at&&Q(u)&&(n.__pages||(n.__pages=[]),r.direction==="previous"?n.__pages.unshift(u):n.__pages.push(u),f=n.__pages.flat(),J&&(n.__nextPageParam=J(u,n.__pages),n.__hasNextPage=n.__nextPageParam!=null),it&&(n.__prevPageParam=it(u,n.__pages),n.__hasPreviousPage=n.__prevPageParam!=null)),l(m)&&(f=m(f,e,e.state)),D&&(f=D(f,e,e.state)),!i())return;(!M||f!==void 0)&&q(e,f,k),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",f),A(t,e,"onFetchComplete",f),O&&O({phase:"success",mode:"query",ok:!0,from:g,method:S,cacheKey:_,durationMs:(typeof performance<"u"?performance.now():Date.now())-yt})}}catch(d){if(!i())return;L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:d,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",d),A(t,e,"onFetchError",d),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:d.message||String(d),durationMs:(typeof performance<"u"?performance.now():Date.now())-yt})}finally{_&&W.get(_)===gt&&W.delete(_)}},Vt=(t,e,s)=>{const r=t.on,o=e.__ref;o.__fetchListeners||(o.__fetchListeners=[]);const n=t.__runner||N;if(r==="submit"){const a=i=>{i.preventDefault(),n(t,e,s)},c=e.node;c&&(c.addEventListener("submit",a),o.__fetchListeners.push(()=>c.removeEventListener("submit",a)))}else if(r==="click"){const a=()=>n(t,e,s),c=e.node;c&&(c.addEventListener("click",a),o.__fetchListeners.push(()=>c.removeEventListener("click",a)))}else r==="stateChange"&&(o.__fetchOnStateChange=()=>n(t,e,s))},Ht=(t,e,s)=>{const r=e.__ref;r.__fetchCleanups||(r.__fetchCleanups=[]),xt();const o=t.refetchInterval;if(o){const i=typeof o=="number"?o:Z(o);if(i>0){const h=setInterval(()=>{(t.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&N(t,e,s,{force:!0})},i);r.__fetchCleanups.push(()=>clearInterval(h))}}const n=Et(t),a=t.refetchOnWindowFocus===void 0?!n:t.refetchOnWindowFocus!==!1,c=t.refetchOnReconnect===void 0?!n:t.refetchOnReconnect!==!1;if(a){const i=()=>{const h=pt(e,s),g=mt(e,s),S=Wt(t,h,g),R=tt(S),x=wt(t.cache);(!R||R.stale||Date.now()-R.time>(x?.staleTime||0))&&N(t,e,s,{force:!0})};Y.focus.add(i),r.__fetchCleanups.push(()=>Y.focus.delete(i))}if(c){const i=()=>N(t,e,s,{force:!0});Y.online.add(i),r.__fetchCleanups.push(()=>Y.online.delete(i))}},Xt=(t,e,s)=>{if(!e.optimistic)return null;const r=t.__ref,o=e.as,n=t.state?.parse?t.state.parse():V(t.state)?{...t.state}:t.state;r.__optimisticSnapshot=n;const a=l(e.optimistic)?e.optimistic(s,n,t):e.optimistic;return a!==void 0&&q(t,a,o),n},Ct=(t,e)=>{const s=t.__ref,r=s.__optimisticSnapshot;r!==void 0&&(q(t,r,e.as),delete s.__optimisticSnapshot)},Zt=async(t,e,s)=>{const r=s?.fetch;if(!r)return;const o=await Ft(r,s);if(!o)return;const n=e.__ref,{method:a,from:c,fields:i,transform:h,as:g,on:S,auth:R,headers:x,baseUrl:nt,responseType:D,invalidates:z,optimistic:ot,onMutate:j,onSuccess:k,onError:I,onSettled:$}=t;let b;if(i===!0||S==="submit")b=rt(e);else if(Q(i)){const p=rt(e);b={};for(const P of i)b[P]=p[P]}else e.state?.parse?b=e.state.parse():V(e.state)&&(b={...e.state});h&&(b=h(b,e,e.state)),l(j)&&j(b,e,e.state);const K=ot?Xt(e,t,b):null;n.__fetching=!0,L(e,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const C=s?.analyze?.emitNetwork,B=C?typeof performance<"u"?performance.now():Date.now():0;C&&C({phase:"start",mode:"mutation",from:c,method:a});try{if(R!==!1&&o.auth!==!1&&o.getSession){const m=await o.getSession();if(R===!0&&!m){K!==void 0&&Ct(e,t);const M={message:"Not authenticated"};E(e,"onFetchError",M),A(t,e,"onFetchError",M);return}}const p=o[a];if(!l(p))return;const P={from:c,data:b,headers:x,baseUrl:nt};D!==void 0&&(P.responseType=D),t.params&&(P.params=$t(t.params,e,s));const J=pt(e,s);J&&(P.headers={...P.headers,"Accept-Language":J});const it=Lt(t),at=await Ot(()=>p(P),it),{data:v,error:F}=at||{};if(F){K!==void 0&&Ct(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:F,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",F),l(I)&&I(F,b,e),l($)&&$(null,F,b,e),C&&C({phase:"error",mode:"mutation",from:c,method:a,error:F.message||String(F),durationMs:(typeof performance<"u"?performance.now():Date.now())-B});return}if(delete n.__optimisticSnapshot,v!==void 0&&(g||!Dt(v))){const m=g?{[g]:v}:v;e.state?.update&&e.state.update(m,{preventFetch:!0})}if(L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",v),A(t,e,"onFetchComplete",v),l(k)&&k(v,b,e),l($)&&$(v,null,b,e),C&&C({phase:"success",mode:"mutation",ok:!0,from:c,method:a,durationMs:(typeof performance<"u"?performance.now():Date.now())-B}),z){const m=Q(z)?z:[z];for(const M of m)if(M===!0||M==="*")for(const[G]of T)G.startsWith(c+":")&&st(G);else st(M)}}catch(p){K!==void 0&&Ct(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",p),A(t,e,"onFetchError",p),l(I)&&I(p,b,e),l($)&&$(null,p,b,e),C&&C({phase:"error",mode:"mutation",from:c,method:a,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-B})}finally{n.__fetching=!1}},Mt=(t,e,s,r)=>{if(!t||!r?.fetch)return;const n=Pt(t,e);if(!n)return;const a=Q(n)?n.map(i=>kt(Pt(i,e),e)).filter(Boolean):[kt(n,e)].filter(Boolean);for(const i of a){const h=i.method==="insert"||i.method==="update"||i.method==="upsert"||i.method==="delete",g=h?Zt:N;i.on==="create"?g(i,e,r):Promise.resolve().then(()=>{Vt({...i,__runner:g},e,r)}),!h&&i.on==="create"&&(i.refetchInterval||i.refetchOnWindowFocus!==!1||i.refetchOnReconnect!==!1)&&Ht(i,e,r)}const c=e.__ref;c.refetch=i=>{for(const h of a)N(h,e,r,{force:!0,...i})},c.fetchNextPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=c.__nextPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"next",force:!0})},c.fetchPreviousPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=c.__prevPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"previous",force:!0})}},ie={invalidateQueries:t=>{if(!t){st();return}if(H(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&st(e);else if(Q(t)){const e=t.join(":");for(const[s]of T)s.includes(e)&&st(s)}},removeQueries:t=>{if(!t){dt();return}if(H(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&dt(e)},getQueryData:t=>tt(t)?.data??void 0,setQueryData:(t,e)=>{const s=tt(t),r=l(e)?e(s?.data):e;et(t,r,null)},prefetchQuery:async(t,e)=>{const s=e?.fetch;if(!s)return;const r=await Ft(s,e);if(!r)return;const o=t.cache?.key||`${t.from}:${t.method||"select"}:${JSON.stringify(t.params||"")}`,n=r[t.method||"select"];if(!l(n))return;const a={from:t.from,params:t.params,limit:t.limit,offset:t.offset,order:t.order,single:t.single,headers:t.headers,baseUrl:t.baseUrl};t.responseType!==void 0&&(a.responseType=t.responseType);const c=await n(a);if(c?.data!==void 0&&!c?.error&&!Et(t)){const i=et(o,c.data,null);i.gcTime=wt(t.cache)?.gcTime||3e5}return c},getCache:()=>T,clear:()=>dt(),dropNonLang:t=>{if(!t)return;const e=`:${t}`;for(const[s]of T)s.match(/:([a-z]{2,3})$/i)&&(s.endsWith(e)||dt(s))}},ae={name:"fetch",create(t){const e=t.fetch;e&&(t.parent||W.clear(),Mt(e,t,t.state,t.context))}};var fe=Mt;export{ne as createAdapter,fe as default,Mt as executeFetch,ae as fetchPlugin,vt as initAdapterAuth,Z as parseDuration,ie as queryClient,re as registerAdapter,Qt as resolveDb};
1
+ import{isArray as Q,isFunction as l,isObject as Z,isString as _e,exec as Ge}from"@symbo.ls/utils";import{createEffect as it}from"@symbo.ls/signal";import{dropEarly as ut}from"./early.js";const ct=["select","rpc","insert","update","upsert","delete","subscribe"],Ke={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},ye=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),ee=(()=>{if(typeof globalThis<"u"&&globalThis[ye])return globalThis[ye];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ye,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[ye]}catch{}return e})(),Se=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),Ce=(()=>{if(typeof globalThis<"u"&&globalThis[Se])return globalThis[Se];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,Se,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[Se]}catch{}return e})(),ft=5e3,lt=e=>new Promise(t=>{if(ee[e])return t(ee[e]);const r=Ce[e]||=[];let s=!1;const o=()=>{s||(s=!0,t(ee[e]||null))};r.push(o),setTimeout(o,ft)}),Ct=(e,t)=>{ee[e]=t;const r=Ce[e];if(r&&r.length){Ce[e]=[];for(const s of r)s()}},Mt=e=>typeof e=="string"&&!!(ee[e]||Ke[e]),Lt=e=>{const t={};for(const r of ct)e[r]&&(t[r]=e[r]);return t.name=e.name||"custom",t},dt=async e=>{if(!e)return null;if(typeof e.select=="function")return e;const{adapter:t,...r}=e,s=typeof t=="string"?t:typeof e=="string"?e:null;if(!s)return null;let o=ee[s]||Ke[s];if(!o&&(o=await lt(s),!o))throw new Error(`Unknown db adapter: "${s}". Use registerAdapter() for adapters with optional deps.`);const n=await o();if(!n||typeof n.setup!="function")throw new Error(`Adapter "${s}" loader returned a module without a setup() function. Got keys: [${Object.keys(n||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return n.setup(r)},se=e=>{if(!e)return 0;if(typeof e=="number")return e;const t=e.match(/^(\d+)(ms|s|m|h)$/);if(!t)return 0;const r=parseInt(t[1]),s=t[2];return s==="ms"?r:s==="s"?r*1e3:s==="m"?r*6e4:s==="h"?r*36e5:0},v=new Map,x=new Map,R=new Map;let I=0;const q=new Map,Me=new WeakMap,Le=(e,t,r,s,o=e.page,n=e.cursor)=>{if(e.cache?.key)return e.cache.key;const{from:i,method:u,infinite:a}=e,d=r?`${r}:`:"",_=s?`:${s}`:"",h=o?":p"+JSON.stringify(o):"",D=n!=null?":c"+JSON.stringify(n):"";return`${i}:${u}:${d}${JSON.stringify(t||"")}${a?":infinite":""}${h}${D}${_}`},ne=e=>v.get(e)||null,oe=(e,t,r,s=++I,o=!1)=>{const n={data:t,error:r,time:Date.now(),stale:o,seq:s};v.set(e,n);const i=x.get(e);if(i)for(const u of i)l(u)&&u(n);return n},be=(e,t)=>{const r=e?v.get(e):null;return r&&!r.error&&r.seq>t?r:null},ke=(e,t)=>(q.get(e)||0)>t,ge=e=>{if(e){v.delete(e),q.set(e,++I);return}for(const[t]of v)q.set(t,++I);for(const[t]of R)q.set(t,++I);v.clear()},kt=(e,t)=>(x.has(e)||x.set(e,new Set),x.get(e).add(t),()=>{const r=x.get(e);r&&(r.delete(t),r.size===0&&x.delete(e))}),Oe=e=>!e&&e!==!1?{staleTime:6e4,gcTime:3e5}:e===!1?null:e===!0?{staleTime:6e4,gcTime:3e5}:typeof e=="number"?{staleTime:e,gcTime:Math.max(e*5,3e5)}:_e(e)?{staleTime:se(e),gcTime:3e5}:{staleTime:se(e.stale||e.staleTime)||6e4,gcTime:se(e.gc||e.gcTime||e.expire)||3e5,key:e.key},V=new Set,xe=e=>!!e.ref&&e.element.__ref===e.ref,pt=({config:e,element:t,context:r})=>{try{return qe(e,t,r)}catch{return null}};let we=null;const ht=()=>{we||(we=setInterval(()=>{const e=Date.now();for(const[t,r]of v){const s=x.get(t);!(s&&s.size>0)&&e-r.time>(r.gcTime||3e5)&&v.delete(t)}for(const[t]of q)!v.has(t)&&!R.has(t)&&q.delete(t);for(const t of V)xe(t)||V.delete(t)},3e4),we.unref&&we.unref())};ht();const Ve=3,Re=e=>Math.min(1e3*2**e,3e4),We=(e,t)=>{const r=e.retry;return r===void 0&&t?{count:0}:r===!1?{count:0}:r===!0||r===void 0?{count:Ve,delay:Re}:typeof r=="number"?{count:r,delay:Re}:{count:r.count??Ve,delay:l(r.delay)?r.delay:typeof r.delay=="number"?()=>r.delay:Re}},Ye=async(e,t)=>{const{count:r,delay:s}=t;let o;for(let n=0;n<=r;n++)try{const i=await e();if(i?.error){if(o=i.error,n<r){const u=l(s)?s(n,o):s;await new Promise(a=>setTimeout(a,u));continue}return i}return i}catch(i){if(o=i,n<r){const u=l(s)?s(n,i):s;await new Promise(a=>setTimeout(a,u));continue}throw i}return{data:null,error:o}},te={focus:new Set,online:new Set};let Je=!1;const _t=()=>{if(Je||typeof window>"u")return;Je=!0;const e=()=>{for(const r of te.focus)r()},t=()=>{for(const r of te.online)r()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&e()}),window.addEventListener("focus",e),window.addEventListener("online",t)},He=(e,t)=>{const r=t.__ref;if(e===!0)return{from:r.__state||t.key,method:"select",query:!0,on:"create"};if(_e(e))return{from:e,method:"select",query:!0,on:"create"};if(Z(e)){const s={...e};return s.from=s.from||r.__state||t.key,s.method=s.method||"select",s.on=s.on||"create",s.query===void 0&&(s.query=!0),s}return null},yt=["insert","update","upsert","delete"],Xe=e=>yt.includes(e),Ie=e=>e.mutation===!0?!0:e.mutation===!1||e.method!=="rpc"?!1:e.on==="submit"||e.on==="click"||e.invalidates!=null,ae=(e,t)=>{const r=e?.state?.root||t?.state?.root;if(r?.lang)return r.lang},Te=(e,t)=>{const s=(e?.state?.root||t?.state?.root)?.__fetchScope;return s?String(s):void 0},ve=(e,t,r)=>{let s;if(!e)s=void 0;else if(l(e))s=e(t,t.state);else{s={};for(const o in e){const n=e[o];s[o]=l(n)?n(t,t.state):n}}return s},ie=(e,t)=>l(e)?e(t,t.state):e,qe=(e,t,r)=>Le(e,ve(e.params,t,r),Te(t,r),ae(t,r),ie(e.page,t),ie(e.cursor,t)),Ne=async(e,t)=>{if(!e||e.__authInitialized||(e.__authInitialized=!0,!e.getSession))return;const r=(s,o)=>{const n=t.state?.root;n?.update&&n.update({auth:{user:s,session:o,loading:!1}})};try{const s=await e.getSession();r(s?.user||null,s)}catch(s){console.warn("[fetch] Failed to restore auth session:",s.message)}e.onAuthStateChange&&e.onAuthStateChange((s,o)=>{r(o?.user||null,o)})},Ue=async(e,t)=>{if(l(e.select))return e.auth!==!1&&await Ne(e,t),e;if(e.__resolved)return e.auth!==!1&&await Ne(e.__resolved,t),e.__resolved;if(e.__resolving)return e.__resolving;e.__resolving=dt(e);const r=await e.__resolving;return delete e.__resolving,r?(r.auth=e.auth,r.url=e.url,r.key=e.key,e.__resolved=r,t.fetch=r,e.auth!==!1&&await Ne(r,t),r):null},F=(e,t,...r)=>{const s=l(e[t])?e[t]:null;s&&s.call(e,...r,e,e.state,e.context)},E=(e,t,r,...s)=>{const o=e&&l(e[r])?e[r]:null;o&&o.call(t,...s,t,t.state,t.context)},ue=e=>{const t={},r=e.node;if(!r)return t;if(r.tagName==="FORM"){const o=new FormData(r);for(const[n,i]of o.entries())t[n]=i;return t}const s=r.querySelectorAll("input, textarea, select");for(let o=0;o<s.length;o++){const n=s[o],i=n.name||n.getAttribute("name");i&&(n.type==="checkbox"?t[i]=n.checked:n.type==="file"?t[i]=n.files:t[i]=n.value)}return t},Fe=e=>e.responseType==="stream"||e.responseType==="response",St=["Blob","File","ArrayBuffer","ReadableStream","Response"],Qe=e=>e!==null&&typeof e=="object"&&(ArrayBuffer.isView(e)||St.includes(Object.prototype.toString.call(e).slice(8,-1))),$=(e,t,r,s={})=>{if(!r&&Qe(t))return;const o=r&&r.startsWith("~/"),n=o&&e.state?.root||e.state;if(n?.update)if(o){const i=r.slice(2);t&&typeof t=="object"&&!Array.isArray(t)&&!Qe(t)&&i in t?n.update(t,{preventFetch:!0,...s}):n.update({[i]:t},{preventFetch:!0,...s})}else{const i=r?{[r]:t}:t;n.update(i,{preventFetch:!0,...s})}},C=(e,t)=>{const r=e?.__ref;r&&(r.__fetchStatus={...t,isError:!!t.error},r.__fetching=t.isFetching,r.__fetchError=t.error)},Ze=(e,t,r)=>{const s=e.__pages&&e.__pages.length?e.__pages:[r];l(t.getNextPageParam)&&(e.__nextPageParam=t.getNextPageParam(s[s.length-1],s),e.__hasNextPage=e.__nextPageParam!=null),l(t.getPreviousPageParam)&&(e.__prevPageParam=t.getPreviousPageParam(s[0],s),e.__hasPreviousPage=e.__prevPageParam!=null)},N=async(e,t,r,s={})=>{const o=r?.fetch;if(!o||!t||!t.__ref)return;const n=t.__ref,i=Te(t,r);(!n.__fetchScopeOwner||n.__fetchScopeOwner.scope!==i)&&(n.__fetchScopeOwner={scope:i});const u=n.__fetchScopeOwner,a=()=>t.__ref===n&&n.__fetchScopeOwner===u&&Te(t,r)===i;if(e.enabled===!1||l(e.enabled)&&!e.enabled(t,t.state)||e.skip===!0||l(e.skip)&&e.skip(t,t.state))return;const d=await Ue(o,r);if(!d||!a())return;const{from:_,method:h,query:D,params:De,cache:Pe,transform:P,single:ce,auth:fe,fields:W,as:L,limit:z,offset:U,order:b,headers:re,baseUrl:m,responseType:Y,page:T,cursor:M,infinite:j,placeholderData:J,initialData:H,select:g,keepPreviousData:k}=e;let B=_e(g)?g:void 0;if(D&&l(t.getQuery)){const p=t.getQuery(d.name||"paths");p&&(B=p.select||p.length&&p.join(",")||B)}const G=ve(De,t,r),A=ie(T,t),me=ie(M,t),le=Ie(e),de=Fe(e)||le?null:Oe(Pe),nt=We(e,le||Xe(h)),je=ae(t,r),y=de?Le(e,G,i,je,A,me):null;if(!n.__fetchInitialized&&y&&(n.__fetchInitialized=!0,H!==void 0)){const p=l(H)?H():H;oe(y,p,null)}if((h==="select"||h==="rpc")&&y&&de&&!s.refresh&&!s.force){const p=ne(y);if(p&&!p.error){const c=Date.now()-p.time,w=p.stale||c>(de.staleTime||0);j&&Q(p.data)&&!n.__pages&&(n.__pages=[p.data],Ze(n,e,p.data));let f=p.data;if(l(g)&&(f=g(f,t,t.state)),P&&(f=P(f,t,t.state)),!a())return;if(!w){C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),$(t,f,L);return}$(t,f,L)}else if(J!==void 0){const c=l(J)?J(t,t.state):J;c!==void 0&&$(t,c,L)}}const pe=y&&!s.force?R.get(y):null;if(pe&&!ke(y,Me.get(pe)||0)){const p=c=>{C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:c,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",c),E(e,t,"onFetchError",c)};try{const c=await Promise.race([pe,new Promise((w,f)=>setTimeout(()=>f("DEDUP_TIMEOUT"),15e3))]);if(!a())return;if(c?.error)p(c.error);else if(c?.data!==void 0){const w=!j&&be(y,Me.get(pe)||0);let f=w?w.data:c.data;if(l(g)&&(f=g(f,t,t.state)),P&&(f=P(f,t,t.state)),!a())return;$(t,f,L),F(t,"onFetchComplete",f),E(e,t,"onFetchComplete",f)}}catch(c){if(!a())return;c!=="DEDUP_TIMEOUT"&&p(c)}return}const ot=!ne(y)?.data;C(t,{isFetching:!0,isLoading:ot,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),F(t,"onFetchStart"),E(e,t,"onFetchStart");const O=r?.analyze?.emitNetwork,Ae=O?typeof performance<"u"?performance.now():Date.now():0;O&&O({phase:"start",mode:"query",from:_,method:h,cacheKey:y,lang:je});const at=async()=>{if(!a())return;if(fe!==!1&&d.auth!==!1&&d.getSession){const f=await d.getSession();if(!a())return;if(fe===!0&&!f){const S={message:"Not authenticated"};return C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:S,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",S),E(e,t,"onFetchError",S),{data:null,error:S}}}const p=d[h];if(!l(p))return{data:null,error:{message:`Method "${h}" not found on adapter`}};const c={from:_,select:B,params:G,single:ce,limit:z,offset:U,order:b,headers:re,baseUrl:m};Y!==void 0&&(c.responseType=Y);const w=ae(t,r);if(w&&(c.headers={...c.headers,"Accept-Language":w}),A!==void 0){if(Z(A))A.offset!==void 0&&(c.offset=A.offset),A.limit!==void 0&&(c.limit=A.limit),A.cursor!==void 0&&(c.params={...c.params,cursor:A.cursor});else if(typeof A=="number"){const f=e.pageSize||z||20;c.offset=(A-1)*f,c.limit=f}}if(me!==void 0&&(c.params={...c.params,cursor:me}),h==="insert"||h==="update"||h==="upsert"){let f;if(W===!0||e.on==="submit")f=ue(t);else if(Q(W)){const S=ue(t);f={};for(const K of W)f[K]=S[K]}else t.state?.parse?f=t.state.parse():Z(t.state)&&(f={...t.state});P&&(f=P(f,t,t.state)),c.data=f}if(h==="rpc"){let f=G;if(e.on==="submit"){const S=ue(t);f=e.transformParams?e.transformParams(S,t,t.state):S}c.params=f,c.read=!le&&e.read!==!1}if(h==="subscribe"){if(l(n.__unsubscribe)){const S=n.__unsubscribe;n.__unsubscribe=null;try{S()}catch{}}const f=d.subscribe({from:_,params:G,on:e.subscribeOn},(S,K,Be)=>{a()&&($(t,S,L),F(t,"onFetchComplete",S),E(e,t,"onFetchComplete",S))});return a()?(n.__unsubscribe=f,{data:null,error:null,subscribed:!0}):(l(f)&&f(),{data:null,error:null,subscribed:!0})}return p(c)},X=++I,he=Ye(at,nt);Me.set(he,X),y&&R.set(y,he);try{const p=await he;if(le&&e.invalidates&&p&&!p.error&&!p.subscribed&&tt(e.invalidates,_),!a()||p?.subscribed)return;const{data:c,error:w}=p||{};if(w){y&&!be(y,X)&&oe(y,null,w,X),C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:w,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",w),E(e,t,"onFetchError",w),O&&O({phase:"error",mode:"query",from:_,method:h,cacheKey:y,error:w.message||w,durationMs:(typeof performance<"u"?performance.now():Date.now())-Ae});return}if(c!==void 0){let f=c;if((h==="select"||h==="rpc")&&y){const K=!j&&be(y,X);if(K)f=K.data;else{const Be=oe(y,c,null,X,ke(y,X));Be.gcTime=de?.gcTime||3e5}}let S=f;if(j&&Q(c)&&((!n.__pages||!s.direction)&&(n.__pages=[]),s.direction==="previous"?n.__pages.unshift(c):n.__pages.push(c),S=n.__pages.flat(),Ze(n,e,c)),l(g)&&(S=g(S,t,t.state)),P&&(S=P(S,t,t.state)),!a())return;C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),(!k||S!==void 0)&&$(t,S,L),F(t,"onFetchComplete",S),E(e,t,"onFetchComplete",S),O&&O({phase:"success",mode:"query",ok:!0,from:_,method:h,cacheKey:y,durationMs:(typeof performance<"u"?performance.now():Date.now())-Ae})}}catch(p){if(!a())return;C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",p),E(e,t,"onFetchError",p),O&&O({phase:"error",mode:"query",from:_,method:h,cacheKey:y,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-Ae})}finally{y&&R.get(y)===he&&R.delete(y)}},bt=(e,t,r)=>{const s=e.on,o=t.__ref;if(!o)return;o.__fetchListeners||(o.__fetchListeners=[]);const n=e.__runner||N;if(s==="submit"){const i=a=>{a.preventDefault(),n(e,t,r)},u=t.node;u&&(u.addEventListener("submit",i),o.__fetchListeners.push(()=>u.removeEventListener("submit",i)))}else if(s==="click"){const i=()=>n(e,t,r),u=t.node;u&&(u.addEventListener("click",i),o.__fetchListeners.push(()=>u.removeEventListener("click",i)))}else s==="stateChange"&&gt(e,t,r,n)},gt=(e,t,r,s)=>{const o=t.__ref;let n;const i=it(()=>{let u;try{u=JSON.stringify([ve(e.params,t,r)??null,l(e.enabled)?!!e.enabled(t,t.state):e.enabled!==!1,l(e.skip)?!!e.skip(t,t.state):e.skip===!0,ie(e.page,t)??null])}catch{return}if(n===void 0){n=u;return}u!==n&&(n=u,Promise.resolve().then(()=>s(e,t,r)))});Array.isArray(o.__effects)?o.__effects.push(i):o.__fetchListeners.push(()=>i.dispose())},wt=(e,t,r)=>{const s=t.__ref;s.__fetchCleanups||(s.__fetchCleanups=[]),_t();const o=e.refetchInterval;if(o){const a=typeof o=="number"?o:se(o);if(a>0){const d=setInterval(()=>{(e.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&N(e,t,r,{force:!0})},a);s.__fetchCleanups.push(()=>clearInterval(d))}}const n=Fe(e),i=e.refetchOnWindowFocus===void 0?!n:e.refetchOnWindowFocus!==!1,u=e.refetchOnReconnect===void 0?!n:e.refetchOnReconnect!==!1;if(i){const a=()=>{const d=qe(e,t,r),_=ne(d),h=Oe(e.cache);(!_||_.stale||Date.now()-_.time>(h?.staleTime||0))&&N(e,t,r,{force:!0})};te.focus.add(a),s.__fetchCleanups.push(()=>te.focus.delete(a))}if(u){const a=()=>N(e,t,r,{force:!0});te.online.add(a),s.__fetchCleanups.push(()=>te.online.delete(a))}},Tt=(e,t,r)=>{if(!t.optimistic)return null;const s=e.__ref,o=t.as,n=e.state?.parse?e.state.parse():Z(e.state)?{...e.state}:e.state;s.__optimisticSnapshot=n;const i=l(t.optimistic)?t.optimistic(r,n,e):t.optimistic;return i!==void 0&&$(e,i,o),n},$e=(e,t)=>{const r=e.__ref;if(!r||!t.optimistic)return;const s=r.__optimisticSnapshot;s!==void 0&&($(e,s,t.as),delete r.__optimisticSnapshot)},ze=e=>{if(!e)return()=>!0;if(_e(e))return t=>t.includes(e);if(Q(e)){const t=e.join(":");return r=>r.includes(t)}return e instanceof RegExp?t=>(e.lastIndex=0,e.test(t)):l(e)?t=>{try{return!!e(t)}catch{return!1}}:()=>!1},vt=e=>{const t=[];for(const r of V){if(!xe(r)){V.delete(r);continue}const s=pt(r);s&&e(s)&&t.push(N(r.config,r.element,r.context,{refresh:!0}))}return Promise.allSettled(t).then(()=>{})},et=e=>{ut();for(const[t,r]of v)e(t)&&(r.stale=!0,q.set(t,++I));for(const[t]of R)!v.has(t)&&e(t)&&q.set(t,++I);return vt(e)},tt=(e,t)=>{const r=(Q(e)?e:[e]).map(s=>s===!0||s==="*"?o=>o.startsWith(t+":"):s?ze(s):()=>!1);return et(s=>r.some(o=>o(s)))},Ft=e=>{for(const[t]of v)e(t)&&ge(t);for(const[t]of R)e(t)&&q.set(t,++I)},Et=async(e,t,r)=>{const s=r?.fetch;if(!s)return;const o=await Ue(s,r);if(!o)return;const n=t.__ref,{method:i,from:u,fields:a,transform:d,as:_,on:h,auth:D,headers:De,baseUrl:Pe,responseType:P,invalidates:ce,optimistic:fe,onMutate:W,onSuccess:L,onError:z,onSettled:U}=e;let b;if(a===!0||h==="submit")b=ue(t);else if(Q(a)){const T=ue(t);b={};for(const M of a)b[M]=T[M]}else t.state?.parse?b=t.state.parse():Z(t.state)&&(b={...t.state});d&&(b=d(b,t,t.state)),l(W)&&W(b,t,t.state);const re=fe?Tt(t,e,b):null;n.__fetching=!0,C(t,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),F(t,"onFetchStart"),E(e,t,"onFetchStart");const m=r?.analyze?.emitNetwork,Y=m?typeof performance<"u"?performance.now():Date.now():0;m&&m({phase:"start",mode:"mutation",from:u,method:i});try{if(D!==!1&&o.auth!==!1&&o.getSession){const B=await o.getSession();if(D===!0&&!B){re!==void 0&&$e(t,e);const G={message:"Not authenticated"};F(t,"onFetchError",G),E(e,t,"onFetchError",G);return}}const T=o[i];if(!l(T))return;const M={from:u,data:b,headers:De,baseUrl:Pe};P!==void 0&&(M.responseType=P),e.params&&(M.params=ve(e.params,t,r));const j=ae(t,r);j&&(M.headers={...M.headers,"Accept-Language":j});const J=We(e,!0),H=await Ye(()=>T(M),J),{data:g,error:k}=H||{};if(k){re!==void 0&&$e(t,e),C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:k,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",k),l(z)&&z(k,b,t),l(U)&&U(null,k,b,t),m&&m({phase:"error",mode:"mutation",from:u,method:i,error:k.message||String(k),durationMs:(typeof performance<"u"?performance.now():Date.now())-Y});return}if(delete n.__optimisticSnapshot,C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),g!==void 0&&(_||!Qe(g))){const B=_?{[_]:g}:g;t.state?.update&&t.state.update(B,{preventFetch:!0})}F(t,"onFetchComplete",g),E(e,t,"onFetchComplete",g),l(L)&&L(g,b,t),l(U)&&U(g,null,b,t),m&&m({phase:"success",mode:"mutation",ok:!0,from:u,method:i,durationMs:(typeof performance<"u"?performance.now():Date.now())-Y}),ce&&tt(ce,u)}catch(T){re!==void 0&&$e(t,e),C(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:T,status:"error",fetchStatus:"idle"}),F(t,"onFetchError",T),E(e,t,"onFetchError",T),l(z)&&z(T,b,t),l(U)&&U(null,T,b,t),m&&m({phase:"error",mode:"mutation",from:u,method:i,error:T.message||String(T),durationMs:(typeof performance<"u"?performance.now():Date.now())-Y})}finally{n.__fetching=!1}},Dt=e=>{const t=r=>{try{r()}catch{}};for(const r of e.__fetchCleanups||[])t(r);for(const r of e.__fetchListeners||[])t(r);l(e.__unsubscribe)&&t(e.__unsubscribe);for(const r of e.__fetchMounted||[])V.delete(r);e.__fetchCleanups=[],e.__fetchListeners=[],e.__unsubscribe=null,e.__fetchMounted=[]},rt=(e,t,r,s)=>{if(!e||!s?.fetch)return;const n=Ge(e,t);if(!n)return;const i=Q(n)?n.map(a=>He(Ge(a,t),t)).filter(Boolean):[He(n,t)].filter(Boolean),u=t.__ref;if(u.__fetchMounted)for(const a of u.__fetchMounted)V.delete(a);u.__fetchMounted=[],!u.__fetchDisposer&&Q(u.__effects)&&(u.__fetchDisposer={dispose:()=>Dt(u)},u.__effects.push(u.__fetchDisposer));for(const a of i){const d=Xe(a.method),_=d?Et:N,h=!d&&!Ie(a)&&a.method!=="subscribe";if(a.on==="create"?_(a,t,s):Promise.resolve().then(()=>{bt({...a,__runner:_},t,s)}),h&&a.on==="create"&&((a.refetchInterval||a.refetchOnWindowFocus!==!1||a.refetchOnReconnect!==!1)&&wt(a,t,s),!Fe(a))){const D={element:t,ref:u,config:a,context:s};V.add(D),u.__fetchMounted.push(D)}}u.refetch=a=>{for(const d of i)N(d,t,s,{force:!0,...a})},u.fetchNextPage=()=>{const a=i[0];if(!a||!a.infinite)return;const d=u.__nextPageParam;if(d==null)return;const _={...a,cursor:d};N(_,t,s,{direction:"next",force:!0})},u.fetchPreviousPage=()=>{const a=i[0];if(!a||!a.infinite)return;const d=u.__prevPageParam;if(d==null)return;const _={...a,cursor:d};N(_,t,s,{direction:"previous",force:!0})}},Ee={invalidateQueries:e=>et(ze(e)),removeQueries:e=>{if(!e){ge();return}Ft(ze(e))},getQueryData:e=>ne(e)?.data??void 0,setQueryData:(e,t)=>{const r=ne(e),s=l(t)?t(r?.data):t;oe(e,s,null)},prefetchQuery:async(e,t)=>{const r=t?.fetch;if(!r)return;const s=await Ue(r,t);if(!s)return;const o=e.method||"select",n=Te(null,t),i=ae(null,t),u=Le({...e,method:o},e.params,n,i),a=s[o];if(!l(a))return;const d={from:e.from,params:e.params,limit:e.limit,offset:e.offset,order:e.order,single:e.single,headers:e.headers,baseUrl:e.baseUrl};i&&(d.headers={...d.headers,"Accept-Language":i}),e.responseType!==void 0&&(d.responseType=e.responseType),o==="rpc"&&(d.read=!Ie(e)&&e.read!==!1);const _=++I,h=await a(d);if(h?.data!==void 0&&!h?.error&&!Fe(e)&&!be(u,_)){const D=oe(u,h.data,null,_,ke(u,_));D.gcTime=Oe(e.cache)?.gcTime||3e5}return h},getCache:()=>v,clear:()=>ge(),dropNonLang:e=>{if(!e)return;const t=`:${e}`;for(const[r]of v)r.match(/:([a-z]{2,3})$/i)&&(r.endsWith(t)||ge(r))}},st=(e,t)=>Z(e)?qe({method:"select",...e},t,t?.context):e,Ot={invalidateQueries(e){return Ee.invalidateQueries(e)},removeQueries(e){return Ee.removeQueries(e)},getQueryData(e){return Ee.getQueryData(st(e,this))},setQueryData(e,t){return Ee.setQueryData(st(e,this),t)}},Rt={name:"fetch",create(e){const t=e.fetch;t&&(e.parent||R.clear(),rt(t,e,e.state,e.context))}};var It=rt;export{Lt as createAdapter,It as default,rt as executeFetch,Ot as fetchFunctions,Rt as fetchPlugin,Mt as hasAdapter,Ne as initAdapterAuth,se as parseDuration,Ee as queryClient,Ct as registerAdapter,dt as resolveDb};
package/early.js ADDED
@@ -0,0 +1,160 @@
1
+ 'use strict'
2
+
3
+ // --- Early requests (`fetch.early`) ---
4
+ //
5
+ // A page's first view waits for its data twice over: the app bundle downloads,
6
+ // boots and mounts, and only THEN do its queries ask. `fetch.early` (opt-in)
7
+ // lets the build emit a pre-boot script (earlyScript.js createEarlyScript)
8
+ // that starts the first view's GETs while the HTML is still parsing, and lets
9
+ // the REST adapter ADOPT each answer for the first call that asks for exactly
10
+ // that request instead of sending it again.
11
+ //
12
+ // The two sides share a registry on globalThis under a `Symbol.for` slot —
13
+ // the pre-boot script runs before any module, so a global is the only thing
14
+ // it can hand over through; the Symbol keeps it off the visible namespace and
15
+ // shared by every copy of this package (same rationale as CUSTOM_ADAPTERS).
16
+ // { time, closed, entries: { [earlyKey]: { time, answer: Promise<Response|null> } } }
17
+ // The script creates it; an adapter that finds none creates it CLOSED, so a
18
+ // pre-boot script that arrives after the app booted (an async script on a
19
+ // cold cache) sends nothing: no call would be left to adopt its answers.
20
+ //
21
+ // The pure helpers below (earlyKey, isScalarParams, matchEarlyRoute) are ALSO
22
+ // embedded into the pre-boot script by source (`fn.toString()`), so the script
23
+ // and the adapter key requests with the same code. They must stay
24
+ // self-contained: no reference to anything outside their own parameters and
25
+ // the platform's built-ins (URL, decodeURIComponent, …).
26
+
27
+ export const EARLY_KEY = '@symbo.ls/fetch:EARLY'
28
+
29
+ // How long an early answer stays adoptable, counted from when the pre-boot
30
+ // script sent the request: long enough for a slow app bundle on a slow
31
+ // network to boot and ask, short enough that an adopted answer is never older
32
+ // than a default-cache query answer (staleTime 1m) may be.
33
+ export const EARLY_MAX_AGE = 30000
34
+
35
+ // The identity of a GET: its URL with the query sorted (the order of params
36
+ // keys is the caller's accident, not a different request) and the language
37
+ // it asked in — the only header an early GET sends, and one a backend may
38
+ // answer differently by.
39
+ export const earlyKey = (url, lang) => {
40
+ const parsed = new URL(url)
41
+ parsed.searchParams.sort()
42
+ return parsed.toString() + ' ' + (lang || '')
43
+ }
44
+
45
+ // An RPC goes early as a GET with its arguments in the query string, and only
46
+ // a string, a finite number or a boolean reads back the same from there: a
47
+ // JSON body's null (sent as null, but dropped from a query), an object or an
48
+ // array would reach the function as something else. `undefined` is dropped
49
+ // by both forms.
50
+ export const isScalarParams = (params) => {
51
+ if (params === undefined || params === null) return true
52
+ if (typeof params !== 'object' || Array.isArray(params)) return false
53
+ // A plain object only: a FormData or Blob body is no argument list.
54
+ const proto = Object.getPrototypeOf(params)
55
+ if (proto !== Object.prototype && proto !== null) return false
56
+ for (const key in params) {
57
+ const value = params[key]
58
+ if (value === undefined || typeof value === 'string' || typeof value === 'boolean') continue
59
+ if (typeof value === 'number' && isFinite(value)) continue
60
+ return false
61
+ }
62
+ return true
63
+ }
64
+
65
+ // The route pattern a path opens, scored like the router's matchRoute: a
66
+ // literal segment beats a `:param`, which beats a trailing `*`. Stricter in
67
+ // one way — a pattern must cover every segment — because a wrong guess here
68
+ // costs a wasted request, never a wrong answer (adoption is by request
69
+ // identity, not by route). Returns { index, params } or null.
70
+ export const matchEarlyRoute = (patterns, path) => {
71
+ const split = (value) => String(value).split('/').filter(Boolean)
72
+ const segments = split(path)
73
+ let best = null
74
+ for (let index = 0; index < patterns.length; index++) {
75
+ const parts = split(patterns[index])
76
+ const wildcard = parts[parts.length - 1] === '*'
77
+ const fixed = wildcard ? parts.length - 1 : parts.length
78
+ if (wildcard ? segments.length < fixed : segments.length !== fixed) continue
79
+ const params = {}
80
+ let score = wildcard ? -1 : 0
81
+ let matched = true
82
+ for (let i = 0; i < fixed; i++) {
83
+ if (parts[i].charAt(0) === ':') {
84
+ try { params[parts[i].slice(1)] = decodeURIComponent(segments[i]) } catch (e) { matched = false; break }
85
+ score += 1
86
+ } else if (parts[i] === segments[i]) {
87
+ score += 3
88
+ } else {
89
+ matched = false
90
+ break
91
+ }
92
+ }
93
+ if (matched && (!best || score > best.score)) best = { index, params, score }
94
+ }
95
+ return best && { index: best.index, params: best.params }
96
+ }
97
+
98
+ const registryKey = () => Symbol.for(EARLY_KEY)
99
+
100
+ // `fetch.early` with its `query` and `rpc` defaulting to the adapter's
101
+ // `reads` (adapters/rest.js): the same two options, declared once, drive both
102
+ // the pre-boot script and the adapter's own GETs. Used by both sides — the
103
+ // build (earlyScript.js) and the adapter (openEarly) — so they agree. An
104
+ // `early` that sets its own keeps them; no `early` stays no `early`.
105
+ export const withReads = (early, reads) => {
106
+ if (!early || typeof early !== 'object' || !reads || typeof reads !== 'object') return early
107
+ const merged = { ...early }
108
+ if (merged.query === undefined && reads.query !== undefined) merged.query = reads.query
109
+ if (merged.rpc === undefined && reads.rpc !== undefined) merged.rpc = reads.rpc
110
+ return merged
111
+ }
112
+
113
+ // The adapter's side of the hand-off, called once when a REST adapter with
114
+ // `early` is set up. Closes the registry against late pre-boot scripts and
115
+ // returns what the adapter needs to recognise an early request: the
116
+ // configured headers the script carried as query parameters (lower-cased
117
+ // name → configured value), whether RPCs went as GETs, and the answer age.
118
+ // No `early` config → null, and the adapter never looks (the opt-in).
119
+ export const openEarly = (config, headers) => {
120
+ if (!config || typeof config !== 'object') return null
121
+ const key = registryKey()
122
+ let registry = globalThis[key]
123
+ if (!registry) {
124
+ registry = { time: Date.now(), entries: {} }
125
+ globalThis[key] = registry
126
+ }
127
+ registry.closed = true
128
+ const carried = {}
129
+ for (const name in config.query || {}) {
130
+ for (const header in headers || {}) {
131
+ if (header.toLowerCase() === name.toLowerCase()) carried[header.toLowerCase()] = headers[header]
132
+ }
133
+ }
134
+ const maxAge = typeof config.maxAge === 'number' && config.maxAge >= 0 ? config.maxAge : EARLY_MAX_AGE
135
+ return { carried, rpc: config.rpc === 'get', maxAge }
136
+ }
137
+
138
+ // The waiting answer for `key`, taken ONCE (a body can be read once; a second
139
+ // identical call asks the network). Resolves to an ok Response, or null when
140
+ // the early request failed, was refused (a 4xx/5xx may be the early form's
141
+ // own problem — a query-string key or a GET the backend does not serve — so
142
+ // the call's own request decides), or is older than `maxAge`.
143
+ export const takeEarly = (key, maxAge = EARLY_MAX_AGE) => {
144
+ const registry = globalThis[registryKey()]
145
+ const entry = registry && registry.entries && registry.entries[key]
146
+ if (!entry) return null
147
+ delete registry.entries[key]
148
+ if (!(Date.now() - entry.time <= maxAge)) return null
149
+ return Promise.resolve(entry.answer).then(
150
+ (res) => (res && res.ok && !res.bodyUsed ? res : null),
151
+ () => null
152
+ )
153
+ }
154
+
155
+ // Forget every answer still waiting. An invalidation means a write happened:
156
+ // an answer asked for before it may predate it.
157
+ export const dropEarly = () => {
158
+ const registry = globalThis[registryKey()]
159
+ if (registry && registry.entries) registry.entries = {}
160
+ }
package/earlyScript.js ADDED
@@ -0,0 +1,204 @@
1
+ 'use strict'
2
+
3
+ // --- The pre-boot script of `fetch.early` (build side) ---
4
+ //
5
+ // createEarlyScript(project) returns the source of a classic script that the
6
+ // build writes next to the page and references from its <head>
7
+ // (@symbo.ls/cli helpers/earlyScript.js). It runs while the HTML parses,
8
+ // before any module, so it carries everything itself: the adapter's address,
9
+ // the configured headers it sends as query parameters, the language rule and
10
+ // the declared requests as data, and the address helpers BY SOURCE — the REST
11
+ // adapter's own buildUrl / selectQuery and early.js's earlyKey /
12
+ // isScalarParams / matchEarlyRoute — so an early request has exactly the
13
+ // address and identity the adapter computes for the call that adopts it.
14
+ //
15
+ // Build-time only: a separate entry (`@symbo.ls/fetch/early-script`) that
16
+ // the runtime bundle never imports.
17
+ //
18
+ // Declaration (the REST adapter's config, `fetch` in config.js):
19
+ //
20
+ // fetch: {
21
+ // adapter: 'rest', url, headers: { apikey: '…' },
22
+ // reads: { query: …, rpc: … }, // the adapter's own anonymous GETs (rest.js)
23
+ // early: {
24
+ // query: { apikey: 'apikey' }, // configured header → query parameter (default: reads.query)
25
+ // rpc: 'get', // the backend serves read-only RPCs as GETs (default: reads.rpc)
26
+ // maxAge: 30000, // adapter side: how old an answer may be
27
+ // always: [ …requests ] | (params, ctx) => [ …requests ],
28
+ // routes: { '/blog/:id': [ …requests ] | ({ id }, ctx) => [ …requests ] }
29
+ // }
30
+ // }
31
+ //
32
+ // A request is the adapter call it stands for — `{ method: 'select' | 'rpc',
33
+ // from, params, select, limit, offset, order, single }` — plus `lang`: by
34
+ // default it asks in the active language (Accept-Language), as a declarative
35
+ // `fetch` does; `lang: false` for one a getDB() call or polyglot's loader
36
+ // makes (they send none). `ctx` is { path, query (URLSearchParams), lang,
37
+ // storage(key) → localStorage value or null }.
38
+
39
+ import { buildUrl, selectQuery } from './adapters/rest.js'
40
+ import { EARLY_KEY, earlyKey, isScalarParams, matchEarlyRoute, withReads } from './early.js'
41
+
42
+ // polyglot's own default for where it keeps the chosen language
43
+ // (@symbo.ls/polyglot STORAGE_KEY_LANG): the script must read the same slot
44
+ // the app will, or its requests ask in another language than the app's.
45
+ const POLYGLOT_LANG_KEY = 'smbls_lang'
46
+
47
+ // The fetch() options an early GET may copy from the adapter's — the ones
48
+ // that change what comes back. Headers never: every header but the language
49
+ // would make the request non-simple (a CORS preflight); the configured ones
50
+ // travel as query parameters (`early.query`) instead.
51
+ const FETCH_OPTION_KEYS = ['credentials', 'mode', 'cache', 'redirect', 'referrerPolicy', 'priority']
52
+
53
+ const compiles = (body) => {
54
+ try {
55
+ new Function(body)
56
+ return true
57
+ } catch (e) {
58
+ return false
59
+ }
60
+ }
61
+
62
+ // A request function as an expression the script can hold: its own source
63
+ // (a function, or the string frank serialized it to). A method shorthand —
64
+ // `'/blog/:id' ({ id }) { … }` — is no expression, so it is read back out of
65
+ // an object literal. A function must stand alone: it runs before the app, with
66
+ // nothing but its arguments and the browser's globals.
67
+ const functionSource = (fn, where) => {
68
+ const source = typeof fn === 'function' ? fn.toString() : String(fn).trim()
69
+ if (compiles('return (' + source + ')')) return '(' + source + ')'
70
+ if (compiles('return ({' + source + '})')) return 'Object.values({' + source + '})[0]'
71
+ throw new Error(`@symbo.ls/fetch early: the request function of ${where} does not compile on its own`)
72
+ }
73
+
74
+ const requestsSource = (requests, where) => {
75
+ if (typeof requests === 'function' || typeof requests === 'string') return functionSource(requests, where)
76
+ return JSON.stringify(Array.isArray(requests) ? requests : [])
77
+ }
78
+
79
+ // The language the app will ask in on its first view: polyglot's stored
80
+ // choice, else the project's `state.lang`, else polyglot's default — the
81
+ // order polyglot's initPolyglot resolves it in. No polyglot: `state.lang`, or
82
+ // none (a declarative fetch then sends no Accept-Language either).
83
+ const languageRule = (project) => {
84
+ const stateLang = project.state && typeof project.state.lang === 'string' ? project.state.lang : ''
85
+ const polyglot = project.polyglot
86
+ if (polyglot && typeof polyglot === 'object') {
87
+ return { storage: polyglot.storageLangKey || POLYGLOT_LANG_KEY, fallback: stateLang || polyglot.defaultLang || 'en' }
88
+ }
89
+ return { storage: '', fallback: stateLang }
90
+ }
91
+
92
+ // `early.query` names configured headers; the script needs their values. A
93
+ // name the adapter does not configure is a mistake worth stopping the build
94
+ // for: those GETs would go out without the key and be refused, every time.
95
+ const queryParams = (mapping, headers) => {
96
+ const params = {}
97
+ for (const name in mapping || {}) {
98
+ const header = Object.keys(headers || {}).find((key) => key.toLowerCase() === name.toLowerCase())
99
+ if (!header) throw new Error(`@symbo.ls/fetch early.query: "${name}" is not one of the adapter's configured headers`)
100
+ params[mapping[name]] = headers[header]
101
+ }
102
+ return params
103
+ }
104
+
105
+ const fetchOptions = (options) => {
106
+ const picked = {}
107
+ for (const key of FETCH_OPTION_KEYS) {
108
+ if (options && options[key] !== undefined) picked[key] = options[key]
109
+ }
110
+ // An early answer must be a fresh one, as the adapter's own request is (an
111
+ // RPC is a POST, which nothing caches): unless the adapter configures a
112
+ // cache mode, the early GET skips the HTTP cache.
113
+ if (picked.cache === undefined) picked.cache = 'no-store'
114
+ return picked
115
+ }
116
+
117
+ /**
118
+ * The pre-boot script for a project, or '' when it declares no early
119
+ * requests (or its adapter is not REST — the script can only build REST
120
+ * addresses).
121
+ *
122
+ * @param {Object} project `{ fetch, polyglot, state }` — config.js and
123
+ * state.js, as source modules or frank JSON (request functions may be
124
+ * strings).
125
+ * @returns {string}
126
+ */
127
+ export const createEarlyScript = (project = {}) => {
128
+ const fetch = project && project.fetch
129
+ // `early.query` / `early.rpc` default to the adapter's `reads` (early.js
130
+ // withReads), exactly as the adapter resolves them.
131
+ const early = fetch && withReads(fetch.early, fetch.reads)
132
+ if (!early || typeof early !== 'object' || fetch.adapter !== 'rest' || !fetch.url) return ''
133
+ const routes = early.routes && typeof early.routes === 'object' ? Object.keys(early.routes) : []
134
+ if (!routes.length && !early.always) return ''
135
+
136
+ const config = {
137
+ url: fetch.url,
138
+ query: queryParams(early.query, fetch.headers),
139
+ rpc: early.rpc === 'get',
140
+ fetchOptions: fetchOptions(fetch.fetchOptions),
141
+ lang: languageRule(project)
142
+ }
143
+ const routeTable = routes
144
+ .map((pattern) => `[${JSON.stringify(pattern)}, ${requestsSource(early.routes[pattern], JSON.stringify(pattern))}]`)
145
+ .join(',\n ')
146
+ const always = early.always ? requestsSource(early.always, '`always`') : '[]'
147
+
148
+ const source = `/* @symbo.ls/fetch — fetch.early: the first view's requests, sent before the app boots */
149
+ ;(function () {
150
+ var g = globalThis
151
+ var K = Symbol.for(${JSON.stringify(EARLY_KEY)})
152
+ if (g[K] || typeof g.fetch !== 'function' || !g.location) return
153
+ var registry = g[K] = { time: Date.now(), entries: {} }
154
+ var config = ${JSON.stringify(config)}
155
+ var buildUrl = ${buildUrl.toString()}
156
+ var selectQuery = ${selectQuery.toString()}
157
+ var earlyKey = ${earlyKey.toString()}
158
+ var isScalarParams = ${isScalarParams.toString()}
159
+ var matchEarlyRoute = ${matchEarlyRoute.toString()}
160
+ var always = ${always}
161
+ var routes = [
162
+ ${routeTable}
163
+ ]
164
+ var storage = function (key) {
165
+ try { return key ? g.localStorage.getItem(key) : null } catch (e) { return null }
166
+ }
167
+ var lang = (config.lang.storage && storage(config.lang.storage)) || config.lang.fallback || ''
168
+ var ctx = { path: g.location.pathname, query: new URLSearchParams(g.location.search), lang: lang, storage: storage }
169
+ var list = function (requests, params) {
170
+ try {
171
+ var out = typeof requests === 'function' ? requests(params, ctx) : requests
172
+ return Array.isArray(out) ? out : []
173
+ } catch (e) {
174
+ return []
175
+ }
176
+ }
177
+ var match = matchEarlyRoute(routes.map(function (route) { return route[0] }), ctx.path)
178
+ var requests = list(always, {}).concat(match ? list(routes[match.index][1], match.params) : [])
179
+ for (var i = 0; i < requests.length; i++) {
180
+ try {
181
+ var request = requests[i]
182
+ if (!request || typeof request !== 'object' || !request.from) continue
183
+ var method = request.method || 'select'
184
+ var url
185
+ if (method === 'select') url = buildUrl(config.url, request.from, selectQuery(request))
186
+ else if (method === 'rpc' && config.rpc && isScalarParams(request.params)) url = buildUrl(config.url, 'rpc/' + request.from, request.params)
187
+ else continue
188
+ var language = request.lang === false ? '' : lang
189
+ var key = earlyKey(url, language)
190
+ if (registry.entries[key]) continue
191
+ var address = new URL(url)
192
+ for (var name in config.query) address.searchParams.set(name, config.query[name])
193
+ var options = Object.assign({}, config.fetchOptions, { method: 'GET' })
194
+ if (language) options.headers = { 'Accept-Language': language }
195
+ registry.entries[key] = { time: Date.now(), answer: g.fetch(address.toString(), options).catch(function () { return null }) }
196
+ } catch (e) {}
197
+ }
198
+ })()
199
+ `
200
+ // Safe to inline too: no literal `</script` can end an inline tag early.
201
+ return source.replace(/<\/script/gi, '<\\/script')
202
+ }
203
+
204
+ export default createEarlyScript