{"id":15290454,"url":"https://github.com/center-key/fetch-json","last_synced_at":"2025-04-05T14:06:19.035Z","repository":{"id":49528538,"uuid":"146338086","full_name":"center-key/fetch-json","owner":"center-key","description":"🐶 A wrapper around Fetch just for JSON (with TypeScript declarations)","archived":false,"fork":false,"pushed_at":"2025-03-04T00:42:01.000Z","size":797,"stargazers_count":32,"open_issues_count":2,"forks_count":17,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T13:09:29.575Z","etag":null,"topics":["browser","fetch","get","http","jamstack","javascript","json","node-fetch","nodejs","post","rest","typescript"],"latest_commit_sha":null,"homepage":"https://fetch-json.js.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/center-key.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-27T18:31:31.000Z","updated_at":"2025-03-04T00:41:54.000Z","dependencies_parsed_at":"2023-11-10T12:33:58.195Z","dependency_job_id":"32938057-58d9-4ba5-a662-2172c3b6d0fa","html_url":"https://github.com/center-key/fetch-json","commit_stats":{"total_commits":328,"total_committers":12,"mean_commits":"27.333333333333332","dds":0.04573170731707321,"last_synced_commit":"7a49852160aae3abf2911eb416f7fad4774b3a57"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Ffetch-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Ffetch-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Ffetch-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Ffetch-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/center-key","download_url":"https://codeload.github.com/center-key/fetch-json/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247345852,"owners_count":20924102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","fetch","get","http","jamstack","javascript","json","node-fetch","nodejs","post","rest","typescript"],"created_at":"2024-09-30T16:08:15.388Z","updated_at":"2025-04-05T14:06:18.997Z","avatar_url":"https://github.com/center-key.png","language":"TypeScript","readme":"# fetch-json\n\u003cimg src=https://raw.githubusercontent.com/center-key/fetch-json/main/docs/logos.png\n   align=right width=180 alt=logos\u003e\n\n_A wrapper around Fetch just for JSON_\n\n[![License:MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/center-key/fetch-json/blob/main/LICENSE.txt)\n[![npm](https://img.shields.io/npm/v/fetch-json.svg)](https://www.npmjs.com/package/fetch-json)\n[![Build](https://github.com/center-key/fetch-json/actions/workflows/run-spec-on-push.yaml/badge.svg)](https://github.com/center-key/fetch-json/actions/workflows/run-spec-on-push.yaml)\n\nWhy would you fetch anything but json? ;)\n\n## A) Make REST Easy\n**fetch-json** is a lightweight JavaScript library to reduce the boilerplate code needed to make\nHTTP calls to JSON endpoints.\nThe minified JS file is under 4 KB.\n\n**fetch-json** automatically:  \u003c!-- sync with docs/index.html --\u003e\n1. Adds the HTTP header `Content-Type: application/json` to ensure the correct data type\n1. Runs `.json()` on the response\n1. Serializes the body payload with `JSON.stringify()`\n1. Appends `params` to the URL of `GET` requests\n1. Sets `credentials` to `'same-origin'` (support user sessions in frameworks like Grails, Rails, PHP, Django, Flask, etc.)\n1. Converts the HTTP text response to JSON if it's not already JSON (convenient for handling HTTP errors)\n1. Maps HTTP response headers from a `HEAD` request into a simple object\n\n**fetch-json** is ideal for a [JAMstack](https://jamstack.org) architecture  where \"dynamic\nprogramming during the request/response cycle is handled by JavaScript, running entirely on the\nclient\".\n\n## B) Setup\n### 1. Web browser\nIn a web page:\n```html\n\u003cscript src=fetch-json.min.js\u003e\u003c/script\u003e\n```\nor from the [jsdelivr.com CDN](https://www.jsdelivr.com/package/npm/fetch-json):\n```html\n\u003cscript src=https://cdn.jsdelivr.net/npm/fetch-json@3.3/dist/fetch-json.min.js\u003e\u003c/script\u003e\n```\n### 2. Node.js server\nInstall package for node:\n```shell\n$ npm install fetch-json\n```\nand then import:\n```javascript\nimport { fetchJson } from 'fetch-json';\n```\n\nRequires minimum **node v18.**\n\nIf you use GitHub Actions, ensure the version of node is set correclty:\n```yaml\n- uses: actions/setup-node@v3\n  with:\n    node-version: 18\n```\n\n## C) Examples\n### 1. HTTP GET\nFetch the NASA Astronomy Picture of the Day:\n```javascript\n// NASA APoD\nconst url =    'https://api.nasa.gov/planetary/apod';\nconst params = { api_key: 'DEMO_KEY' };\nconst handleData = (data) =\u003e\n   console.log('The NASA APoD for today is at:', data.url);\nfetchJson.get(url, params).then(handleData);\n```\nExample output:\n```\n\u003e The NASA APoD for today is at:\n\u003e https://apod.nasa.gov/apod/image/2107/LRVBPIX3M82Crop1024.jpg\n```\n### 2. HTTP POST\nCreate a resource for the planet Jupiter:\n```javascript\n// Create Jupiter\nconst resource = { name: 'Jupiter', position: 5 };\nconst handleData = (data) =\u003e\n   console.log('New planet:', data);  //http response body as an object literal\nfetchJson.post('https://centerkey.com/rest/', resource)\n   .then(handleData)\n   .catch(console.error);\n```\nFor more examples, see the Mocha specification suite:\u003cbr\u003e\n[spec/node.spec.js](spec/node.spec.js)\n([Mocha output for each **build** under `Run npm test`](https://github.com/center-key/fetch-json/actions/workflows/run-spec-on-push.yaml))\n\nTo see a website that incorporates **fetch-json**, check out DataDashboard:\u003cbr\u003e\n[data-dashboard.js.org 📊](https://data-dashboard.js.org)\n\n## D) Examples Using async/await\n### 1. HTTP GET\nFetch the NASA Astronomy Picture of the Day:\n```javascript\n// NASA APoD\nconst show = async () =\u003e {\n   const url =    'https://api.nasa.gov/planetary/apod';\n   const params = { api_key: 'DEMO_KEY' };\n   const data =   await fetchJson.get(url, params);\n   console.log('The NASA APoD for today is at: ' + data.url);\n   };\nshow();\n```\n### 2. HTTP POST\nCreate a resource for the planet Jupiter:\n```javascript\n// Create Jupiter\nconst create = async (resource) =\u003e {\n   const data = await fetchJson.post('https://centerkey.com/rest/', resource);\n   console.log('New planet:', data);  //http response body as an object literal\n   };\ncreate({ name: 'Jupiter', position: 5 });\n```\n\n## E) Leverages Fetch API\n**fetch-json** calls the native\n**[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)**.\n\nFor comparison, the POST example in section [C) Examples](#c-examples) to create a planet would be\ndone calling the **Fetch API**\ndirectly with the code:\n```javascript\n// Create Jupiter (WITHOUT fetch-json)\nconst resource = { name: 'Jupiter', position: 5 };\nconst options = {\n   method: 'POST',\n   headers: {\n      'Content-Type': 'application/json',\n      'Accept': 'application/json',\n      },\n   body: JSON.stringify(resource),\n   };\nconst handleData = (data) =\u003e\n   console.log(data);  //http response body as an object literal\nfetch('https://centerkey.com/rest/', options)\n   .then(response =\u003e response.json())\n   .then(handleData)\n   .catch(console.error);\n```\nThe example _with_ **fetch-json** and the example _without_ **fetch-json** each produce the same\noutput.\n\n## F) API\n### 1. API \u0026mdash; HTTP Request\nThe format for using **fetch-json** is:\n#### GET\n```javascript\nfetchJson.get(url, params, options).then(callback);\n```\n#### POST\n```javascript\nfetchJson.post(url, resource, options).then(callback);\n```\n#### PUT\n```javascript\nfetchJson.put(url, resource, options).then(callback);\n```\n#### PATCH\n```javascript\nfetchJson.patch(url, resource, options).then(callback);\n```\n#### DELETE\n```javascript\nfetchJson.delete(url, resource, options).then(callback);\n```\n#### HEAD (HTTP response headers)\n```javascript\nfetchJson.head(url, params, options).then(callback);  //headers returned as an object\n```\nNotes:\n1. Only the `url` parameter is required.\u0026nbsp; The other parameters are optional.\n1. The `params` object for `fetchJson.get()` is converted into a query string and appended to the `url`.\n1. The `resource` object is turned into the body of the HTTP request.\n1. The `options` parameter is passed through to the **Fetch API** (see the `init` [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)).\n1. `options` is enhanced with a boolean setting for `strictErrors` mode (default `false`) that throws an error to `.catch()` whenever the HTTP response status is 400 or higher.\n\n#### Dynamic HTTP method\nIf you need to programmatically set the method, use the format:\n```javascript\nfetchJson.request(method, url, data, options).then(callback);\n```\nWhere `method` is `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, or `'DELETE'`, and `data` represents\neither `params` or `resource`.\n\n### 2. API \u0026mdash; logging\nTurn on basic logging to the console with:\n```javascript\nfetchJson.enableLogger();\n```\nTo use a custom logger, pass in a function that accepts 9 parameters to log.\n\nTo get an array containing the names of the parameters:\n```javascript\nfetchJson.getLogHeaders();\n// 'Timestamp', 'HTTP', 'Method', 'Domain', 'URL', 'Ok', 'Status', 'Text', 'Type'\n```\nThe default console output looks like:\u003cbr\u003e\n`2018-09-12T07:20:12.372Z – \"request\" - \"GET\" – \"api.nasa.gov\" – \"https://api.nasa.gov/planetary/apod\"`\u003cbr\u003e\n`2018-09-12T07:20:13.009Z – \"response\" - \"GET\" – \"api.nasa.gov\" – \"https://api.nasa.gov/planetary/apod\" - true - 200 - \"OK\" - \"application/json\"`\n\nTurn off logging with:\n```javascript\nfetchJson.enableLogger();\n```\n\n## G) Response Text and Errors Converted to JSON\nThe HTTP response body is considered to be JSON if the `Content-Type` is `\"application/json\"` or\n`\"text/javascript\"`.\u0026nbsp;\nIf the HTTP response body is not JSON, **fetch-json** passes back\nthrough the promise an object with a `bodyText` string field containing response body text.\n\nIn addition to the `bodyText` field, the object will have the fields: `ok`, `status`, `statusText`,\n`contentType`, and `data`.\u0026nbsp;\nIf an HTML error response is JSON, the `data` will contain the parsed JSON.\n\nFor example, an HTTP response for an error status of 500 would be converted to an object\nsimilar to:\n```javascript\n{\n   ok:          false,\n   status:      500,\n   statusText:  'INTERNAL SERVER ERROR',\n   contentType: 'text/html; charset=utf-8',\n   bodyText:    '\u003c!doctype html\u003e\u003chtml lang=en\u003e\u003cbody\u003eServer Error\u003c/body\u003e\u003c/html\u003e',\n   data:        null,\n}\n```\nEvery response that is not JSON or is an HTTP error will be consistently formatted like the object above.\u0026nbsp;\nWith **fetch-json** you know the response will always be passed back to you as a consistent,\nsimple object literal.\n\n## H) Base Options\nUse `fetchJson.setBaseOptions()` to configure options to be used on future **fetchJson** requests.\n\nThe example below sets the `Authorization` HTTP header so it is sent on the subsequent GET and\nDELETE requests:\n```javascript\nfetchJson.setBaseOptions({ headers: { Authorization: 'Basic WE1MIGlzIGhpZGVvdXM=' } });\nfetchJson.get('https://dna-engine.org/api/books/').then(display);  //with auth header\nfetchJson.delete('https://dna-engine.org/api/books/3/');           //with auth header\n```\n\nTo have multiple base options available at the same time, use the `FetchJson` class to instantiate\nmultiple copies of `fetchJson`:\n```javascript\nimport { FetchJson } from 'fetch-json';\n\nconst fetchJsonA = new FetchJson({ headers: { From: 'aaa@example.com' } }).fetchJson;\nconst fetchJsonB = new FetchJson({ headers: { From: 'bbb@example.com' } }).fetchJson;\nfetchJsonA.get('https://dna-engine.org/api/books/').then(display);  //from aaa@example.com\nfetchJsonB.delete('https://dna-engine.org/api/books/3/');           //from bbb@example.com\n```\n\n## I) TypeScript Declarations\nSee the TypeScript declarations at the top of the [fetch-json.ts](src/fetch-json.ts) file.\n\nThe declarations provide type information about the API.  For example, the `fetchJson.post()`\nfunction returns a **Promise** for a `FetchResponse`:\n```typescript\nfetchJson.post(url: string, resource?: RequestData,\n   options?: FetchOptions): Promise\u003cFetchResponse\u003e\n```\n\n## J) Fetch polyfills\n### 1. Add Fetch to JSDOM\nJSDOM does not include `fetch`, so you need to add a polyfill.\n```shell\n$ npm install --save-dev whatwg-fetch\n```\nSee usage of `whatwg-fetch` in [spec/jsdom.spec.js](spec/jsdom.spec.js).\n\n### 2. Legacy Node.js\nNative support for **Fetch API** was introduced in **node v18** which became the Active LTS version on 2022-10-25.\u0026nbsp;\nIf you're using an older version of **node,** stick with **fetch-json v2.7** and in your **package.json** file declare a dependency on the **node-fetch** polyfill package.\n```shell\n$ npm install node-fetch\n```\n\n## K) Build Environment\nCheck out the `runScriptsConfig` section in [package.json](package.json) for an\ninteresting approach to organizing build tasks.\n\n**CLI Build Tools for package.json**\n   - 🎋 [add-dist-header](https://github.com/center-key/add-dist-header):\u0026nbsp; _Prepend a one-line banner comment (with license notice) to distribution files_\n   - 📄 [copy-file-util](https://github.com/center-key/copy-file-util):\u0026nbsp; _Copy or rename a file with optional package version number_\n   - 📂 [copy-folder-util](https://github.com/center-key/copy-folder-util):\u0026nbsp; _Recursively copy files from one folder to another folder_\n   - 🪺 [recursive-exec](https://github.com/center-key/recursive-exec):\u0026nbsp; _Run a command on each file in a folder and its subfolders_\n   - 🔍 [replacer-util](https://github.com/center-key/replacer-util):\u0026nbsp; _Find and replace strings or template outputs in text files_\n   - 🔢 [rev-web-assets](https://github.com/center-key/rev-web-assets):\u0026nbsp; _Revision web asset filenames with cache busting content hash fingerprints_\n   - 🚆 [run-scripts-util](https://github.com/center-key/run-scripts-util):\u0026nbsp; _Organize npm package.json scripts into groups of easy to manage commands_\n   - 🚦 [w3c-html-validator](https://github.com/center-key/w3c-html-validator):\u0026nbsp; _Check the markup validity of HTML files using the W3C validator_\n\n\u003cbr\u003e\n\n---\n_\"Stop trying to make fetch happen without [#fetchJson](https://twitter.com/hashtag/fetchJson)!\"_\n\nFeel free to submit questions at:\u003cbr\u003e\n[github.com/center-key/fetch-json/issues](https://github.com/center-key/fetch-json/issues)\n\n[MIT License](LICENSE.txt)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcenter-key%2Ffetch-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcenter-key%2Ffetch-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcenter-key%2Ffetch-json/lists"}