fch 4.0.0 → 4.1.1

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.
Files changed (3) hide show
  1. package/package.json +25 -12
  2. package/readme.md +38 -11
  3. package/fetch.min.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fch",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
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",
@@ -9,11 +9,10 @@
9
9
  "author": "Francisco Presencia <public@francisco.io> (https://francisco.io/)",
10
10
  "license": "MIT",
11
11
  "scripts": {
12
- "build": "terser --compress --mangle --toplevel -o ./fetch.min.js -- ./fetch.js",
13
- "size": "echo $(gzip -c fetch.min.js | wc -c) bytes",
14
- "start": "npm run watch # Start ~= Start dev",
15
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --detectOpenHandles",
16
- "watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch --coverage --detectOpenHandles"
12
+ "build": "rollup -c",
13
+ "size": "echo $(gzip -c index.min.js | wc -c) bytes",
14
+ "start": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch --coverage --detectOpenHandles",
15
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --detectOpenHandles"
17
16
  },
18
17
  "keywords": [
19
18
  "fetch",
@@ -23,21 +22,35 @@
23
22
  "async",
24
23
  "ajax"
25
24
  ],
26
- "main": "./fetch.min.js",
27
- "files": [
28
- "fetch.min.js"
29
- ],
25
+ "main": "./index.min.js",
26
+ "files": [],
30
27
  "type": "module",
31
28
  "engines": {
32
29
  "node": ">=18.0.0"
33
30
  },
34
31
  "devDependencies": {
35
- "jest": "^28.0.1",
32
+ "@babel/core": "^7.15.0",
33
+ "@babel/preset-env": "^7.15.0",
34
+ "@babel/preset-react": "^7.14.5",
35
+ "babel-loader": "^8.2.2",
36
+ "babel-polyfill": "^6.26.0",
37
+ "jest": "^28.1.0",
38
+ "jest-environment-jsdom": "^28.1.0",
36
39
  "jest-fetch-mock": "^3.0.3",
37
- "terser": "^5.13.1"
40
+ "rollup": "^1.32.1",
41
+ "rollup-plugin-babel": "^4.4.0",
42
+ "rollup-plugin-node-resolve": "^5.2.0",
43
+ "rollup-plugin-terser": "^5.2.0",
44
+ "swear": "^1.1.2"
38
45
  },
39
46
  "jest": {
40
47
  "testEnvironment": "jest-environment-node",
41
48
  "transform": {}
49
+ },
50
+ "babel": {
51
+ "presets": [
52
+ "@babel/preset-env",
53
+ "@babel/preset-react"
54
+ ]
42
55
  }
43
56
  }
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- # Fch [![npm install fch](https://img.shields.io/badge/npm%20install-fch-blue.svg)](https://www.npmjs.com/package/fch) [![gzip size](https://img.badgesize.io/franciscop/fetch/master/fetch.min.js.svg?compression=gzip)](https://github.com/franciscop/fetch/blob/master/fetch.min.js)
1
+ # Fch [![npm install fch](https://img.shields.io/badge/npm%20install-fch-blue.svg)](https://www.npmjs.com/package/fch) [![test badge](https://github.com/franciscop/fetch/workflows/tests/badge.svg "test badge")](https://github.com/franciscop/fetch/blob/master/.github/workflows/tests.yml) [![gzip size](https://img.badgesize.io/franciscop/fetch/master/index.min.js.svg?compression=gzip)](https://github.com/franciscop/fetch/blob/master/index.min.js)
2
2
 
3
3
  A tiny library to make API calls easier. Similar to Axios, but tiny size and simpler API:
4
4
 
@@ -32,6 +32,7 @@ api.head(url, { headers, ...options });
32
32
  api.post(url, { body, headers, ...options });
33
33
  api.patch(url, { body, headers, ...options });
34
34
  api.put(url, { body, headers, ...options });
35
+ api.del(url, { body, headers, ...options });
35
36
  api.delete(url, { body, headers, ...options });
36
37
 
37
38
  api.create({ url, body, headers, ...options });
@@ -256,6 +257,21 @@ When to use each?
256
257
 
257
258
  ### Output
258
259
 
