Skip to content

Commit dda16d4

Browse files
committed
make it actually work, add tests;
1 parent b8ff328 commit dda16d4

File tree

9 files changed

+274
-255
lines changed

9 files changed

+274
-255
lines changed

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
root = true
2+
3+
[*]
4+
indent_style = tab
5+
end_of_line = lf
6+
charset = utf-8
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
10+
[{*.json,*.md,.*rc,*.yml,*.txt}]
11+
indent_style = space
12+
indent_size = 2
13+
insert_final_newline = false

.gitignore

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
/node_modules
2-
/package-lock.json
3-
/preact
4-
/babel
5-
/dist
1+
node_modules
2+
package-lock.json
3+
dist
4+
coverage

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# axios-shim
1+
# redaxios
22

33
The axios API, as a thin 800-byte wrapper around fetch().

package.json

Lines changed: 16 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,38 @@
11
{
2-
"name": "axios-shim",
2+
"name": "redaxios",
33
"version": "0.1.0",
44
"description": "The API from Axios, as a tiny abstraction over Fetch.",
55
"source": "src/index.mjs",
6-
"main": "dist/axios-shim.js",
7-
"umd:main": "dist/axios-shim.js",
8-
"module": "dist/axios-shim.mjs",
6+
"main": "dist/redaxios.js",
7+
"umd:main": "dist/redaxios.js",
8+
"module": "dist/redaxios.mjs",
99
"scripts": {
1010
"build": "microbundle",
11-
"test": "eslint \"{src,test}/**/*.{mjs,js}\" && jest"
11+
"test": "eslint \"{src,test}/**/*.{mjs,js}\" && karmatic"
1212
},
1313
"files": [
1414
"dist",
1515
"src"
1616
],
17-
"jest": {
18-
"verbose": true,
19-
"testURL": "http://localhost/",
20-
"testMatch": [
21-
"**/__tests__/**/*.?(m)js?(x)",
22-
"**/?(*.)(spec|test).?(m)js?(x)"
23-
],
24-
"moduleFileExtensions": [
25-
"mjs",
26-
"js",
27-
"json"
28-
],
29-
"transform": {
30-
"^.+\\.m?jsx?$": "babel-jest"
31-
},
32-
"watchPathIgnorePatterns": [
33-
"<rootDir>/node_modules/",
34-
"<rootDir>/test/fixtures/.*?/dist/"
35-
]
36-
},
37-
"babel": {
38-
"plugins": [
39-
"transform-es2015-modules-commonjs"
40-
]
41-
},
4217
"eslintConfig": {
43-
"extends": "google",
44-
"parserOptions": {
45-
"ecmaVersion": "8",
46-
"sourceType": "module"
47-
},
48-
"rules": {
49-
"guard-for-in": 0,
50-
"require-jsdoc": 0,
51-
"max-len": [
52-
1,
53-
120
54-
]
55-
}
18+
"extends": "developit"
5619
},
57-
"repository": "GoogleChromeLabs/axios-shim",
20+
"repository": "developit/redaxios",
5821
"keywords": [
5922
"axios",
6023
"fetch"
6124
],
6225
"author": "Jason Miller <[email protected]>",
6326
"license": "Apache-2.0",
64-
"homepage": "https://github.com/GoogleChromeLabs/axios-shim",
27+
"homepage": "https://github.com/developit/redaxios",
6528
"devDependencies": {
66-
"babel-jest": "^23.4.2",
67-
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
68-
"eslint": "^5.2.0",
69-
"eslint-config-google": "^0.9.1",
70-
"jest": "^23.4.2",
71-
"microbundle": "^0.6.0"
29+
"eslint": "^6.8.0",
30+
"eslint-config-developit": "^1.1.1",
31+
"file-loader": "^5.0.2",
32+
"jest": "^24.9.0",
33+
"karmatic": "^1.4.0",
34+
"microbundle": "^0.11.0",
35+
"sinon": "^8.0.4",
36+
"webpack": "^4.41.5"
7237
}
7338
}

