diff --git a/README.md b/README.md index 72dca8c..f71d29c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Fetch, supercharged. The [Fetch Web API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) is great, but it could be better. -AxleJS supercharges fetch, with better error handling, easier to use options, can automatically follow redirects, an easier way to manage and view headers and search queries, custom response and request classes and methods, and a lot more. +AxleJS supercharges fetch, with better error handling, using custom and built-in middleware and options, an easier way to manage and view headers and search queries, custom response and request classes and methods, and a lot more. ## [Documentation](https://github.com/ksplatdev/AxleJS/wiki/Documenation) @@ -49,7 +49,7 @@ AxleJS supercharges fetch, with better error handling, easier to use options, ca ### CDN -1. Import from or for minified version . +1. Import from or for minified version . 2. Read the [documentation](https://github.com/ksplatdev/AxleJS/wiki/Documenation). ## Quick Start diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..da9d795 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,5 @@ +# AxleJS Examples + +Examples of the AxleJS API. + +This is **NOT** documentation. For documentation go to diff --git a/examples/injectData.ts b/examples/injectData.ts new file mode 100644 index 0000000..208fb19 --- /dev/null +++ b/examples/injectData.ts @@ -0,0 +1,18 @@ +import Axle from '../dist/index'; + +// inject into json results +Axle.inject({ + someInjectedData: 'injected', +}); + +// inject with middleware, check examples/useMiddleware.ts for more info +Axle.use((req, res) => { + Axle.inject({ timeTook: res.timeTook }); +}); + +(async () => { + const res = await Axle.get('https://someApi.com/documentation'); + const json = await res.json(); + + console.log(json.someInjectedData); // 'injected' +})(); diff --git a/examples/productionEx.ts b/examples/productionEx.ts new file mode 100644 index 0000000..4b67079 --- /dev/null +++ b/examples/productionEx.ts @@ -0,0 +1,79 @@ +// production example + +// types +interface Result { + status: number; + statusMessage: string; + message: string; + sessionToken: string; + regenerated: boolean; +} + +// dependencies +import Axle from '../dist'; + +// constants +const form: HTMLFormElement = document.querySelector('#loginForm'); +const formData = new FormData(form); + +// setup +form.onsubmit = (e) => { + e.preventDefault(); + + loginUser(); +}; + +Axle.use(Axle.middleware.timeTook()); +Axle.useOptions(Axle.middlewareOptions.kneepads()); +Axle.useOptions(Axle.middlewareOptions.cors()); + +// custom middleware to inject regenerated property into json +Axle.use((req, res) => { + if (req.method === 'POST') { + if (Boolean(res.queryParam('regenerateToken')) === true) { + Axle.inject({ + regenerated: true, + }); + } else { + Axle.inject({ + regenerated: false, + }); + } + } +}); + +// Main + +// loginUser function, makes post request to /api/login, sets sessionToken, and follows redirect +async function loginUser(regenerateToken = false) { + const url = `https://example.com/api/login?regenerateToken=${regenerateToken}`; + + const res = await Axle.post(url, formData, { + handleStatus: handleStatus, + }); + const json = await res.json(); + + console.log(json.message); + + // login session token + localStorage.setItem('test-session-token', json.sessionToken); + + // if new token was generated + if (json.regenerated) { + console.log('New token.'); + } + + // follow redirect by Location header + res.finishRedirect(); +} + +// custom handle status +// return true to throw error and reject or false to resolve and continue +function handleStatus(status: number, statusMessage: string) { + if (status >= 500) { + console.log(status, statusMessage); + return true; + } else { + return false; + } +} diff --git a/package-lock.json b/package-lock.json index 303cbea..1d596d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "axlejs", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -211,9 +211,9 @@ "dev": true }, "@types/node": { - "version": "16.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.4.tgz", - "integrity": "sha512-25QXpDsTiDnl2rZGUenagVMwO46way8dOUdvoC3R3p+6TrbpxeJBo/v87BEG1IHI31Jhaa8lPeSHcqwxsVBeYQ==", + "version": "16.7.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz", + "integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==", "dev": true }, "@types/normalize-package-data": { @@ -956,9 +956,9 @@ } }, "electron-to-chromium": { - "version": "1.3.822", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.822.tgz", - "integrity": "sha512-k7jG5oYYHxF4jx6PcqwHX3JVME/OjzolqOZiIogi9xtsfsmTjTdie4x88OakYFPEa8euciTgCCzvVNwvmjHb1Q==", + "version": "1.3.829", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.829.tgz", + "integrity": "sha512-5EXDbvsaLRxS1UOfRr8Hymp3dR42bvBNPgzVuPwUFj3v66bpvDUcNwwUywQUQYn/scz26/3Sgd3fNVGQOlVwvQ==", "dev": true }, "emoji-regex": { @@ -2637,17 +2637,17 @@ } }, "terser-webpack-plugin": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz", - "integrity": "sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.3.tgz", + "integrity": "sha512-eDbuaDlXhVaaoKuLD3DTNTozKqln6xOG6Us0SzlKG5tNlazG+/cdl8pm9qiF1Di89iWScTI0HcO+CDcf2dkXiw==", "dev": true, "requires": { - "jest-worker": "^27.0.2", + "jest-worker": "^27.0.6", "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", + "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", - "terser": "^5.7.0" + "terser": "^5.7.2" } }, "text-table": { @@ -2780,9 +2780,9 @@ } }, "webpack": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.1.tgz", - "integrity": "sha512-xsn3lwqEKoFvqn4JQggPSRxE4dhsRcysWTqYABAZlmavcoTmwlOb9b1N36Inbt/eIispSkuHa80/FJkDTPos1A==", + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.2.tgz", + "integrity": "sha512-odydxP4WA3XYYzwSQUivPxywdzMlY42bbfxMwCaEtHb+i/N9uzKSHcLgWkXo/Gsa+4Zlzf3Jg0hEHn1FnZpk2Q==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", diff --git a/package.json b/package.json index 6397ceb..48bd1ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "axlejs", - "version": "1.1.1", + "version": "1.2.0", "description": "Fetch, supercharged.", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -47,7 +47,7 @@ "prettier": "^2.3.2", "typescript": "^4.4.2", "uglify-js": "^3.14.1", - "webpack": "^5.51.1", + "webpack": "^5.51.2", "webpack-cli": "^4.8.0" } } diff --git a/src/core/delete.ts b/src/core/delete.ts index 0dd4794..db722c5 100644 --- a/src/core/delete.ts +++ b/src/core/delete.ts @@ -5,7 +5,7 @@ import AxleResponse from '../models/response'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export default async function deleteReq | FormData>( url: string, - data?: t | undefined | null, + data?: t | FormData | undefined | null, options: AxleTypes.AxleOptions = { mode: 'cors', cache: 'default', diff --git a/src/core/inject.ts b/src/core/inject.ts new file mode 100644 index 0000000..6778654 --- /dev/null +++ b/src/core/inject.ts @@ -0,0 +1,9 @@ +const __axle_js__inject_arr: Record[] = []; + +export default function inject(data: Record) { + return __axle_js__inject_arr.push(data); +} + +export function __getInjectedData() { + return __axle_js__inject_arr; +} diff --git a/src/core/patch.ts b/src/core/patch.ts index 4a84560..d238920 100644 --- a/src/core/patch.ts +++ b/src/core/patch.ts @@ -5,7 +5,7 @@ import AxleResponse from '../models/response'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export default async function patch>( url: string, - data?: t | undefined | null, + data?: t | FormData | undefined | null, options: AxleTypes.AxleOptions = { mode: 'cors', cache: 'default', diff --git a/src/core/post.ts b/src/core/post.ts index 3ba1fe4..37ac08f 100644 --- a/src/core/post.ts +++ b/src/core/post.ts @@ -5,7 +5,7 @@ import AxleResponse from '../models/response'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export default async function post>( url: string, - data?: t | undefined | null, + data?: t | FormData | undefined | null, options: AxleTypes.AxleOptions = { mode: 'cors', cache: 'default', diff --git a/src/core/put.ts b/src/core/put.ts index d7b32d9..f3da0dc 100644 --- a/src/core/put.ts +++ b/src/core/put.ts @@ -5,7 +5,7 @@ import AxleResponse from '../models/response'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export default async function put>( url: string, - data?: t | undefined | null, + data?: t | FormData | undefined | null, options: AxleTypes.AxleOptions = { mode: 'cors', cache: 'default', diff --git a/src/index.ts b/src/index.ts index 1fc7558..648e06b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import deleteReq from './core/delete'; import get from './core/get'; import head from './core/head'; +import inject from './core/inject'; import patch from './core/patch'; import post from './core/post'; import put from './core/put'; @@ -76,6 +77,7 @@ const Axle = { cancelMark: AxleCancelMark, use: use, useOptions: useOptions, + inject: inject, middleware: { timeTook: timeTook, }, diff --git a/src/models/request.ts b/src/models/request.ts index b207ba6..4ebf9b7 100644 --- a/src/models/request.ts +++ b/src/models/request.ts @@ -19,7 +19,7 @@ export default class AxleRequest> { constructor( method: string, url: string, - body: t | undefined | null, + body: t | FormData | undefined | null, options: AxleTypes.AxleOptions ) { this.method = method.toUpperCase(); diff --git a/src/models/response.ts b/src/models/response.ts index 12b3ab1..388d52c 100644 --- a/src/models/response.ts +++ b/src/models/response.ts @@ -1,5 +1,6 @@ // Class for converting Response to AxleResponse to supercharge fetch! +import { __getInjectedData } from '../core/inject'; import getQuery from '../utils/getQuery'; import queryParam from '../utils/queryParam'; import AxleHeaders from './headers'; @@ -16,8 +17,20 @@ export default class AxleResponse { this.timeEnd = timeEnd; } - public async json>(): Promise { - const json = await this.res.json(); + public async json>() { + let json: t = await this.res.json(); + + // get injected data + + const injectedData = __getInjectedData(); + + // add injected data + injectedData.forEach((data) => { + json = { + ...json, + ...data, + }; + }); return json; }