@selkirk-systems/fetch 0.1.6 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -53
- package/dist/Download.js +183 -0
- package/dist/FetchWrapper.js +389 -0
- package/dist/constants/ErrorConstants.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -88
- package/dist/middleware/FetchErrorHandler.js +37 -0
- package/dist/middleware/FetchLogger.js +29 -0
- package/lib/Download.js +175 -0
- package/lib/FetchWrapper.js +515 -0
- package/lib/constants/ErrorConstants.js +1 -0
- package/lib/index.js +3 -0
- package/lib/middleware/FetchErrorHandler.js +42 -0
- package/lib/middleware/FetchLogger.js +38 -0
- package/package.json +30 -60
- package/.jshintrc +0 -125
- package/.npmignore +0 -10
- package/LICENSE +0 -21
- package/dist/exampleTests.js +0 -27
- package/gulpfile.js +0 -11
- package/index.js +0 -1
- package/package-lock.json +0 -9422
- package/scripts/mocha_runner.js +0 -21
- package/src/__tests__/index.js +0 -61
- package/src/exampleTests.js +0 -26
- package/src/index.js +0 -91
package/dist/index.js
CHANGED
|
@@ -1,88 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var Promise = require("bluebird");
|
|
5
|
-
|
|
6
|
-
require('es6-promise').polyfill();
|
|
7
|
-
require('isomorphic-fetch');
|
|
8
|
-
|
|
9
|
-
var _networkTimer = null;
|
|
10
|
-
|
|
11
|
-
function _checkFetchStatus(response) {
|
|
12
|
-
if (response.status >= 200 && response.status < 300) {
|
|
13
|
-
return response.text().then(function (text) {
|
|
14
|
-
try {
|
|
15
|
-
return text ? JSON.parse(text) : {};
|
|
16
|
-
} catch (e) {
|
|
17
|
-
return text;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
} else {
|
|
21
|
-
var error = new Error(response.statusText);
|
|
22
|
-
return response.text().then(function (text) {
|
|
23
|
-
if (text) {
|
|
24
|
-
try {
|
|
25
|
-
error.response = JSON.parse(text);
|
|
26
|
-
} catch (e) {
|
|
27
|
-
error.response = text;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
throw error;
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function _invokeFetch(url, props) {
|
|
36
|
-
if (!url) {
|
|
37
|
-
throw new Error("fetch:Missing Parameter - URL");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var options = {
|
|
41
|
-
method: "GET",
|
|
42
|
-
credentials: 'same-origin',
|
|
43
|
-
headers: {
|
|
44
|
-
'Accept': 'application/json',
|
|
45
|
-
'Content-Type': 'application/json'
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
options = Assign(options, props);
|
|
50
|
-
|
|
51
|
-
if (_networkTimer) {
|
|
52
|
-
return new Promise(function (resolve, reject) {
|
|
53
|
-
setTimeout(resolve, _networkTimer);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (options.headers['Content-Type'] === "application/json" && options.body) options.body = JSON.stringify(options.body);
|
|
58
|
-
|
|
59
|
-
return fetch(url, options).then(_checkFetchStatus);
|
|
60
|
-
}
|
|
61
|
-
module.exports = function (dispatcher, params) {
|
|
62
|
-
if (!dispatcher) return _invokeFetch;
|
|
63
|
-
|
|
64
|
-
var options = Assign({
|
|
65
|
-
lastErrorEvent: "LAST_ERROR_EVENT",
|
|
66
|
-
errorID: null
|
|
67
|
-
}, params);
|
|
68
|
-
|
|
69
|
-
return function (url, props, responseEvent) {
|
|
70
|
-
return _invokeFetch(url, props).then(function (response) {
|
|
71
|
-
|
|
72
|
-
if (!responseEvent) return null;
|
|
73
|
-
|
|
74
|
-
dispatcher.handleViewAction({
|
|
75
|
-
actionType: responseEvent,
|
|
76
|
-
item: response
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
return response;
|
|
80
|
-
}).catch(function (err) {
|
|
81
|
-
console.error(new Error("Fetch - " + options.errorID || ""), err);
|
|
82
|
-
dispatcher.handleViewAction({
|
|
83
|
-
actionType: options.lastErrorEvent,
|
|
84
|
-
item: { error: err, id: options.errorID }
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
};
|
|
1
|
+
export { default as Download } from './Download';
|
|
2
|
+
export { default as fetch, applyMiddleware } from './FetchWrapper';
|
|
3
|
+
export { ADD_ERROR } from "./constants/ErrorConstants";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { dispatch } from "@selkirk-systems/state-management";
|
|
2
|
+
import { ADD_ERROR } from "../constants/ErrorConstants";
|
|
3
|
+
const handler = err => response => options => next => {
|
|
4
|
+
if (err) {
|
|
5
|
+
dispatch(ADD_ERROR, err);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
return next(null, response);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// NOTE: event name is all lower case as per DOM convention
|
|
12
|
+
window.addEventListener("unhandledrejection", function (e) {
|
|
13
|
+
// NOTE: e.preventDefault() must be manually called to prevent the default
|
|
14
|
+
// action which is currently to log the stack trace to console.warn
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
// NOTE: parameters are properties of the event detail property
|
|
17
|
+
var reason = e.reason || e.detail.reason;
|
|
18
|
+
//var promise = e.detail.promise;
|
|
19
|
+
// See Promise.onPossiblyUnhandledRejection for parameter documentation
|
|
20
|
+
console.groupEnd();
|
|
21
|
+
console.groupEnd();
|
|
22
|
+
console.groupEnd();
|
|
23
|
+
throw reason;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// NOTE: event name is all lower case as per DOM convention
|
|
27
|
+
window.addEventListener("rejectionhandled", function (e) {
|
|
28
|
+
// NOTE: e.preventDefault() must be manually called prevent the default
|
|
29
|
+
// action which is currently unset (but might be set to something in the future)
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
// NOTE: parameters are properties of the event detail property
|
|
32
|
+
var promise = e.reason || e.detail.promise;
|
|
33
|
+
// See Promise.onUnhandledRejectionHandled for parameter documentation
|
|
34
|
+
console.groupEnd();
|
|
35
|
+
console.log("REJECTION HANDLED", promise);
|
|
36
|
+
});
|
|
37
|
+
export default handler;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function getStatusCode(err) {
|
|
2
|
+
return err && err.response && err.response.statusCode ? err.response.statusCode : 500;
|
|
3
|
+
}
|
|
4
|
+
const FetchLogger = err => response => options => next => {
|
|
5
|
+
//Only log outputs for 'development' environment
|
|
6
|
+
if (process.env.NODE_ENV !== "development") return next(err, response);
|
|
7
|
+
const headerCSS = ['color:gray;font-weight:lighter'];
|
|
8
|
+
const bodyCSS = 'color:gray;font-weight:lighter';
|
|
9
|
+
const successCSS = 'color: green; font-weight:bold';
|
|
10
|
+
const errorCSS = 'color:red;font-weight:bold';
|
|
11
|
+
const responseCSS = 'color:#87A7DB;font-weight:bold';
|
|
12
|
+
const paramsCSS = 'color:orange;font-weight:bold';
|
|
13
|
+
if (err) {
|
|
14
|
+
headerCSS.push(errorCSS);
|
|
15
|
+
headerCSS.push(bodyCSS);
|
|
16
|
+
console.groupCollapsed(`%cfetch %cFAIL (${getStatusCode(err)}) %c${options.url}`, ...headerCSS);
|
|
17
|
+
console.log("error", err.response);
|
|
18
|
+
} else {
|
|
19
|
+
headerCSS.push(successCSS);
|
|
20
|
+
headerCSS.push(bodyCSS);
|
|
21
|
+
console.groupCollapsed(`%cfetch %cSUCCESS %c${options.url}`, ...headerCSS);
|
|
22
|
+
console.log("%cerror", errorCSS, err);
|
|
23
|
+
}
|
|
24
|
+
console.log("%cresponse", responseCSS, response);
|
|
25
|
+
console.log("%cparams", paramsCSS, options);
|
|
26
|
+
console.groupEnd();
|
|
27
|
+
return next(err, response);
|
|
28
|
+
};
|
|
29
|
+
export default FetchLogger;
|
package/lib/Download.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
//download.js v4.21, by dandavis; 2008-2018. [MIT] see http://danml.com/download.html for tests/usage
|
|
4
|
+
// v1 landed a FF+Chrome compatible way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
|
|
5
|
+
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
|
|
6
|
+
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
|
|
7
|
+
// v4 adds AMD/UMD, commonJS, and plain browser support
|
|
8
|
+
// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
|
|
9
|
+
// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
|
|
10
|
+
// https://github.com/rndme/download
|
|
11
|
+
|
|
12
|
+
( function ( root, factory ) {
|
|
13
|
+
if ( typeof define === 'function' && define.amd ) {
|
|
14
|
+
// AMD. Register as an anonymous module.
|
|
15
|
+
define( [], factory );
|
|
16
|
+
} else if ( typeof exports === 'object' ) {
|
|
17
|
+
// Node. Does not work with strict CommonJS, but
|
|
18
|
+
// only CommonJS-like environments that support module.exports,
|
|
19
|
+
// like Node.
|
|
20
|
+
module.exports = factory();
|
|
21
|
+
} else {
|
|
22
|
+
// Browser globals (root is window)
|
|
23
|
+
root.download = factory();
|
|
24
|
+
}
|
|
25
|
+
}( this, function () {
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
return function download( data, strFileName, strMimeType ) {
|
|
29
|
+
|
|
30
|
+
var self = window, // this script is only for browsers anyway...
|
|
31
|
+
defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
|
|
32
|
+
mimeType = strMimeType || defaultMime,
|
|
33
|
+
payload = data,
|
|
34
|
+
url = !strFileName && !strMimeType && payload,
|
|
35
|
+
anchor = document.createElement( "a" ),
|
|
36
|
+
toString = function ( a ) { return String( a ); },
|
|
37
|
+
myBlob = ( self.Blob || self.MozBlob || self.WebKitBlob || toString ),
|
|
38
|
+
fileName = strFileName || "download",
|
|
39
|
+
blob,
|
|
40
|
+
reader;
|
|
41
|
+
myBlob = myBlob.call ? myBlob.bind( self ) : Blob;
|
|
42
|
+
|
|
43
|
+
if ( String( this ) === "true" ) { //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
|
|
44
|
+
payload = [payload, mimeType];
|
|
45
|
+
mimeType = payload[0];
|
|
46
|
+
payload = payload[1];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if ( url && url.length < 2048 ) { // if no filename and no mime, assume a url was passed as the only argument
|
|
51
|
+
fileName = url.split( "/" ).pop().split( "?" )[0];
|
|
52
|
+
anchor.href = url; // assign href prop to temp anchor
|
|
53
|
+
if ( anchor.href.indexOf( url ) !== -1 ) { // if the browser determines that it's a potentially valid url path:
|
|
54
|
+
var ajax = new XMLHttpRequest();
|
|
55
|
+
ajax.open( "GET", url, true );
|
|
56
|
+
ajax.responseType = 'blob';
|
|
57
|
+
ajax.onload = function ( e ) {
|
|
58
|
+
download( e.target.response, fileName, defaultMime );
|
|
59
|
+
};
|
|
60
|
+
setTimeout( function () { ajax.send(); }, 0 ); // allows setting custom ajax headers using the return:
|
|
61
|
+
return ajax;
|
|
62
|
+
} // end if valid url?
|
|
63
|
+
} // end if url?
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
//go ahead and download dataURLs right away
|
|
67
|
+
if ( /^data:([\w+-]+\/[\w+.-]+)?[,;]/.test( payload ) ) {
|
|
68
|
+
|
|
69
|
+
if ( payload.length > ( 1024 * 1024 * 1.999 ) && myBlob !== toString ) {
|
|
70
|
+
payload = dataUrlToBlob( payload );
|
|
71
|
+
mimeType = payload.type || defaultMime;
|
|
72
|
+
} else {
|
|
73
|
+
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
|
|
74
|
+
navigator.msSaveBlob( dataUrlToBlob( payload ), fileName ) :
|
|
75
|
+
saver( payload ); // everyone else can save dataURLs un-processed
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
} else {//not data url, is it a string with special needs?
|
|
79
|
+
if ( /([\x80-\xff])/.test( payload ) ) {
|
|
80
|
+
var i = 0, tempUiArr = new Uint8Array( payload.length ), mx = tempUiArr.length;
|
|
81
|
+
for ( i; i < mx; ++i ) tempUiArr[i] = payload.charCodeAt( i );
|
|
82
|
+
payload = new myBlob( [tempUiArr], { type: mimeType } );
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
blob = payload instanceof myBlob ?
|
|
86
|
+
payload :
|
|
87
|
+
new myBlob( [payload], { type: mimeType } );
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
function dataUrlToBlob( strUrl ) {
|
|
91
|
+
var parts = strUrl.split( /[:;,]/ ),
|
|
92
|
+
type = parts[1],
|
|
93
|
+
indexDecoder = strUrl.indexOf( "charset" ) > 0 ? 3 : 2,
|
|
94
|
+
decoder = parts[indexDecoder] == "base64" ? atob : decodeURIComponent,
|
|
95
|
+
binData = decoder( parts.pop() ),
|
|
96
|
+
mx = binData.length,
|
|
97
|
+
i = 0,
|
|
98
|
+
uiArr = new Uint8Array( mx );
|
|
99
|
+
|
|
100
|
+
for ( i; i < mx; ++i ) uiArr[i] = binData.charCodeAt( i );
|
|
101
|
+
|
|
102
|
+
return new myBlob( [uiArr], { type: type } );
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function saver( url, winMode ) {
|
|
106
|
+
|
|
107
|
+
if ( 'download' in anchor ) { //html5 A[download]
|
|
108
|
+
anchor.href = url;
|
|
109
|
+
anchor.setAttribute( "download", fileName );
|
|
110
|
+
anchor.className = "download-js-link";
|
|
111
|
+
anchor.innerHTML = "downloading...";
|
|
112
|
+
anchor.style.display = "none";
|
|
113
|
+
anchor.addEventListener( 'click', function ( e ) {
|
|
114
|
+
e.stopPropagation();
|
|
115
|
+
this.removeEventListener( 'click', arguments.callee );
|
|
116
|
+
} );
|
|
117
|
+
document.body.appendChild( anchor );
|
|
118
|
+
setTimeout( function () {
|
|
119
|
+
anchor.click();
|
|
120
|
+
document.body.removeChild( anchor );
|
|
121
|
+
if ( winMode === true ) { setTimeout( function () { self.URL.revokeObjectURL( anchor.href ); }, 250 ); }
|
|
122
|
+
}, 66 );
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// handle non-a[download] safari as best we can:
|
|
127
|
+
if ( /(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test( navigator.userAgent ) ) {
|
|
128
|
+
if ( /^data:/.test( url ) ) url = "data:" + url.replace( /^data:([\w\/\-\+]+)/, defaultMime );
|
|
129
|
+
if ( !window.open( url ) ) { // popup blocked, offer direct download:
|
|
130
|
+
if ( confirm( "Displaying New Document\n\nUse Save As... to download, then click back to return to this page." ) ) { location.href = url; }
|
|
131
|
+
}
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
//do iframe dataURL download (old ch+FF):
|
|
136
|
+
var f = document.createElement( "iframe" );
|
|
137
|
+
document.body.appendChild( f );
|
|
138
|
+
|
|
139
|
+
if ( !winMode && /^data:/.test( url ) ) { // force a mime that will download:
|
|
140
|
+
url = "data:" + url.replace( /^data:([\w\/\-\+]+)/, defaultMime );
|
|
141
|
+
}
|
|
142
|
+
f.src = url;
|
|
143
|
+
setTimeout( function () { document.body.removeChild( f ); }, 333 );
|
|
144
|
+
|
|
145
|
+
}//end saver
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
if ( navigator.msSaveBlob ) { // IE10+ : (has Blob, but not a[download] or URL)
|
|
151
|
+
return navigator.msSaveBlob( blob, fileName );
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if ( self.URL ) { // simple fast and modern way using Blob and URL:
|
|
155
|
+
saver( self.URL.createObjectURL( blob ), true );
|
|
156
|
+
} else {
|
|
157
|
+
// handle non-Blob()+non-URL browsers:
|
|
158
|
+
if ( typeof blob === "string" || blob.constructor === toString ) {
|
|
159
|
+
try {
|
|
160
|
+
return saver( "data:" + mimeType + ";base64," + self.btoa( blob ) );
|
|
161
|
+
} catch ( y ) {
|
|
162
|
+
return saver( "data:" + mimeType + "," + encodeURIComponent( blob ) );
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Blob but not URL support:
|
|
167
|
+
reader = new FileReader();
|
|
168
|
+
reader.onload = function ( e ) {
|
|
169
|
+
saver( this.result );
|
|
170
|
+
};
|
|
171
|
+
reader.readAsDataURL( blob );
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}; /* end download() */
|
|
175
|
+
} ) );
|