src/index.js

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/**
2+
* Copyright 2018 Google Inc. All Rights Reserved.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
14+
/**
15+
* @typedef Options
16+
* @property {string} [url] the URL to request
17+
* @property {string} [method="get"] HTTP method, case-insensitive
18+
* @property {Headers} [headers] Request headers
19+
* @property {'text'|'json'|'stream'|'blob'|'arrayBuffer'|'formData'|'stream'} [responseType="text"] An encoding to use for the response
20+
* @property {string} [auth] Authorization header value to send with the request
21+
* @property {string} [xsrfCookieName] Pass an Cross-site Request Forgery prevention cookie value as a header defined by `xsrfHeaderName`
22+
* @property {string} [xsrfHeaderName] The name of a header to use for passing XSRF cookies
23+
* @property {(status: number) => boolean} [validateStatus] Override status code handling (default: 200-399 is a success)
24+
* @property {Array<(body: any, headers: Headers) => any?>} [transformRequest] An array of transformations to apply to the outgoing request
25+
*/
26+
27+
/**
28+
* @typedef Headers
29+
* @type {{[name: string]: string}}
30+
*/
31+
32+
/**
33+
* @typedef Response
34+
* @property {Options} config the resolved request configuration
35+
* @property {FormData|string|object} [body] a body, optionally encoded, to send
36+
*/
37+
38+
export default (function create(defaults) {
39+
defaults = defaults || {};
40+
41+
/**
42+
* Creates a request factory bound to the given HTTP method.
43+
* @param {string} method
44+
* @param {boolean} allowBody
45+
* @returns {(url: string, config?: Options, body?) => Promise<Response>}
46+
*/
47+
function createMethod(method, allowBody) {
48+
return (url, config, alt) => {
49+
let data;
50+
if (allowBody) {
51+
data = config;
52+
config = alt;
53+
}
54+
config = Object.assign({ method }, config);
55+
return axios(url, data, config);
56+
};
57+
}
58+
59+
axios.request = axios;
60+
axios.get = createMethod('get', false);
61+
axios.delete = createMethod('delete', false);
62+
axios.options = createMethod('options', false);
63+
axios.post = createMethod('post', true);
64+
axios.put = createMethod('put', true);
65+
axios.patch = createMethod('patch', true);
66+
67+
function deepMerge(opts, overrides, lowerCase) {
68+
if (Array.isArray(opts)) {
69+
return opts.concat(overrides);
70+
}
71+
if (overrides && typeof overrides == 'object') {
72+
let out = {}, i;
73+
if (opts) {
74+
for (i in opts) {
75+
let key = lowerCase ? i.toLowerCase() : i;
76+
out[key] = opts[i];
77+
}
78+
}
79+
for (i in overrides) {
80+
let key = lowerCase ? i.toLowerCase() : i;
81+
if (key === 'headers') lowerCase = true;
82+
if (i in out) {
83+
out[key] = deepMerge(out[key], overrides[i], lowerCase);
84+
}
85+
else {
86+
out[key] = overrides[i];
87+
}
88+
}
89+
return out;
90+
}
91+
return overrides;
92+
}
93+
94+
function isOk(status) {
95+
return (status/100|0) === 2;
96+
}
97+
98+
/**
99+
* Issues a request.
100+
* @param {string} url the URL to fetch
101+
* @param {any} [data] request body to send
102+
* @param {Options} [config] configuration for the request
103+
* @returns {Promise<Response>}
104+
*/
105+
function axios(url, data, config) {
106+
let options = config;
107+
if (typeof url !== 'string') {
108+
options = url;
109+
url = options.url;
110+
}
111+
else if (config === undefined) {
112+
options = data;
113+
data = undefined;
114+
}
115+
options = deepMerge(defaults, options) || {};
116+
117+
if (options.transformRequest) {
118+
for (let i = 0; i < options.transformRequest.length; i++) {
119+
let r = options.transformRequest[i](data, options.headers);
120+
if (r !== undefined) {
121+
data = r;
122+
}
123+
}
124+
}
125+
126+
const customHeaders = {};
127+
128+
if (data && typeof data === 'object') {
129+
data = JSON.stringify(data);
130+
customHeaders['Content-Type'] = 'application/json';
131+
}
132+
133+
if (options.xsrfCookieName) {
134+
let parts = document.cookie.split(/ *[;=] */);
135+
for (let i = 0; i < parts.length; i += 2) {
136+
if (parts[i] == options.xsrfCookieName) {
137+
customHeaders[options.xsrfHeaderName] = decodeURIComponent(parts[i+1]);
138+
break;
139+
}
140+
}
141+
}
142+
143+
if (options.auth) {
144+
customHeaders.Authorization = options.auth;
145+
}
146+
147+
const response = {
148+
config
149+
};
150+
return fetch(url, {
151+
method: options.method,
152+
body: data,
153+
headers: deepMerge(options.headers, customHeaders, true)
154+
}).then((res) => {
155+
let i;
156+
for (i in res) {
157+
if (typeof res[i] != 'function') response[i] = res[i];
158+
}
159+
if (!(options.validateStatus || isOk)(res.status)) {
160+
return Promise.reject(res);
161+
}
162+
const withData = options.responseType === 'stream'
163+
? Promise.resolve(res.body)
164+
: res[options.responseType || 'text']();
165+
return withData.then((data) => {
166+
response.data = data;
167+
return response;
168+
});
169+
});
170+
}
171+
172+
axios.CancelToken = self.AbortController || Object;
173+
174+
return axios;
175+
})();

0 commit comments

Comments
 (0)