UNPKG

@phyter/tarc

Version:

Next.js Typed Api Routes and Clients

3 lines (2 loc) 9.39 kB
"use strict";var e=require("react"),t=require("recoil");const r=t.atomFamily({key:"routeCache",default:{}}),a=t.selectorFamily({key:"routeLoading",get:e=>({get:t})=>t(r(e)).loading,set:e=>({set:t},a)=>{t(r(e),(e=>({...e,loading:a})))}}),n=t.selectorFamily({key:"routeError",get:e=>({get:t})=>t(r(e)).error,set:e=>({set:t},a)=>{t(r(e),(e=>({...e,error:a})))}}),o=t.selectorFamily({key:"routeData",get:e=>({get:t})=>t(r(e)).data,set:e=>({set:t},a)=>{t(r(e),(e=>({...e,data:a})))}});var s={},i=e=>encodeURIComponent(e).replace(/[!'()*]/g,(e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)),c=new RegExp("%[a-f0-9]{2}","gi"),u=new RegExp("(%[a-f0-9]{2})+","gi");function l(e,t){try{return decodeURIComponent(e.join(""))}catch(e){}if(1===e.length)return e;t=t||1;var r=e.slice(0,t),a=e.slice(t);return Array.prototype.concat.call([],l(r),l(a))}function p(e){try{return decodeURIComponent(e)}catch(a){for(var t=e.match(c),r=1;r<t.length;r++)t=(e=l(t,r).join("")).match(c);return e}}var f=function(e){if("string"!=typeof e)throw new TypeError("Expected `encodedURI` to be of type `string`, got `"+typeof e+"`");try{return e=e.replace(/\+/g," "),decodeURIComponent(e)}catch(t){return function(e){for(var t={"%FE%FF":"��","%FF%FE":"��"},r=u.exec(e);r;){try{t[r[0]]=decodeURIComponent(r[0])}catch(e){var a=p(r[0]);a!==r[0]&&(t[r[0]]=a)}r=u.exec(e)}t["%C2"]="�";for(var n=Object.keys(t),o=0;o<n.length;o++){var s=n[o];e=e.replace(new RegExp(s,"g"),t[s])}return e}(e)}},d=(e,t)=>{if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Expected the arguments to be of type `string`");if(""===t)return[e];const r=e.indexOf(t);return-1===r?[e]:[e.slice(0,r),e.slice(r+t.length)]},y=function(e,t){for(var r={},a=Object.keys(e),n=Array.isArray(t),o=0;o<a.length;o++){var s=a[o],i=e[s];(n?-1!==t.indexOf(s):t(s,i,e))&&(r[s]=i)}return r};!function(e){const t=i,r=f,a=d,n=y,o=Symbol("encodeFragmentIdentifier");function s(e){if("string"!=typeof e||1!==e.length)throw new TypeError("arrayFormatSeparator must be single character string")}function c(e,r){return r.encode?r.strict?t(e):encodeURIComponent(e):e}function u(e,t){return t.decode?r(e):e}function l(e){return Array.isArray(e)?e.sort():"object"==typeof e?l(Object.keys(e)).sort(((e,t)=>Number(e)-Number(t))).map((t=>e[t])):e}function p(e){const t=e.indexOf("#");return-1!==t&&(e=e.slice(0,t)),e}function g(e){const t=(e=p(e)).indexOf("?");return-1===t?"":e.slice(t+1)}function m(e,t){return t.parseNumbers&&!Number.isNaN(Number(e))&&"string"==typeof e&&""!==e.trim()?e=Number(e):!t.parseBooleans||null===e||"true"!==e.toLowerCase()&&"false"!==e.toLowerCase()||(e="true"===e.toLowerCase()),e}function h(e,t){s((t=Object.assign({decode:!0,sort:!0,arrayFormat:"none",arrayFormatSeparator:",",parseNumbers:!1,parseBooleans:!1},t)).arrayFormatSeparator);const r=function(e){let t;switch(e.arrayFormat){case"index":return(e,r,a)=>{t=/\[(\d*)\]$/.exec(e),e=e.replace(/\[\d*\]$/,""),t?(void 0===a[e]&&(a[e]={}),a[e][t[1]]=r):a[e]=r};case"bracket":return(e,r,a)=>{t=/(\[\])$/.exec(e),e=e.replace(/\[\]$/,""),t?void 0!==a[e]?a[e]=[].concat(a[e],r):a[e]=[r]:a[e]=r};case"colon-list-separator":return(e,r,a)=>{t=/(:list)$/.exec(e),e=e.replace(/:list$/,""),t?void 0!==a[e]?a[e]=[].concat(a[e],r):a[e]=[r]:a[e]=r};case"comma":case"separator":return(t,r,a)=>{const n="string"==typeof r&&r.includes(e.arrayFormatSeparator),o="string"==typeof r&&!n&&u(r,e).includes(e.arrayFormatSeparator);r=o?u(r,e):r;const s=n||o?r.split(e.arrayFormatSeparator).map((t=>u(t,e))):null===r?r:u(r,e);a[t]=s};case"bracket-separator":return(t,r,a)=>{const n=/(\[\])$/.test(t);if(t=t.replace(/\[\]$/,""),!n)return void(a[t]=r?u(r,e):r);const o=null===r?[]:r.split(e.arrayFormatSeparator).map((t=>u(t,e)));void 0!==a[t]?a[t]=[].concat(a[t],o):a[t]=o};default:return(e,t,r)=>{void 0!==r[e]?r[e]=[].concat(r[e],t):r[e]=t}}}(t),n=Object.create(null);if("string"!=typeof e)return n;if(!(e=e.trim().replace(/^[?#&]/,"")))return n;for(const o of e.split("&")){if(""===o)continue;let[e,s]=a(t.decode?o.replace(/\+/g," "):o,"=");s=void 0===s?null:["comma","separator","bracket-separator"].includes(t.arrayFormat)?s:u(s,t),r(u(e,t),s,n)}for(const e of Object.keys(n)){const r=n[e];if("object"==typeof r&&null!==r)for(const e of Object.keys(r))r[e]=m(r[e],t);else n[e]=m(r,t)}return!1===t.sort?n:(!0===t.sort?Object.keys(n).sort():Object.keys(n).sort(t.sort)).reduce(((e,t)=>{const r=n[t];return Boolean(r)&&"object"==typeof r&&!Array.isArray(r)?e[t]=l(r):e[t]=r,e}),Object.create(null))}e.extract=g,e.parse=h,e.stringify=(e,t)=>{if(!e)return"";s((t=Object.assign({encode:!0,strict:!0,arrayFormat:"none",arrayFormatSeparator:","},t)).arrayFormatSeparator);const r=r=>t.skipNull&&null==e[r]||t.skipEmptyString&&""===e[r],a=function(e){switch(e.arrayFormat){case"index":return t=>(r,a)=>{const n=r.length;return void 0===a||e.skipNull&&null===a||e.skipEmptyString&&""===a?r:null===a?[...r,[c(t,e),"[",n,"]"].join("")]:[...r,[c(t,e),"[",c(n,e),"]=",c(a,e)].join("")]};case"bracket":return t=>(r,a)=>void 0===a||e.skipNull&&null===a||e.skipEmptyString&&""===a?r:null===a?[...r,[c(t,e),"[]"].join("")]:[...r,[c(t,e),"[]=",c(a,e)].join("")];case"colon-list-separator":return t=>(r,a)=>void 0===a||e.skipNull&&null===a||e.skipEmptyString&&""===a?r:null===a?[...r,[c(t,e),":list="].join("")]:[...r,[c(t,e),":list=",c(a,e)].join("")];case"comma":case"separator":case"bracket-separator":{const t="bracket-separator"===e.arrayFormat?"[]=":"=";return r=>(a,n)=>void 0===n||e.skipNull&&null===n||e.skipEmptyString&&""===n?a:(n=null===n?"":n,0===a.length?[[c(r,e),t,c(n,e)].join("")]:[[a,c(n,e)].join(e.arrayFormatSeparator)])}default:return t=>(r,a)=>void 0===a||e.skipNull&&null===a||e.skipEmptyString&&""===a?r:null===a?[...r,c(t,e)]:[...r,[c(t,e),"=",c(a,e)].join("")]}}(t),n={};for(const t of Object.keys(e))r(t)||(n[t]=e[t]);const o=Object.keys(n);return!1!==t.sort&&o.sort(t.sort),o.map((r=>{const n=e[r];return void 0===n?"":null===n?c(r,t):Array.isArray(n)?0===n.length&&"bracket-separator"===t.arrayFormat?c(r,t)+"[]":n.reduce(a(r),[]).join("&"):c(r,t)+"="+c(n,t)})).filter((e=>e.length>0)).join("&")},e.parseUrl=(e,t)=>{t=Object.assign({decode:!0},t);const[r,n]=a(e,"#");return Object.assign({url:r.split("?")[0]||"",query:h(g(e),t)},t&&t.parseFragmentIdentifier&&n?{fragmentIdentifier:u(n,t)}:{})},e.stringifyUrl=(t,r)=>{r=Object.assign({encode:!0,strict:!0,[o]:!0},r);const a=p(t.url).split("?")[0]||"",n=e.extract(t.url),s=e.parse(n,{sort:!1}),i=Object.assign(s,t.query);let u=e.stringify(i,r);u&&(u=`?${u}`);let l=function(e){let t="";const r=e.indexOf("#");return-1!==r&&(t=e.slice(r)),t}(t.url);return t.fragmentIdentifier&&(l=`#${r[o]?c(t.fragmentIdentifier,r):t.fragmentIdentifier}`),`${a}${u}${l}`},e.pick=(t,r,a)=>{a=Object.assign({parseFragmentIdentifier:!0,[o]:!1},a);const{url:s,query:i,fragmentIdentifier:c}=e.parseUrl(t,a);return e.stringifyUrl({url:s,query:n(i,r),fragmentIdentifier:c},a)},e.exclude=(t,r,a)=>{const n=Array.isArray(r)?e=>!r.includes(e):(e,t)=>!r(e,t);return e.pick(t,n,a)}}(s);const g=new Map([["get",({apiUrl:e,path:t,inputShape:r,outputShape:a})=>async n=>{const o=r.safeParse(n),i=await fetch(e+t+"?"+s.stringify(o,{encode:!0}),{method:"GET",headers:{"Content-Type":"application/json"}});return a.safeParse(await i.json())}],["post",({apiUrl:e,path:t,inputShape:r,outputShape:a})=>async n=>{const o=r.safeParse(n),s=await fetch(e+t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)}),i=await s.json();return a.safeParse(i)}]]),m=new Map([["get",({inputShape:e,outputShape:t,context:r,handler:a})=>async(n,o)=>{const s=e.safeParse(n.query),i=await a({req:n,res:o,context:r,input:s});o.status(200).json(t.safeParse(i))}],["post",({inputShape:e,outputShape:t,context:r,handler:a})=>async(n,o)=>{const s=e.safeParse(n.body),i=await a({req:n,res:o,context:r,input:s});o.status(200).json(t.safeParse(i))}]]);exports.Router=({contextShape:e,apiUrl:t="/api"})=>{let r;return{route:({method:a,path:n,inputShape:o,outputShape:s})=>{let i=[];const c=m.get(a)??m.get("post");return{apiUrl:t,path:n,routeMiddleware:i,inputShape:o,outputShape:s,contextShape:e,handler:e=>async(t,a)=>{for(const e of i||[])await e(t,a);if(await(()=>{if(!r)throw new Error("createContext not set");return r})()(t,a))return c({inputShape:o,outputShape:s,context:await r(t,a),handler:e})(t,a);a.status(500).json({status:"error",message:"no context"})},client:()=>(g.get(a)??g.get("post"))({apiUrl:t,path:n,inputShape:o,outputShape:s}),middleware:(...e)=>{i=[...i,...e]}}},context:e=>{r=e},methodHandlers:e=>{for(const[t,r]of e)m.set(t,r)},methodClients:e=>{for(const[t,r]of e)g.set(t,r)}}},exports.RouterContextProvider=({children:r,clients:a,router:n})=>{const o=e.useRef(!1);return e.useEffect((()=>{!o.current&&a&&n&&(o.current=!0,n.methodClients(a))}),[n,a]),e.createElement(t.RecoilRoot,null,r)},exports.useCachedRoute=r=>{const s=r.apiUrl+r.path,i=r.client(),[c,u]=t.useRecoilState(o(s)),[l,p]=t.useRecoilState(n(s)),[f,d]=t.useRecoilState(a(s));return[e.useCallback((async e=>{let t;d(!0);try{t=await i(e),u(t)}catch(e){p(e)}finally{return d(!1),t}}),[r]),{data:c,error:l,loading:f}]},exports.useRoute=t=>{const[r,a]=e.useState(),[n,o]=e.useState(),[s,i]=e.useState(!1);return[e.useCallback((async e=>{let r;i(!0);try{r=await t(e),a(r)}catch(e){o(e)}finally{return i(!1),r}}),[t]),{data:r,error:n,loading:s}]}; //# sourceMappingURL=index.js.map