@cerebral/http
Advanced tools
Comparing version 5.0.0-1514099265786 to 5.0.0-1519463520217
import { Provider } from "function-tree" | ||
export enum HttpProviderErrorTypes {Http = 'http', Abort = 'abort', Timeout = 'timeout'} | ||
export class HttpProviderError extends Error { | ||
constructor (status: number, headers: any, body: any, message?: string, isAborted?: boolean) | ||
constructor (type: HttpProviderErrorTypes, status: number, headers: any, body: any, message?: string, isAborted?: boolean) | ||
type: HttpProviderErrorTypes | ||
response: { | ||
@@ -14,2 +17,62 @@ status: number, | ||
export default function HttpProvider(options: any): Provider | ||
export default function HttpProvider(moduleOptions: HttpModuleOptions): HttpProvider; | ||
export interface HttpModuleOptions { | ||
method?: string, | ||
baseUrl?: string, | ||
headers?: { [id: string]: string }, | ||
onRequest?: (xhr: XMLHttpRequest, options: HttpResponseOptions) => void; | ||
onResponse?: (response: XMLHttpRequest, resolve: Function, reject: Function, options?: HttpResponseOptions) => void; | ||
onRequestCallback?: (xhr: XMLHttpRequest) => void; | ||
onResponseCallback?: (response: XMLHttpRequest) => void; | ||
} | ||
export interface HttpRequestOptions { | ||
query?: { [id: string]: any }, | ||
headers?: { [id: string]: string }, | ||
} | ||
export interface HttpResponseOptions extends HttpRequestOptions, HttpModuleOptions { | ||
body: string | ||
} | ||
export interface HttpRequestReponse<T> { | ||
result: T, | ||
status: string | ||
} | ||
export interface HttpProvider { | ||
request: any, | ||
get<T>(url: string, passedQuery?: { [id: string]: any }, options?: HttpRequestOptions): Promise<HttpRequestReponse<T>>, | ||
post<T>(url: string, body: any, options?: HttpRequestOptions): Promise<HttpRequestReponse<T>>, | ||
put<T>(url: string, body: any, options?: HttpRequestOptions): Promise<HttpRequestReponse<T>>, | ||
patch<T>(url: string, body: any, options?: HttpRequestOptions): Promise<HttpRequestReponse<T>>, | ||
delete<T>(url: string, passedQuery: { [id: string]: any }, options?: HttpRequestOptions): Promise<HttpRequestReponse<T>>, | ||
uploadFile<T>(url: string, files: FileList | File, options?: FileUploadOptions): FileUpload<T>, | ||
updateOptions(newOptions: HttpModuleOptions): void; | ||
abort(regexp: string): boolean; | ||
} | ||
export interface FileUploadProgress { | ||
progress: number | ||
} | ||
export interface FileUploadOptions { | ||
name?: string, | ||
data?: { [id: string]: any }, | ||
headers?: { [id: string]: string }, | ||
onProgress?: (progress: FileUploadProgress) => void | string | ||
} | ||
export interface FileUploadResult<T> { | ||
result?: T, | ||
status: string | ||
} | ||
export class FileUpload<TResponse> { | ||
constructor(options: FileUploadOptions); | ||
xhr: XMLHttpRequest; | ||
isAborted: boolean; | ||
send: (files: FileList | File[]) => Promise<FileUploadResult<TResponse>>; | ||
abort: () => void; | ||
} |
@@ -29,2 +29,6 @@ 'use strict'; | ||
if (typeof window !== 'undefined' && window.FormData && options.body instanceof window.FormData) { | ||
delete options.headers['Content-Type']; | ||
} | ||
xhr.withCredentials = Boolean(options.withCredentials); | ||
@@ -36,5 +40,9 @@ | ||
if (options.onRequestCallback) { | ||
options.onRequestCallback(xhr); | ||
} | ||
xhr.send(options.body); | ||
}, | ||
onResponse: function onResponse(xhr, resolve, reject) { | ||
onResponse: function onResponse(xhr, resolve, reject, options) { | ||
var result = xhr.responseText; | ||
@@ -48,2 +56,6 @@ | ||
if (options && options.onRequestCallback) { | ||
options.onResponseCallback(xhr); | ||
} | ||
if (xhr.status >= 200 && xhr.status < 300) { | ||
@@ -53,7 +65,6 @@ resolve({ | ||
headers: responseHeaders, | ||
result: result, | ||
isAborted: false | ||
result: result | ||
}); | ||
} else { | ||
reject(new _HttpProviderError2.default(xhr.status, responseHeaders, result, xhr.responseText)); | ||
reject(new _HttpProviderError2.default(undefined, xhr.status, responseHeaders, result, xhr.responseText)); | ||
} | ||
@@ -60,0 +71,0 @@ } |
@@ -40,8 +40,10 @@ 'use strict'; | ||
var _warnAboutDeprecatedIsAborted = false; | ||
var HttpProviderError = function (_extendableBuiltin2) { | ||
_inherits(HttpProviderError, _extendableBuiltin2); | ||
function HttpProviderError(status, headers, result) { | ||
var message = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var isAborted = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; | ||
function HttpProviderError(type, status, headers, result) { | ||
var message = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; | ||
var isAborted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; | ||
@@ -54,8 +56,18 @@ _classCallCheck(this, HttpProviderError); | ||
_this.message = message; | ||
_this.type = type || 'http'; | ||
_this.response = { | ||
status: status, | ||
headers: headers, | ||
result: result, | ||
isAborted: isAborted | ||
result: result | ||
}; | ||
Object.defineProperty(_this.response, 'isAborted', { | ||
get: function get() { | ||
if (!_warnAboutDeprecatedIsAborted) { | ||
console.warn('DEPRECATED - Please use error.type === "abort" instead'); | ||
_warnAboutDeprecatedIsAborted = true; | ||
} | ||
return isAborted; | ||
} | ||
}); | ||
return _this; | ||
@@ -68,2 +80,3 @@ } | ||
return { | ||
type: this.type, | ||
name: this.name, | ||
@@ -70,0 +83,0 @@ message: this.message, |
@@ -9,4 +9,8 @@ 'use strict'; | ||
function request(options, cb) { | ||
function request() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var cb = arguments[1]; | ||
var xhr = new XMLHttpRequest(); | ||
xhr.addEventListener('progress', cb); | ||
@@ -16,2 +20,13 @@ xhr.addEventListener('load', cb); | ||
xhr.addEventListener('abort', cb); | ||
xhr.ontimeout = function () { | ||
var ev = { | ||
type: 'timeout', | ||
currentTarget: xhr | ||
}; | ||
cb(ev); | ||
}; | ||
xhr.timeout = options.timeout || 0; | ||
xhr.open(options.method, options.baseUrl + options.url); | ||
@@ -18,0 +33,0 @@ options.onRequest(xhr, options); |
@@ -26,7 +26,7 @@ 'use strict'; | ||
case 'load': | ||
return options.onResponse(event.currentTarget, resolve, reject); | ||
return options.onResponse(event.currentTarget, resolve, reject, options); | ||
case 'progress': | ||
if (options.onProgress && event.lengthComputable) { | ||
options.onProgress({ | ||
progress: Number(event.loaded / event.total).toFixed(0) | ||
progress: Number(event.loaded / event.total * 100).toFixed() | ||
}); | ||
@@ -36,7 +36,10 @@ } | ||
case 'error': | ||
reject(new _HttpProviderError2.default(event.currentTarget.status, getAllResponseHeaders(event.currentTarget), event.currentTarget.responseText, event.currentTarget.responseText || 'request error')); | ||
reject(new _HttpProviderError2.default(undefined, event.currentTarget.status, getAllResponseHeaders(event.currentTarget), event.currentTarget.responseText, event.currentTarget.responseText || 'request error')); | ||
break; | ||
case 'abort': | ||
reject(new _HttpProviderError2.default(event.currentTarget.status, getAllResponseHeaders(event.currentTarget), null, 'request abort', true)); | ||
reject(new _HttpProviderError2.default(event.type, event.currentTarget.status, getAllResponseHeaders(event.currentTarget), null, 'request abort', true)); | ||
break; | ||
case 'timeout': | ||
reject(new _HttpProviderError2.default(event.type, event.currentTarget.status, getAllResponseHeaders(event.currentTarget), null, 'request timeout')); | ||
break; | ||
} | ||
@@ -105,6 +108,10 @@ }; | ||
if (error.isAborted && path.abort) { | ||
if (error.type === 'abort' && path.abort) { | ||
return path.abort({ error: error.toJSON() }); | ||
} | ||
if (error.type === 'timeout' && path.timeout) { | ||
return path.timeout({ error: error.toJSON() }); | ||
} | ||
if (path[error.response.status]) { | ||
@@ -111,0 +118,0 @@ return path[error.response.status]({ error: error.toJSON() }); |
{ | ||
"name": "@cerebral/http", | ||
"version": "5.0.0-1514099265786", | ||
"version": "5.0.0-1519463520217", | ||
"description": "HTTP provider for Cerebral 2", | ||
@@ -27,8 +27,8 @@ "main": "lib/index.js", | ||
"peerDependencies": { | ||
"cerebral": "^5.0.0-1514099265786" | ||
"cerebral": "^5.0.0-1519463520217" | ||
}, | ||
"devDependencies": { | ||
"cerebral": "^5.0.0-1514099265786", | ||
"xhr-mock": "^1.9.0" | ||
"cerebral": "^5.0.0-1519463520217", | ||
"xhr-mock": "^2.1.0" | ||
} | ||
} |
@@ -29,23 +29,31 @@ # @cerebral/http | ||
```js | ||
import {Controller} from 'cerebral' | ||
import {Controller, Module} from 'cerebral' | ||
import HttpProvider from '@cerebral/http' | ||
const controller = Controller({ | ||
providers: [ | ||
HttpProvider({ | ||
// Prefix all requests with this url | ||
baseUrl: 'https://api.github.com', | ||
const http = HttpProvider({ | ||
// Prefix all requests with this url | ||
baseUrl: 'https://api.github.com', | ||
// Any default headers to pass on requests | ||
headers: { | ||
'Content-Type': 'application/json; charset=UTF-8', | ||
'Accept': 'application/json' | ||
}, | ||
// Any default headers to pass on requests | ||
headers: { | ||
'Content-Type': 'application/json; charset=UTF-8', | ||
'Accept': 'application/json' | ||
}, | ||
// When talking to cross origin (cors), pass cookies | ||
// if set to true | ||
withCredentials: false | ||
}) | ||
] | ||
// When talking to cross origin (cors), pass cookies | ||
// if set to true | ||
withCredentials: false, | ||
// Provide a global request timeout for all calls | ||
// which can be overwritten for request by providing | ||
// a different timeout when doing a request | ||
// in actions or operators | ||
timeout: 5000 | ||
}) | ||
const app = Module({ | ||
providers: { http } | ||
}) | ||
const controller = Controller(app) | ||
``` | ||
@@ -64,3 +72,3 @@ | ||
## abort | ||
You can abort any running request, causing the request to resolve as status code **0** and set an **isAborted** property on the response object. | ||
You can abort any running request, causing the request to resolve as status code **0** and sets the type to **abort** on the error object. | ||
@@ -73,3 +81,3 @@ ```js | ||
.catch((error) => { | ||
if (error.isAborted) { | ||
if (error.type === 'abort') { | ||
return path.abort() | ||
@@ -112,2 +120,3 @@ } | ||
name: 'HttpProviderError', | ||
type: 'http | abort | timeout', | ||
message: 'Some error message or responseText', | ||
@@ -117,4 +126,3 @@ response: { | ||
headers: {}, | ||
status: 200, | ||
isAborted: false | ||
status: 200 | ||
}, | ||
@@ -148,3 +156,3 @@ stack: '...' | ||
- To signal/global catch handlers | ||
- To module catch handlers | ||
@@ -157,6 +165,6 @@ ```js | ||
Controller({ | ||
catch: new Map([ | ||
Module({ | ||
catch: [ | ||
[HttpProviderError, errorCatched] | ||
]) | ||
] | ||
}) | ||
@@ -214,2 +222,5 @@ ``` | ||
], | ||
timeout: [ | ||
/* PROPS: {error: {...}} */ | ||
], | ||
@@ -273,2 +284,5 @@ // Optionally any status code, ex. 404: [] | ||
], | ||
timeout: [ | ||
/* PROPS: {error: {...}} */ | ||
], | ||
@@ -332,2 +346,5 @@ // Optionally any status code, ex. 404: [] | ||
], | ||
timeout: [ | ||
/* PROPS: {error: {...}} */ | ||
], | ||
@@ -397,2 +414,5 @@ // Optionally any status code, ex. 404: [] | ||
], | ||
timeout: [ | ||
/* PROPS: {error: {...}} */ | ||
], | ||
@@ -458,2 +478,5 @@ // Optionally any status code, ex. 404: [] | ||
], | ||
timeout: [ | ||
/* PROPS: {error: {...}} */ | ||
], | ||
@@ -476,4 +499,3 @@ // Optionally any status code, ex. 404: [] | ||
headers: {...}, | ||
status: 200, | ||
isAborted: false | ||
status: 200 | ||
} | ||
@@ -486,6 +508,6 @@ ``` | ||
name: 'HttpProviderError', | ||
type: 'http | abort | timeout', | ||
message: 'Some potential error message', | ||
result: 'Message or response body', | ||
status: 500, | ||
isAborted: false, | ||
headers: {}, | ||
@@ -492,0 +514,0 @@ stack: '...' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
76948
693
598