260
+ The default output manipulation is to expect either plain `TEXT` as `plain/text` or `JSON` as `application/json` from the `Content-Type`. If your API works with these (the vast majority of APIs do) then you should be fine out of the box!
261
+
262
+ ```js
263
+ const cats = await api.get("/cats");
264
+ console.log(cats); // [{ id: 1, name: 'Whiskers', ... }, ...]
265
+ ```
266
+
267
+ For more expressive control, you can use the **`output` option** (either as a default when [creating an instance](#create-an-instance) or with each call), or using a method:
268
+
269
+ ```js
270
+ const api = fch.create({ output: "json" }); // JSON by default
271
+ const streamImg = await api.get("/cats/123/image", { output: "stream" }); // Stream the image
272
+ const streamImg2 = await api.get("/cats/123/image").stream(); // Shortcut for the one above
273
+ ```
274
+
259
275
  This controls whether the call returns just the body (default), or the whole response. It can be controlled globally or on a per-request basis:
260
276
 
261
277
  ```js
@@ -276,16 +292,27 @@ const blob = await api.get("/data", { output: "blob" });
276
292
  There are few options that can be specified:
277
293
 
278
294
  - `output: "body"` (default): returns the body, parsed as JSON or plain TEXT depending on the headers.
279
- - `output: "response"`: return the full response with the properties `body`, `headers`, `status`, etc. The body will be parsed as JSON or plain TEXT depending on the headers. If you want the raw `response`, use `raw` or `clone` instead (see below in "raw" or "METHODS").
295
+ - `output: "response"`: return the full response with the properties `body`, `headers`, `status`. The body will be parsed as JSON or plain TEXT depending on the headers. If you want the raw `response`, use `raw` or `clone` instead (see below in "raw" or "clone").
280
296
  - `output: "stream"`: return a [web ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) of the body as the result of the promise.
281
- - Any of [the valid methods](https://developer.mozilla.org/en-US/docs/Web/API/Response#methods):
282
- - `output: "arrayBuffer"`: returns an arrayBuffer of the response body.
283
- - `output: "blob"`: returns an arrayBuffer of the response body.
284
- - `output: "clone"`: returns the raw Response, with the raw body. See also `raw` below.
285
- - `output: formData`: returns an instance of FormData with all the parsed data.
286
- - `output: json`: attempts to parse the response as JSON.
287
- - `output: text`: puts the response body as plain text.
288
- - `output: "raw"`: an alias for `clone`, returning the raw response (after passing through `after`).
297
+ - `output: "arrayBuffer"`\*: returns an arrayBuffer of the response body.
298
+ - `output: "blob"`\*: returns an arrayBuffer of the response body.
299
+ - `output: "clone"`\*: returns the raw Response, with the raw body. See also `raw` below.
300
+ - `output: "formData"`\* (might be unavailable): returns an instance of FormData with all the parsed data.
301
+ - `output: "json"`\*: attempts to parse the response as JSON.
302
+ - `output: "text"`\*: puts the response body as plain text.
303
+ - `output: "raw"`\*: an alias for `clone`, returning the raw response (after passing through `after`).
304
+
305
+ \* Standard [MDN methods](https://developer.mozilla.org/en-US/docs/Web/API/Response#methods)
306
+
307
+ The `output` values can all be used as a method as well. So all of these are equivalent:
308
+
309
+ ```js
310
+ const text = await api.get("/cats", { output: "text" });
311
+ const text = await api.get("/cats").text();
312
+
313
+ const raw = await api.get("/cats", { output: "raw" });
314
+ const raw = await api.get("/cats").raw();
315
+ ```
289
316
 
290
317
  For example, return the raw body as a `ReadableStream` with the option `stream`:
291
318
 
@@ -341,7 +368,7 @@ it("can opt out locally", async () => {
341
368
  You can also easily add the interceptors `before`, `after` and `error`:
342
369
 
343
370
  - `before`: Called when the request is fully formed, but before actually launching it.
344
- - `before`: Called just after the response is created and if there was no error, but before parsing anything else.
371
+ - `after`: Called just after the response is created and if there was no error, but before parsing anything else.
345
372
  - `error`: When the response is not okay, if possible it'll include the `response` object.
346
373
 
347
374
  > Note: interceptors are never deduped/cached and always execute once per call, even if the main async fetch() has been deduped.
package/fetch.min.js DELETED
@@ -1 +0,0 @@
1
- const e=(e,{after:t,cache:r,error:o,output:a})=>fetch(e.url,e).then((async e=>{r&&r.clear();let s={status:e.status,statusText:e.statusText,headers:{}};for(let t of e.headers.keys())s.headers[t.toLowerCase()]=e.headers.get(t);if(!e.ok){const t=new Error(e.statusText);return t.response=s,o(t)}if(s=t(s),"stream"===a)return e.body;if(e[a]&&"function"==typeof e[a])return e[a]();const n=e.headers.get("content-type"),u=n&&n.includes("application/json");if(s.body=s.body||await(u?e.json():e.text()),"body"===a)return s.body;if("response"===a)return s;throw new Error(`Invalid option output="${a}"`)})),t=(r={})=>{const o=(()=>{const e=new Map;return t=>({save:r=>(e.set(t,r),r),get:()=>e.get(t),clear:()=>e.delete(t)})})(),a=async(t="/",r={})=>{"object"!=typeof r&&(r={}),r="string"==typeof t?{url:t,...r}:t;let{dedupe:s,output:n,before:u,after:d,error:c,...f}={...a,...r};f.url=((e,t,r)=>{let[o,a={}]=e.split("?");const s=new URLSearchParams({...Object.fromEntries(new URLSearchParams(t)),...Object.fromEntries(new URLSearchParams(a))}).toString();return s&&(o=o+"?"+s),r?new URL(o,r).href:o})(f.url,{...a.query,...r.query},f.baseUrl??f.baseURL),f.method=f.method.toLowerCase(),f.headers=(e=>{const t={};for(let[r,o]of Object.entries(e))t[r.toLowerCase()]=o;return t})({...a.headers,...r.headers});const p=!(!s||"get"!==f.method)&&o(f.url);var i;return"object"!=typeof(i=f.body)||i instanceof FormData||i.pipe||(f.body=JSON.stringify(f.body),f.headers["content-type"]="application/json"),f=u(f),p&&!f.signal?p.get()?p.get():p.save(e(f,{cache:p,output:n,error:c,after:d})):e(f,{output:n,error:c,after:d})};return a.url=r.url??"/",a.method=r.method??"get",a.query=r.query??{},a.headers=r.headers??{},a.baseUrl=r.baseUrl??r.baseURL??null,a.dedupe=r.dedupe??!0,a.output=r.output??"body",a.credentials=r.credentials??"include",a.before=r.before??(e=>e),a.after=r.after??(e=>e),a.error=r.error??(e=>{throw e}),["get","head","post","patch","put","delete"].map((e=>{a[e]=(t,r={})=>a(t,{...r,method:e})})),a.create=t,a};"undefined"!=typeof window&&(window.fch=t());export default t();