fch 5.0.0 → 5.1.0

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/index.min.js CHANGED
@@ -1,2 +1,2 @@
1
- var d=async e=>(e=await e,Array.isArray(e)?await Promise.all(e.map(d)):e),y=(e,n)=>(...a)=>(r=>r instanceof RegExp?r.test.bind(r):r)(e).call(n,...a),k=(e,n)=>async(a,r,t)=>({value:a,extra:await y(e,n)(a,r,t)}),D=({extra:e})=>e,M=({value:e})=>e,T={every:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(!await y(n,a)(e[r],r,e))return!1;return!0},filter:async(e,n,a)=>(await d(e.map(k(n,a)))).filter(D).map(M),find:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return e[r]},findIndex:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return r;return-1},forEach:async(e,n,a)=>(await d(e.map(k(n,a))),e),reduce:async(e,n,a)=>{let r=a!==void 0;r||(a=e[0]);for(let t=r?0:1;t<e.length;t++)a=await y(n)(a,e[t],t,e);return a},reduceRight:async(e,n,a)=>{let r=a!==void 0;r||(a=e[e.length-1]);for(let t=e.length-(r?1:2);t>=0;t--)a=await y(n)(a,e[t],t,e);return a},some:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return!0;return!1}},v=(e,n)=>(a,r)=>r==="then"?(...t)=>d(e).then(...t):r==="catch"?(...t)=>p(d(e).catch(...t)):h(d(e).then(t=>typeof r=="symbol"?t[r]:r in n?h((...o)=>n[r](t,...o),n):typeof t=="number"&&r in n.number?h((...o)=>n.number[r](t,...o),n):typeof t=="string"&&r in n.string?h((...o)=>n.string[r](t,...o),n):Array.isArray(t)&&r in n.array?h((...o)=>n.array[r](t,...o),n):t[r]&&t[r].bind?h(t[r].bind(t),n):h(t[r],n)),n),F=(e,n)=>(a,r,t)=>h(d(e).then(o=>{return typeof o!="function"?(c=`You tried to call "${JSON.stringify(o)}" (${typeof o}) as a function, but it is not.`,Promise.reject(new Error(c))):o(...t);var c}),n),h=(e,n)=>new Proxy(()=>{},{get:v(e,n),apply:F(e,n)});function p(e,{number:n,string:a,array:r,...t}={}){return typeof e=="function"?(...o)=>p(Promise.all(o).then(c=>e(...c)),{number:n,string:a,array:r,...t}):new Proxy({},{get:v(e,{number:{...n},string:{...a},array:{...T,...r},...t})})}function w(e){e.expire||(e.expire=0);let n=new Map,a=async r=>{if(!n.has(r))return!1;let{time:t,expire:o}=n.get(r);return!(!o||new Date().getTime()-t>o*1e3)};return{get:async r=>{if(!await a(r))return null;let{data:o}=n.get(r);return o},set:async(r,t,o={})=>{let c=new Date().getTime(),f=o.EX||o.expire||e.expire;return n.set(r,{time:c,expire:f,data:t})},keys:async()=>[...await n.keys()],del:async r=>n.delete(r),exists:a,flushAll:()=>n.clear()}}var O=/(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/giu;s.nanosecond=s.ns=1/1e6;s.\u00B5s=s.\u03BCs=s.us=s.microsecond=1/1e3;s.millisecond=s.ms=1;s.second=s.sec=s.s=s[""]=s.ms*1e3;s.minute=s.min=s.m=s.s*60;s.hour=s.hr=s.h=s.m*60;s.day=s.d=s.h*24;s.week=s.wk=s.w=s.d*7;s.month=s.b=s.d*(365.25/12);s.year=s.yr=s.y=s.d*365.25;function C(e){return s[e]||s[e.toLowerCase().replace(/s$/,"")]}function s(e="",n="ms"){if(!e)return 0;if(typeof e=="boolean")return e?60*60:0;if(typeof e=="number")return e;var a=null;e=(e+"").replace(/(\d)[,_](\d)/g,"$1$2");var r=e[0]==="-";return e.replace(O,function(t,o,c){c=C(c),c&&(a=(a||0)+Math.abs(parseFloat(o,10))*c)}),Math.max(1,Math.round((a&&a/(C(n)||1)*(r?-1:1))/1e3))}var $=e=>!e||e instanceof FormData||typeof(e.pipe||e.pipeTo)=="function"?!1:typeof e=="object"||Array.isArray(e),g=e=>{if(typeof e!="object")return e;for(let n in e)e[n]===void 0&&delete e[n];return e},b=class extends Error{constructor(n){let a="Error "+n.status;super(a),this.response=n,this.message=a}},j=(e,n,a)=>{let[r,t={}]=e.split("?"),o=new URLSearchParams(Object.fromEntries([...new URLSearchParams(g(n)),...new URLSearchParams(g(t))])).toString();return o&&(r=r+"?"+o),a?new URL(r.replace(/^\//,""),a).href:r},B=e=>{let n={};for(let[a,r]of Object.entries(e))n[a.toLowerCase()]=r;return n},R=async e=>{let n=e.headers.get("content-type"),a=n&&n.includes("application/json"),r=await e.clone().text();return a?JSON.parse(r):r},S=async(e,n)=>{let a={status:e.status,statusText:e.statusText,headers:{}};for(let r of e.headers.keys())a.headers[r.toLowerCase()]=e.headers.get(r);if(!e.ok)throw new b(e);return a.body=await R(e),a},L=(e,{ref:n,after:a,error:r,output:t})=>fetch(e.url,e).then(async o=>{if(n.res=o,o.ok&&t==="stream")return o.body;if(o.ok&&o[t]&&typeof o[t]=="function")return o[t]();let c=a(await S(o,r));if(t==="body")return c.body;if(t==="response")return c;if(t==="raw")return o.clone();throw new Error(`Invalid option output="${t}"`)}),J=e=>e.method==="get",N=e=>e.method+":"+e.url,q=(e={},n)=>{let a={store:w({expire:s(e.expire)}),shouldCache:J,createKey:N,...e};return a.clear=()=>a.store?.flushAll(),n&&(a.shouldCache=()=>!1),a};function x(e={}){let n={},a={},t=p(async(o="/",c={})=>{let{output:f,before:A,after:E,error:U,...i}={...t,...c},l={...t.cache},P=u=>["number","string","boolean"].includes(typeof u);if(l.expire=s([c.cache?.expire,c.cache,l?.expire,l].find(P)),i.url=j(o,{...t.query,...c.query},i.baseUrl??i.baseURL),i.method=i.method.toLowerCase()||"GET",i.headers=B({...t.headers,...c.headers}),i.body instanceof SubmitEvent&&(i.body=new FormData(i.body.target)),i.body instanceof HTMLFormElement&&(i.body=new FormData(i.body)),$(i.body)&&(i.body=JSON.stringify(g(i.body)),i.headers["content-type"]="application/json"),i=A(i),l.shouldCache(i)&&l.expire){let u=l.createKey(i);if(await l.store.exists(u))return l.store.get(u);if(n[u])return n[u];let m;try{n[u]=L(i,{ref:a,cache:l,output:f,error:U,after:E}),m=await n[u]}finally{delete n[u]}return await l.store.set(u,m,{EX:l.expire}),m}return L(i,{ref:a,output:f,error:U,after:E})},{text:()=>a.res.text(),json:()=>a.res.json(),blob:()=>a.res.blob(),stream:()=>a.res.body,arrayBuffer:()=>a.res.arrayBuffer(),formData:()=>a.res.formData(),body:()=>R(a.res),clone:()=>a.res.clone(),raw:()=>a.res.clone(),response:()=>S(a.res.clone())});return t.url=e.url??"/",t.method=e.method??"get",t.query=e.query??{},t.headers=e.headers??{},t.baseUrl=e.baseUrl??e.baseURL??null,["number","string","boolean"].includes(typeof e.cache)&&(e.cache={expire:e.cache}),t.cache=q(e.cache,e.cache?.expire===!1||e.cache?.expire===0),t.output=e.output??"body",t.credentials=e.credentials??"include",t.before=e.before??(o=>o),t.after=e.after??(o=>o),t.error=e.error??(o=>{throw o}),t.get=(o,c)=>t(o,{method:"get",...c}),t.head=(o,c)=>t(o,{method:"head",...c}),t.post=(o,c,f)=>t(o,{method:"post",body:c,...f}),t.patch=(o,c,f)=>t(o,{method:"patch",body:c,...f}),t.put=(o,c,f)=>t(o,{method:"put",body:c,...f}),t.delete=(o,c)=>t(o,{method:"delete",...c}),t.del=t.delete,t.create=x,t}typeof window<"u"&&(window.fch=x());var _=x();export{x as create,_ as default};
1
+ var d=async e=>(e=await e,Array.isArray(e)?await Promise.all(e.map(d)):e),y=(e,n)=>(...a)=>(r=>r instanceof RegExp?r.test.bind(r):r)(e).call(n,...a),k=(e,n)=>async(a,r,t)=>({value:a,extra:await y(e,n)(a,r,t)}),D=({extra:e})=>e,T=({value:e})=>e,j={every:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(!await y(n,a)(e[r],r,e))return!1;return!0},filter:async(e,n,a)=>(await d(e.map(k(n,a)))).filter(D).map(T),find:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return e[r]},findIndex:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return r;return-1},forEach:async(e,n,a)=>(await d(e.map(k(n,a))),e),reduce:async(e,n,a)=>{let r=a!==void 0;r||(a=e[0]);for(let t=r?0:1;t<e.length;t++)a=await y(n)(a,e[t],t,e);return a},reduceRight:async(e,n,a)=>{let r=a!==void 0;r||(a=e[e.length-1]);for(let t=e.length-(r?1:2);t>=0;t--)a=await y(n)(a,e[t],t,e);return a},some:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return!0;return!1}},C=(e,n)=>(a,r)=>r==="then"?(...t)=>d(e).then(...t):r==="catch"?(...t)=>p(d(e).catch(...t)):h(d(e).then(t=>typeof r=="symbol"?t[r]:r in n?h((...o)=>n[r](t,...o),n):typeof t=="number"&&r in n.number?h((...o)=>n.number[r](t,...o),n):typeof t=="string"&&r in n.string?h((...o)=>n.string[r](t,...o),n):Array.isArray(t)&&r in n.array?h((...o)=>n.array[r](t,...o),n):t[r]&&t[r].bind?h(t[r].bind(t),n):h(t[r],n)),n),F=(e,n)=>(a,r,t)=>h(d(e).then(o=>{return typeof o!="function"?(c=`You tried to call "${JSON.stringify(o)}" (${typeof o}) as a function, but it is not.`,Promise.reject(new Error(c))):o(...t);var c}),n),h=(e,n)=>new Proxy(()=>{},{get:C(e,n),apply:F(e,n)});function p(e,{number:n,string:a,array:r,...t}={}){return typeof e=="function"?(...o)=>p(Promise.all(o).then(c=>e(...c)),{number:n,string:a,array:r,...t}):new Proxy({},{get:C(e,{number:{...n},string:{...a},array:{...j,...r},...t})})}function w(e){e.expire||(e.expire=0);let n=new Map,a=async r=>{if(!n.has(r))return!1;let{time:t,expire:o}=n.get(r);return!(!o||new Date().getTime()-t>o*1e3)};return{get:async r=>{if(!await a(r))return null;let{data:o}=n.get(r);return o},set:async(r,t,o={})=>{let c=new Date().getTime(),f=o.EX||o.expire||e.expire;return n.set(r,{time:c,expire:f,data:t})},keys:async()=>[...await n.keys()],del:async r=>n.delete(r),exists:a,flushAll:()=>n.clear()}}var M=/(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/iu;s.millisecond=s.ms=1;s.second=s.sec=s.s=s[""]=s.ms*1e3;s.minute=s.min=s.m=s.s*60;s.hour=s.hr=s.h=s.m*60;s.day=s.d=s.h*24;s.week=s.wk=s.w=s.d*7;s.year=s.yr=s.y=s.d*365.25;s.month=s.b=s.y/12;function s(e=""){if(!e)return 0;if(e===!0)return 60*60*1e3;if(typeof e=="number")return e;e=e.toLowerCase().replace(/[,_]/g,"");let[n,a,r]=M.exec(e)||[];r=s[r]||s[r.replace(/s$/,"")]||1e3;let t=r*parseFloat(a,10);return Math.abs(Math.round(t))}var O=e=>!e||e instanceof FormData||typeof(e.pipe||e.pipeTo)=="function"?!1:typeof e=="object"||Array.isArray(e),b=e=>{if(typeof e!="object")return e;for(let n in e)e[n]===void 0&&delete e[n];return e},g=class extends Error{constructor(n){let a="Error "+n.status;super(a),this.response=n,this.message=a}},B=(e,n,a)=>{let[r,t={}]=e.split("?"),o=new URLSearchParams(Object.fromEntries([...new URLSearchParams(b(n)),...new URLSearchParams(b(t))])).toString();return o&&(r=r+"?"+o),a?new URL(r.replace(/^\//,""),a).href:r},J=e=>{let n={};for(let[a,r]of Object.entries(e))n[a.toLowerCase()]=r;return n},v=async e=>{let n=e.headers.get("content-type"),a=n&&n.includes("application/json"),r=await e.clone().text();return a?JSON.parse(r):r},P=async e=>{let n={status:e.status,statusText:e.statusText,headers:{}};for(let a of e.headers.keys())n.headers[a.toLowerCase()]=e.headers.get(a);if(!e.ok)throw new g(e);return n.body=await v(e),n},L=(e,{ref:n,after:a,error:r,output:t})=>fetch(e.url,e).then(async o=>{if(n.res=o,o.ok&&t==="stream")return o.body;if(o.ok&&o[t]&&typeof o[t]=="function")return o[t]();let c=a(await P(o));if(t==="body")return c.body;if(t==="response")return c;if(t==="raw")return o.clone();throw new Error(`Invalid option output="${t}"`)}).catch(r),$=e=>e.method==="get",q=e=>e.method+":"+e.url,K=({store:e,...n}={},a)=>{let r={store:e?p(e):w({expire:s(n.expire)}),shouldCache:$,createKey:q,...n};return r.clear=()=>Promise.resolve(r.store).then(t=>t?.flushAll()),a&&(r.shouldCache=()=>!1),r};function x(e={}){let n={},a={},t=p(async(o="/",c={})=>{let{output:f,before:S,after:E,error:U,...i}={...t,...c},l={...t.cache},A=u=>["number","string","boolean"].includes(typeof u);if(l.expire=s([c.cache?.expire,c.cache,l?.expire,l].find(A)),i.url=B(o,{...t.query,...c.query},i.baseUrl??i.baseURL),i.method=i.method.toLowerCase()||"GET",i.headers=J({...t.headers,...c.headers}),i.body instanceof SubmitEvent&&(i.body=new FormData(i.body.target)),i.body instanceof HTMLFormElement&&(i.body=new FormData(i.body)),O(i.body)&&(i.body=JSON.stringify(b(i.body)),i.headers["content-type"]="application/json"),i=S(i),l.shouldCache(i)&&l.expire){let u=l.createKey(i);if(l.store?.then){let R=await l.store;l.store=R}if(await l.store.exists(u))return l.store.get(u);if(n[u])return n[u];let m;try{n[u]=L(i,{ref:a,cache:l,output:f,error:U,after:E}),m=await n[u]}finally{delete n[u]}return await l.store.set(u,m,{EX:l.expire}),m}return L(i,{ref:a,output:f,error:U,after:E})},{text:()=>a.res.text(),json:()=>a.res.json(),blob:()=>a.res.blob(),stream:()=>a.res.body,arrayBuffer:()=>a.res.arrayBuffer(),formData:()=>a.res.formData(),body:()=>v(a.res),clone:()=>a.res.clone(),raw:()=>a.res.clone(),response:()=>P(a.res.clone())});return t.url=e.url??"/",t.method=e.method??"get",t.query=e.query??{},t.headers=e.headers??{},t.baseUrl=e.baseUrl??e.baseURL??null,["number","string","boolean"].includes(typeof e.cache)&&(e.cache={expire:e.cache}),t.cache=K(e.cache,e.cache?.expire===!1||e.cache?.expire===0),t.output=e.output??"body",t.credentials=e.credentials??"include",t.before=e.before??(o=>o),t.after=e.after??(o=>o),t.error=e.error??(o=>Promise.reject(o)),t.get=(o,c)=>t(o,{method:"get",...c}),t.head=(o,c)=>t(o,{method:"head",...c}),t.post=(o,c,f)=>t(o,{method:"post",body:c,...f}),t.patch=(o,c,f)=>t(o,{method:"patch",body:c,...f}),t.put=(o,c,f)=>t(o,{method:"put",body:c,...f}),t.delete=(o,c)=>t(o,{method:"delete",...c}),t.del=t.delete,t.create=x,t}typeof window<"u"&&(window.fch=x());var _=x();export{x as create,_ as default,s as parse};
2
2
  //# sourceMappingURL=index.min.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fch",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Fetch interface with better promises, deduplication, defaults, etc.",
5
5
  "homepage": "https://github.com/franciscop/fetch",
6
6
  "repository": "https://github.com/franciscop/fetch.git",
@@ -33,11 +33,12 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "check-dts": "^0.7.2",
36
+ "dotenv": "^16.3.1",
36
37
  "esbuild": "^0.19.2",
37
38
  "jest": "^28.1.0",
38
39
  "jest-environment-jsdom": "^28.1.0",
39
40
  "jest-fetch-mock": "^3.0.3",
40
- "redis": "^4.6.7",
41
+ "redis": "^4.6.10",
41
42
  "swear": "^1.1.2"
42
43
  },
43
44
  "jest": {
package/readme.md CHANGED
@@ -354,9 +354,9 @@ Your cache will have a `store`; by default we create an in-memory store, but you
354
354
  import fch from "fch";
355
355
  import { createClient } from "redis";
356
356
 
357
- // Create a redis client
358
- const store = createClient();
359
- await store.connect();
357
+ // You can either pass the store instance, or a promise that will
358
+ // return the instance. In this case we are doing the latter
359
+ const store = createClient().connect();
360
360
 
361
361
  const api = fch.create({
362
362
  cache: {
@@ -384,14 +384,11 @@ import { createClient } from "redis";
384
384
  // Initialize it straight away
385
385
  const api = fch.create({
386
386
  cache: {
387
- store: createClient(),
387
+ store: createClient().connect(),
388
388
  expire: "1h",
389
389
  },
390
390
  });
391
391
 
392
- // Connect it here now
393
- await api.cache.store.connect();
394
-
395
392
  // Later on, maybe in a different place
396
393
  await api.cache.store.flushDB();
397
394
  ```
@@ -439,6 +436,8 @@ const api = fch.create({
439
436
  });
440
437
  ```
441
438
 
439
+ It is this flexible since you can use fch both in the front-end and back-end, so usually in each of them you might want to follow a slightly different strategy.
440
+
442
441
  #### Creating a store.
443
442
 
444
443
  You might want to create a custom store. Please have a look at `src/store.js`, but basically you need an object that implements these methods: