browser-fetch-json
Advanced tools
Comparing version 0.2.2 to 0.3.0
@@ -1,4 +0,4 @@ | ||
//! browser-fetch-json v0.2.2 | ||
//! A thin wrapper around the browser's native Fetch API just for JSON | ||
//! MIT License -- https://github.com/center-key/browser-fetch-json | ||
//! browser-fetch-json v0.3.0 | ||
//! A wrapper around Fetch just for JSON | ||
//! MIT License -- https://github.com/center-key/fetch-json | ||
@@ -8,3 +8,3 @@ const fetch = typeof window === 'object' ? window.fetch : require('node-fetch'); | ||
const fetchJson = { | ||
version: '0.2.2', | ||
version: '0.3.0', | ||
request: function(method, url, data, options) { | ||
@@ -11,0 +11,0 @@ const settings = { method: method.toUpperCase(), credentials: 'same-origin' }; |
@@ -1,3 +0,3 @@ | ||
//! browser-fetch-json v0.2.2 | ||
//! MIT License -- https://github.com/center-key/browser-fetch-json | ||
const fetch='object'==typeof window?window.fetch:require('node-fetch'),fetchJson={version:'0.2.2',request:function(a,b,c,d){const e={method:a.toUpperCase(),credentials:'same-origin'};d=Object.assign(e,d);return d.headers=Object.assign({"Content-Type":'application/json',Accept:'application/json'},d.headers),'GET'===d.method&&c?b=b+(b.includes('?')?'&':'?')+Object.keys(c).map(function(a){return a+'='+encodeURIComponent(c[a])}).join('&'):'GET'!==d.method&&c&&(d.body=JSON.stringify(c)),fetchJson.logger&&fetchJson.logger(new Date().toISOString(),d.method,b),fetch(b,d).then(function(a){function b(b){return fetchJson.logger&&fetchJson.logger(new Date().toISOString(),d.method,a.url,a.ok,a.status,a.statusText,c),a.error=!a.ok,a.contentType=c,a.bodyText=b,a}const c=a.headers.get('content-type'),e=/json|javascript/.test(c);return e?a.json():a.text().then(b)})},get:function(a,b,c){return fetchJson.request('GET',a,b,c)},post:function(a,b,c){return fetchJson.request('POST',a,b,c)},put:function(a,b,c){return fetchJson.request('PUT',a,b,c)},patch:function(a,b,c){return fetchJson.request('PATCH',a,b,c)},delete:function(a,b,c){return fetchJson.request('DELETE',a,b,c)},logger:null,enableLogger:function(a){return fetchJson.logger='function'==typeof a?a:!1===a?null:console.log,fetchJson.logger}};'object'==typeof module?module.exports=fetchJson:'object'==typeof window&&(window.fetchJson=fetchJson); | ||
//! browser-fetch-json v0.3.0 | ||
//! MIT License -- https://github.com/center-key/fetch-json | ||
const fetch='object'==typeof window?window.fetch:require('node-fetch'),fetchJson={version:'0.3.0',request:function(a,b,c,d){const e={method:a.toUpperCase(),credentials:'same-origin'};d=Object.assign(e,d);return d.headers=Object.assign({"Content-Type":'application/json',Accept:'application/json'},d.headers),'GET'===d.method&&c?b=b+(b.includes('?')?'&':'?')+Object.keys(c).map(function(a){return a+'='+encodeURIComponent(c[a])}).join('&'):'GET'!==d.method&&c&&(d.body=JSON.stringify(c)),fetchJson.logger&&fetchJson.logger(new Date().toISOString(),d.method,b),fetch(b,d).then(function(a){function b(b){return fetchJson.logger&&fetchJson.logger(new Date().toISOString(),d.method,a.url,a.ok,a.status,a.statusText,c),a.error=!a.ok,a.contentType=c,a.bodyText=b,a}const c=a.headers.get('content-type'),e=/json|javascript/.test(c);return e?a.json():a.text().then(b)})},get:function(a,b,c){return fetchJson.request('GET',a,b,c)},post:function(a,b,c){return fetchJson.request('POST',a,b,c)},put:function(a,b,c){return fetchJson.request('PUT',a,b,c)},patch:function(a,b,c){return fetchJson.request('PATCH',a,b,c)},delete:function(a,b,c){return fetchJson.request('DELETE',a,b,c)},logger:null,enableLogger:function(a){return fetchJson.logger='function'==typeof a?a:!1===a?null:console.log,fetchJson.logger}};'object'==typeof module?module.exports=fetchJson:'object'==typeof window&&(window.fetchJson=fetchJson); |
// browser-fetch-json | ||
// Tasks | ||
// Imports | ||
const babel = require('gulp-babel'); | ||
@@ -12,2 +13,3 @@ const gulp = require('gulp'); | ||
// Setup | ||
const pkg = require('./package.json'); | ||
@@ -44,2 +46,3 @@ const banner = [ | ||
// Gulp | ||
gulp.task('build', task.build); |
{ | ||
"name": "browser-fetch-json", | ||
"description": "A thin wrapper around the browser's native Fetch API just for JSON", | ||
"version": "0.2.2", | ||
"description": "A wrapper around Fetch just for JSON", | ||
"version": "0.3.0", | ||
"license": "MIT", | ||
"main": "fetch-json.js", | ||
"repository": "github:center-key/browser-fetch-json", | ||
"homepage": "https://github.com/center-key/browser-fetch-json", | ||
"bugs": "https://github.com/center-key/browser-fetch-json/issues", | ||
"docs": "https://github.com/center-key/browser-fetch-json/blob/master/README.md", | ||
"repository": "github:center-key/fetch-json", | ||
"homepage": "https://github.com/center-key/fetch-json", | ||
"bugs": "https://github.com/center-key/fetch-json/issues", | ||
"docs": "https://github.com/center-key/fetch-json/blob/master/README.md", | ||
"keywords": [ | ||
@@ -67,4 +67,4 @@ "browser", | ||
"node-fetch": "~2.2", | ||
"whatwg-fetch": "~2.0" | ||
"whatwg-fetch": "~3.0" | ||
} | ||
} |
168
README.md
# browser-fetch-json | ||
<img src=https://raw.githubusercontent.com/center-key/browser-fetch-json/master/logos.png | ||
align=right width=200 alt=logos> | ||
_A thin wrapper around the browser's native Fetch API just for JSON_ | ||
## Deprecated | ||
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/center-key/browser-fetch-json/blob/master/LICENSE.txt) | ||
| ||
[![npm](https://img.shields.io/npm/v/browser-fetch-json.svg)](https://www.npmjs.com/package/browser-fetch-json) | ||
| ||
[![Known Vulnerabilities](https://snyk.io/test/github/center-key/browser-fetch-json/badge.svg)](https://snyk.io/test/github/center-key/browser-fetch-json) | ||
| ||
[![Build Status](https://travis-ci.org/center-key/browser-fetch-json.svg)](https://travis-ci.org/center-key/browser-fetch-json) | ||
Why would you fetch anything but json? ;) | ||
### 1) Setup | ||
In a web page: | ||
```html | ||
<script src=fetch-json.min.js></script> | ||
``` | ||
From the [jsdelivr.com CDN](https://www.jsdelivr.com/package/npm/browser-fetch-json): | ||
```html | ||
<script src=https://cdn.jsdelivr.net/npm/browser-fetch-json@0.2/fetch-json.min.js></script> | ||
browser-fetch-json + node-fetch-json = fetch-json | ||
``` | ||
Or install as a module: | ||
```shell | ||
$ npm install browser-fetch-json | ||
``` | ||
Then import with: | ||
```javascript | ||
const fetchJson = require('browser-fetch-json'); | ||
``` | ||
**browser-fetch-json** and **node-fetch-json** have been merged into **fetch-json** | ||
### 2) Examples | ||
#### HTTP GET | ||
Fetch the NASA Astronomy Picture of the Day: | ||
```javascript | ||
// NASA APOD | ||
const url = 'https://api.nasa.gov/planetary/apod'; | ||
const params = { api_key: 'DEMO_KEY' }; | ||
function handleData(data) { | ||
console.log('The NASA APOD for today is at: ' + data.url); | ||
} | ||
fetchJson.get(url, params).then(handleData); | ||
``` | ||
#### HTTP POST | ||
Create a resource for the planet Jupiter: | ||
```javascript | ||
// Create Jupiter | ||
const resource = { name: 'Jupiter', position: 5 }; | ||
function handleData(data) { | ||
console.log(data); //HTTP response body as an object literal | ||
} | ||
fetchJson.post('https://httpbin.org/post', resource) | ||
.then(handleData) | ||
.catch(console.error); | ||
``` | ||
## fetch-json | ||
### 3) Leverages the Fetch API | ||
**browser-fetch-json** uses the browser's native **[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)**. | ||
* GitHub: https://github.com/center-key/fetch-json | ||
* npm: https://www.npmjs.com/package/fetch-json2 | ||
For comparison, the above POST example to create a planet would be done directly using the **Fetch API** with the code: | ||
```javascript | ||
// Create Jupiter (with Fetch API instead of browser-fetch-json) | ||
const resource = { name: 'Jupiter', position: 5 }; | ||
const options = { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'Accept': 'application/json' | ||
}, | ||
body: JSON.stringify(resource) | ||
}; | ||
function handleData(data) { | ||
console.log(data); //HTTP response body as an object literal | ||
} | ||
fetch('https://httpbin.org/post', options) | ||
.then(response => response.json()) | ||
.then(handleData) | ||
.catch(console.error); | ||
``` | ||
The examples for **browser-fetch-json** and the **Fetch API** each produce the same output. | ||
### 4) Details | ||
The **browser-fetch-json** module automatically: | ||
1. Serializes the body payload with `JSON.stringify()`. | ||
1. Adds the JSON data type (`'application/json'`) to the HTTP headers. | ||
1. Builds the URL query string from the `params` object for GET requests. | ||
1. Runs `.json()` on the response from the promise. | ||
1. Sets `credentials` to `'same-origin'` to support user sessions for frameworks/servers such as Grails, Rails, PHP, Flask, etc. | ||
1. If the response body is HTML or text, it's converted to JSON. | ||
### 5) API | ||
The format for using **browser-fetch-json** is: | ||
#### GET | ||
```javascript | ||
fetchJson.get(url, params, options).then(callback); | ||
``` | ||
#### POST | ||
```javascript | ||
fetchJson.post(url, resource, options).then(callback); | ||
``` | ||
#### PUT | ||
```javascript | ||
fetchJson.put(url, resource, options).then(callback); | ||
``` | ||
#### PATCH | ||
```javascript | ||
fetchJson.patch(url, resource, options).then(callback); | ||
``` | ||
#### DELETE | ||
```javascript | ||
fetchJson.delete(url, resource, options).then(callback); | ||
``` | ||
Notes: | ||
1. Only the `url` parameter is required. The other parameters are optional. | ||
1. The `params` object for `fetchJson.get()` is converted into a query string and appended to the `url`. | ||
1. The `resource` object is turned into the body of the HTTP request. | ||
1. The `options` parameter is passed through to the **Fetch API** (see the MDN **Fetch API** documentation for supported **[`init` options](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)**). | ||
#### Dynamic HTTP method | ||
If you need to programmatically set the method, use the format: | ||
```javascript | ||
fetchJson.request(method, url, data, options).then(callback); | ||
``` | ||
Where `method` is `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, or `'DELETE'`, and `data` represents | ||
either `params` or `resource`. | ||
#### Logging | ||
Enable basic logging to the console with: | ||
```javascript | ||
fetchJson.enableLogger(); | ||
``` | ||
Pass in a function to use a custom logger or pass in `false` to disable logging. | ||
#### Text to JSON | ||
If the HTTP response body is not JSON (`Content-Type` is not `"application/json"` or `"text/javascript"`), an object containing the body as a string in the `bodyText` field is created and passed on through the promise. In addition to the `bodyText` field, the object | ||
will have the fields: `ok`, `status`, `statusText`, and `contentType`. | ||
For example, an HTTP response for an error status of 500 would be converted to an object | ||
similar to: | ||
```javascript | ||
{ | ||
ok: false, | ||
status: 500, | ||
statusText: 'INTERNAL SERVER ERROR', | ||
contentType: 'text/html; charset=utf-8', | ||
bodyText: '<!doctype html><html><body>Server Error</body></html>' | ||
} | ||
``` | ||
### 6) Legacy web browsers | ||
To support really old browsers, include polyfills for | ||
[Promise](https://github.com/taylorhakes/promise-polyfill/) and | ||
[Fetch API](https://github.com/github/fetch): | ||
Load from the [jsdelivr.com CDN](https://www.jsdelivr.com/package/npm/fetch-json2): | ||
```html | ||
<script src=https://cdn.jsdelivr.net/npm/promise-polyfill@8.1/dist/polyfill.min.js></script> | ||
<script src=https://cdn.jsdelivr.net/npm/whatwg-fetch@2.0/fetch.min.js></script> | ||
<script src=https://cdn.jsdelivr.net/npm/fetch-json2@0.3/fetch-json.min.js></script> | ||
``` | ||
### 7) Related | ||
[node-fetch-json](https://github.com/center-key/node-fetch-json) - A version for node | ||
### 8) Questions or enhancements | ||
Feel free to submit an [issue](https://github.com/center-key/browser-fetch-json/issues). | ||
--- | ||
[MIT License](LICENSE.txt) |
@@ -9,3 +9,3 @@ // Mocha Specification Cases | ||
// Setup | ||
const scripts = ['node_modules/whatwg-fetch/fetch.js', './fetch-json.js']; | ||
const scripts = ['node_modules/whatwg-fetch/dist/fetch.umd.js', './fetch-json.js']; | ||
const window = new JSDOM('', { runScripts: 'outside-only' }).window; | ||
@@ -261,2 +261,72 @@ function loadScript(file) { window.eval(fs.readFileSync(file).toString()); } | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
describe('The "bodyText" field of the object returned from requesting', () => { | ||
function getFirstLine(string) { return string.split('\n', 1)[0]; } | ||
it('an HTML web page is a string that begins with "<!DOCTYPE html>"', (done) => { | ||
const url = 'https://httpbin.org/html'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'text/html; charset=utf-8', | ||
firstLine: '<!DOCTYPE html>' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
it('an XML document is a string that begins with "<!DOCTYPE xml>"', (done) => { | ||
const url = 'https://httpbin.org/xml'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'application/xml', | ||
firstLine: '<?xml version=\'1.0\' encoding=\'us-ascii\'?>' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
it('a "robots.txt" text file is a string that begins with "User-agent: *"', (done) => { | ||
const url = 'https://httpbin.org/robots.txt'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'text/plain', | ||
firstLine: 'User-agent: *' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
}); | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
describe('Function fetchJson.enableLogger()', () => { | ||
@@ -263,0 +333,0 @@ |
@@ -254,2 +254,72 @@ // Mocha Specification Cases | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
describe('The "bodyText" field of the object returned from requesting', () => { | ||
function getFirstLine(string) { return string.split('\n', 1)[0]; } | ||
it('an HTML web page is a string that begins with "<!DOCTYPE html>"', (done) => { | ||
const url = 'https://httpbin.org/html'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'text/html; charset=utf-8', | ||
firstLine: '<!DOCTYPE html>' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
it('an XML document is a string that begins with "<!DOCTYPE xml>"', (done) => { | ||
const url = 'https://httpbin.org/xml'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'application/xml', | ||
firstLine: '<?xml version=\'1.0\' encoding=\'us-ascii\'?>' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
it('a "robots.txt" text file is a string that begins with "User-agent: *"', (done) => { | ||
const url = 'https://httpbin.org/robots.txt'; | ||
function handleData(data) { | ||
const actual = { | ||
ok: data.ok, | ||
status: [data.status, data.statusText], | ||
contentType: data.contentType, | ||
firstLine: getFirstLine(data.bodyText) | ||
}; | ||
const expected = { | ||
ok: true, | ||
status: [200, 'OK'], | ||
contentType: 'text/plain', | ||
firstLine: 'User-agent: *' | ||
}; | ||
assert.deepEqual(actual, expected); | ||
done(); | ||
} | ||
fetchJson.get(url).then(handleData); | ||
}); | ||
}); | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
describe('Function fetchJson.enableLogger()', () => { | ||
@@ -256,0 +326,0 @@ |
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
742
2
157681
20