-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3638c54
Showing
24 changed files
with
5,362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
node_modules | ||
.DS_Store | ||
lib | ||
*.js | ||
dist | ||
uploads |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pnpm lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
lib/tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# CHANGELOG 📝 | ||
|
||
## v0.0.3 2024-02-20 | ||
|
||
- Chore: improve README and add more tests | ||
- Feat: `xiorInstance.request` remove first parameter `url` | ||
|
||
## v0.0.2 2024-02-18 | ||
|
||
- Feat: compatiable error handle with axios's response interceptor | ||
|
||
## v0.0.1 2024-02-15 | ||
|
||
🐣 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
[![npm version](https://badgen.net/npm/v/xior?color=green)](https://www.npmjs.com/package/xior) | ||
[![minzipped size](https://badgen.net/badge/gzip/2.6kb/green)](https://bundlephobia.com/package/xior) | ||
[![tree shaking](https://badgen.net/bundlephobia/tree-shaking/xior)](https://bundlephobia.com/package/xior) | ||
![typescript](https://badgen.net/badge/icon/typescript?icon=typescript&label&color=blue) | ||
[![dependency](https://badgen.net/bundlephobia/dependency-count/xior)](https://bundlephobia.com/package/xior) | ||
![license](https://badgen.net/npm/license/xior?color=blue) | ||
|
||
# Xior | ||
|
||
An axios similar API request library but use fetch, and more. | ||
|
||
Features: | ||
|
||
- 🫡 Similiar `axios.create` / `axios.interceptors.request.use` / `axios.interceptors.response.use` / `.get/post/put/patch/delete/head/options` | ||
- 🔥 Use fetch | ||
- 🚀 Lightweight ~6KB, Gzip ~2.6KB | ||
- 🤙 Support timeout and cancel request | ||
- 👊 Unit tests | ||
- 💪 100% Write in TypeScript | ||
- [ ] **❗️❗️❗️WIP** 🥷 Plugins support: error retry, cache, repeat requests filter plugins 😎 | ||
|
||
## Getting Started | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const http = xior.create({ baseURL: 'https://exmaple.com', timeout: 120 * 1000 }); | ||
|
||
http.interceptors.request.use((config) => { | ||
// do something | ||
return config; | ||
}); | ||
|
||
http.interceptors.response.use((result) => { | ||
const { config, response, data } = result; | ||
// do something | ||
return result; | ||
}); | ||
|
||
// GET | ||
async function getList() { | ||
const { data } = await http.get('/list', { params: { page: 1, perPage: 20 } }); | ||
return data; | ||
} | ||
|
||
// POST | ||
async function create() { | ||
const { data } = await http.post( | ||
'/create', | ||
{ name: 'test', desc: 'foobar..foobar' }, | ||
{ params: { redirect: '/list' } } | ||
); | ||
return data; | ||
} | ||
``` | ||
|
||
## Usage | ||
|
||
### GET / POST | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const instance = xior.create({}); | ||
|
||
await instance.get('http://httpbin.org', { | ||
params: { | ||
a: 1, | ||
b: 2, | ||
}, | ||
}); | ||
|
||
await instance.post('http://httpbin.org', { | ||
a: 1, | ||
b: 2, | ||
}); | ||
``` | ||
|
||
### URL encode support nested objects | ||
|
||
In **xior**, URI encoded strings default use lite encode, means if your `params` is nested object, it will be `[object object]`: | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const instance = xior.create({}); | ||
instance.get('http://httpbin.org', { | ||
params: { | ||
a: 1, | ||
b: { | ||
c: 2, | ||
}, | ||
}, | ||
}); | ||
``` | ||
|
||
The url will be like: `http://httpbin.org?a=1&b=[object object]`, to support nested objects url encoded, use `qs`'s `stringify` module: | ||
|
||
```ts | ||
import xior from 'xior'; | ||
// @ts-ignore | ||
import stringify from 'qs/lib/stringify'; | ||
|
||
const instance = xior.create({ | ||
encode: (params: Record<string, any>) => stringify(params, {}), | ||
}); | ||
instance.get('http://httpbin.org', { | ||
params: { | ||
a: 1, | ||
b: { | ||
c: 2, | ||
}, | ||
}, | ||
}); | ||
|
||
// http://httpbin.org?a=1&b[c]=2 | ||
``` | ||
|
||
### Upload data | ||
|
||
> Not like axios, xior doesn't support upload progess or download progress. | ||
Use FormData to upload files. | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const instance = xior.create(); | ||
|
||
const formData = new FormData(); | ||
|
||
formData.append('file', fileObject); | ||
formData.append('filed1', 'val1'); | ||
formData.append('filed2', 'val2'); | ||
|
||
instance.post('/upload', formData).then((res) => { | ||
console.log(res.data); | ||
}); | ||
``` | ||
|
||
### Timeout | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const instance = xior.create({ | ||
timeout: 120 * 1000, | ||
}); | ||
|
||
await instance.post( | ||
'http://httpbin.org', | ||
{ | ||
a: 1, | ||
b: 2, | ||
}, | ||
{ | ||
timeout: 60 * 1000, // override default timeout 120 * 1000 | ||
} | ||
); | ||
``` | ||
|
||
### Cancel request | ||
|
||
```ts | ||
import xior from 'xior'; | ||
const instance = xior.create(); | ||
|
||
const controller = new AbortController(); | ||
|
||
xiorInstance.get('http://httpbin.org', { signal: controller.signal }).then((res) => { | ||
console.log(res.data); | ||
}); | ||
|
||
class CancelRequestError extends Error {} | ||
controller.abort(new CancelRequestError()); // abort request with custom error | ||
``` | ||
|
||
### xior.interceptors.request.use | ||
|
||
```ts | ||
import xior, { merge as deepMerge } from 'xior'; | ||
|
||
const instance = xior.create(); | ||
instance.interceptors.request.use((config) => { | ||
return deepMerge(config, { | ||
headers: { | ||
token: localStorage.getItem('token') || '', | ||
}, | ||
}); | ||
}); | ||
``` | ||
|
||
### xior.interceptors.response.use | ||
|
||
```ts | ||
import xior, { merge as deepMerge } from 'xior'; | ||
|
||
const instance = xior.create(); | ||
instance.interceptors.response.use( | ||
(res) => { | ||
const { data, request, response } = res; | ||
console.log(request, resposne, data); | ||
return res; | ||
}, | ||
function onRejected(error) { | ||
throw error; | ||
} | ||
); | ||
``` | ||
|
||
### stream | ||
|
||
> if the options `responseType` is `responseType: 'stream' | 'document' | 'arraybuffer' | 'blob'`, then xior will just return the original response: `{ response }`, you can do anthing with response you like: | ||
```ts | ||
import xior, { merge as deepMerge } from 'xior'; | ||
const instance = xior.create({ | ||
baseURL: 'http://httpbin.org', | ||
}); | ||
|
||
instance.get('/stream', { responseType: 'stream' }).then(({ response }) => { | ||
// `response` is the original response, like fetch('/stream').then(response => { console.log(response)}) | ||
}); | ||
``` | ||
|
||
## Use plugins | ||
|
||
**❗️❗️❗️ WIP (Work in Progress) ❗️❗️❗️** | ||
|
||
```ts | ||
import xior from 'xior'; | ||
import xiorCachePlugin from 'xior/lib/plugins/cache'; | ||
import xiorErrorRetryPlugin from 'xior/lib/plugins/error-retry'; | ||
import xiorRepeatRequestsFilterPlugin from 'xior/lib/plugins/repeat-requests-filter'; | ||
|
||
const instance = xior.create(); | ||
|
||
instance.plugins.use(xiorCachePlugin()); | ||
instance.plugins.use(xiorErrorRetryPlugin()); | ||
instance.plugins.use(xiorAvoidRepeatRequestsPlugin()); | ||
``` | ||
|
||
## Custom plugin | ||
|
||
**❗️❗️❗️ WIP (Work in Progress) ❗️❗️❗️** | ||
|
||
```ts | ||
import xior from 'xior'; | ||
|
||
const instance = xior.create(); | ||
instance.plugins.use(async (request, response, error) => { | ||
const inRequestPhase = !response; | ||
const inResponsePhase = Boolean(response); | ||
const isError = Boolean(error); | ||
|
||
if (isError) { | ||
// | ||
} | ||
if (inRequestPhase) { | ||
// | ||
} else if (inResponsePhase) { | ||
// | ||
} | ||
}); | ||
``` | ||
|
||
## FAQ | ||
|
||
- Is `xior` 100% compatiable with `axios`? No | ||
- How to upload files? Use `FormData` | ||
- How to show upload progress like axios? Doesn't support. | ||
- What about response of `'stream' | 'document' | 'arraybuffer' | 'blob'` ? Use `responseType: 'stream' | 'document' | 'arraybuffer' | 'blob'`, will return original `{ response }` | ||
- More: Anything else? create new issues let me know! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
{ | ||
"name": "xior", | ||
"version": "0.0.3", | ||
"description": "Axios similiar API request library but based on fetch", | ||
"repository": "suhaotian/xior", | ||
"bugs": "https://github.com/suhaotian/xior/issues", | ||
"homepage": "https://github.com/suhaotian/xior", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.esm.js", | ||
"types": "./dist/types/index.d.ts", | ||
"exports": { | ||
"types": "./dist/types/index.d.ts", | ||
"require": "./dist/index.cjs", | ||
"import": "./dist/index.mjs", | ||
"module": "./dist/index.esm.js" | ||
}, | ||
"scripts": { | ||
"build": "npm run build:lib && bunchee ./src/index.ts -m", | ||
"build:lib": "rm -rf lib && tsc --project tsconfig.json", | ||
"test": "pnpm build:lib && node --test", | ||
"prepare": "is-ci || pnpm build && husky", | ||
"start-publish": "pnpm test && npm publish --registry=https://registry.npmjs.org" | ||
}, | ||
"dependencies": { | ||
"ts-deepmerge": "^7.0.0" | ||
}, | ||
"devDependencies": { | ||
"husky": "^9.0.7", | ||
"lint-staged": "^15.2.0", | ||
"prettier": "^3.2.4", | ||
"is-ci": "^3.0.1", | ||
"typescript": "^5.3.3", | ||
"@types/node": "^20.11.13", | ||
"eslint-config-universe": "^12.0.0", | ||
"@tsconfig/recommended": "^1.0.3", | ||
"@types/mime": "^3.0.4", | ||
"express": "^4.18.2", | ||
"@types/express": "^4.17.21", | ||
"axios": "^1.6.7", | ||
"multer": "^1.4.5-lts.1", | ||
"@types/multer": "^1.4.11", | ||
"qs": "^6.11.2", | ||
"@types/qs": "^6.9.11", | ||
"bunchee": "^4.4.6", | ||
"lfs-auto-track": "^1.1.0" | ||
}, | ||
"prettier": { | ||
"printWidth": 100, | ||
"tabWidth": 2, | ||
"singleQuote": true, | ||
"trailingComma": "es5", | ||
"bracketSameLine": true | ||
}, | ||
"eslintConfig": { | ||
"extends": "eslint-config-universe", | ||
"ignorePatterns": [ | ||
"node_modules" | ||
] | ||
}, | ||
"lint-staged": { | ||
"*": [ | ||
"lfs-auto-track 'image,video,audio:100kb;*:1024kb'" | ||
], | ||
"*.{ts,tsx,mts}": [ | ||
"prettier --write", | ||
"eslint --fix" | ||
], | ||
"*.{md,css,js,mjs}": [ | ||
"prettier --write" | ||
] | ||
}, | ||
"files": [ | ||
"lib", | ||
"!lib/tests", | ||
"dist" | ||
], | ||
"keywords": [ | ||
"fetch", | ||
"http", | ||
"https", | ||
"network", | ||
"axios", | ||
"axios alternatives", | ||
"url", | ||
"uri", | ||
"promise", | ||
"request", | ||
"error retry", | ||
"request cache", | ||
"repeat requests filter" | ||
], | ||
"author": "suhaotian", | ||
"license": "MIT" | ||
} |
Oops, something went wrong.