random-transactions-sdk 0.0.0-stage → 0.3.0

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/.min-wd ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "hostname": "localhost",
3
+ "port": 4444,
4
+ "browsers": [{
5
+ "name": "firefox",
6
+ "url": "http://localhost:8080/test"
7
+ }, {
8
+ "name": "phantomjs",
9
+ "url": "http://localhost:8080/test"
10
+ }]
11
+ }
package/.travis.yml ADDED
@@ -0,0 +1,27 @@
1
+ sudo: false
2
+ language: node_js
3
+ matrix:
4
+ fast_finish: true
5
+ include:
6
+ - node_js: "4"
7
+ env: TASK=test-node
8
+ - node_js: "3"
9
+ env: TASK=test-node
10
+ - node_js: "2"
11
+ env: TASK=test-node
12
+ - node_js: "1"
13
+ env: TASK=test-node
14
+ - node_js: "0.12"
15
+ env: TASK=test-node
16
+ - node_js: "0.10"
17
+ env: TASK=test-node
18
+ script:
19
+ - "npm run ${TASK}"
20
+ after_script:
21
+ - 'if [ "${TASK}" == "test-node" ]; then npm i coveralls@2 && cat coverage/lcov.info | coveralls; fi'
22
+ notifications:
23
+ irc:
24
+ channels:
25
+ - "irc.freenode.org#unshift"
26
+ on_success: change
27
+ on_failure: change
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,3 +1,106 @@
1
- # Temporary Holding Version
1
+ # requests
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![Made by unshift][made-by]](http://unshift.io)[![Version npm][version]](http://browsenpm.org/package/requests)[![Build Status][build]](https://travis-ci.org/unshiftio/requests)[![Dependencies][david]](https://david-dm.org/unshiftio/requests)[![Coverage Status][cover]](https://coveralls.io/r/unshiftio/requests?branch=master)[![IRC channel][irc]](http://webchat.freenode.net/?channels=unshift)
4
+
5
+ [made-by]: https://img.shields.io/badge/made%20by-unshift-00ffcc.svg?style=flat-square
6
+ [version]: https://img.shields.io/npm/v/requests.svg?style=flat-square
7
+ [build]: https://img.shields.io/travis/unshiftio/requests/master.svg?style=flat-square
8
+ [david]: https://img.shields.io/david/unshiftio/requests.svg?style=flat-square
9
+ [cover]: https://img.shields.io/coveralls/unshiftio/requests/master.svg?style=flat-square
10
+ [irc]: https://img.shields.io/badge/IRC-irc.freenode.net%23unshift-00a8ff.svg?style=flat-square
11
+
12
+ Requests is a small library that implements fully and true streaming XHR for
13
+ browsers that support these methods. It uses a variety of proprietary
14
+ `responseType` properties to force a streaming connection, even for binary data.
15
+ For browsers that don't support this we will simply fallback to a regular but
16
+ **async** XHR 1/2 request or ActiveXObject in even older deprecated browsers.
17
+
18
+ - Internet Explorer >= 10: `ms-stream`
19
+ - FireFox >= 9: `moz-chunked`
20
+ - FireFox < 20: `multipart`
21
+
22
+ This module comes with build-in protection against ActiveX blocking that is
23
+ frequently used in firewalls & virus scanners.
24
+
25
+ ## Installation
26
+
27
+ The module is released in the public npm registry and can be installed using:
28
+
29
+ ```
30
+ npm install --save requests
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ The API is a mix between the Fetch API, mixed with EventEmitter API for the
36
+ event handling.
37
+
38
+ ```js
39
+ 'use strict';
40
+
41
+ var requests = require('requests');
42
+ ```
43
+
44
+ Now that we've included the library we can start making requests. The exported
45
+ method accepts 2 arguments:
46
+
47
+ - **url** Required URL that you want to have requested.
48
+ - **options** Optional object with additional configuration options:
49
+ - **streaming** Should we use streaming API's to fetch the data, defaults to
50
+ `false`.
51
+ - **method** The HTTP method that should be used to get the contents, defaults
52
+ to `GET`.
53
+ - **mode** The request mode, defaults to `cors`
54
+ - **headers** Object with header name/value that we need to send to the server.
55
+ - **timeout** The timeout in ms before we should abort the request.
56
+ - **manual** Manually `open` the request, defaults to `false`.
57
+
58
+ ```js
59
+ requests('https://google.com/foo/bar', { streaming })
60
+ .on('data', function (chunk) {
61
+ console.log(chunk)
62
+ })
63
+ .on('end', function (err) {
64
+ if (err) return console.log('connection closed due to errors', err);
65
+
66
+ console.log('end');
67
+ });
68
+ ```
69
+
70
+ ## Events
71
+
72
+ In the example above you can see the that we're listing to various of events.
73
+ The following events are emitted:
74
+
75
+ - `data` A new chunk of data has been received. It can be a small chunk but also
76
+ the full response depending on the environment it's loaded in.
77
+ - `destroy` The request instance has been fully destroyed.
78
+ - `error` An error occurred while requesting the given URL.
79
+ - `end` Done with requesting the URL. An error argument can be supplied if the
80
+ connection was closed due to an error.
81
+ - `before` Emitted before we send the actual request.
82
+ - `send` Emitted after we've succesfully started the sending of the data.
83
+
84
+ ### requests#destroy
85
+
86
+ Destroy the running XHR request and release all the references that the
87
+ `requests` instance holds. It returns a boolean as indication of a successful
88
+ destruction.
89
+
90
+ ```js
91
+ requests.destroy();
92
+ ```
93
+
94
+ ### Requests.requested
95
+
96
+ The total amount of requests that we've made in this library. It also serves as
97
+ unique id for each request that we store in `.active`.
98
+
99
+ ### Requests.active
100
+
101
+ An object that contains all running and active requests. Namespaced under
102
+ `request.requested` id and the requests instance.
103
+
104
+ ## License
105
+
106
+ MIT
package/index.js ADDED
@@ -0,0 +1,324 @@
1
+ 'use strict';
2
+
3
+ var Requested = require('./requested')
4
+ , listeners = require('loads')
5
+ , send = require('xhr-send')
6
+ , hang = require('hang')
7
+ , AXO = require('axo')
8
+ , XMLHttpRequest = require('node-http-xhr');
9
+
10
+ /**
11
+ * RequestS(tream).
12
+ *
13
+ * Options:
14
+ *
15
+ * - streaming: Should the request be streaming.
16
+ * - method: Which HTTP method should be used.
17
+ * - headers: Additional request headers.
18
+ * - mode: Enable CORS mode.
19
+ * - body: The payload for the request.
20
+ *
21
+ * @constructor
22
+ * @param {String} url The URL we want to request.
23
+ * @param {Object} options Various of request options.
24
+ * @api public
25
+ */
26
+ var Requests = module.exports = Requested.extend({
27
+ constructor: function bobthebuilder(url, options) {
28
+ if (!(this instanceof Requests)) return new Requests(url, options);
29
+
30
+ Requested.apply(this, arguments);
31
+ },
32
+
33
+ /**
34
+ * The offset of data that we've already previously read
35
+ *
36
+ * @type {Number}
37
+ * @private
38
+ */
39
+ offset: 0,
40
+
41
+ /**
42
+ * The requests instance has been fully initialized.
43
+ *
44
+ * @param {String} url The URL we need to connect to.
45
+ * @api private
46
+ */
47
+ initialize: function initialize(url) {
48
+ this.socket = Requests[Requests.method](this);
49
+
50
+ //
51
+ // Open the socket BEFORE adding any properties to the instance as this might
52
+ // trigger a thrown `InvalidStateError: An attempt was made to use an object
53
+ // that is not, or is no longer, usable` error in FireFox:
54
+ //
55
+ // @see https://bugzilla.mozilla.org/show_bug.cgi?id=707484
56
+ //
57
+ this.socket.open(this.method.toUpperCase(), url, true);
58
+
59
+ //
60
+ // Register this as an active HTTP request.
61
+ //
62
+ Requests.active[this.id] = this;
63
+ },
64
+
65
+ /**
66
+ * Initialize and start requesting the supplied resource.
67
+ *
68
+ * @param {Object} options Passed in defaults.
69
+ * @api private
70
+ */
71
+ open: function open() {
72
+ var what
73
+ , slice = true
74
+ , requests = this
75
+ , socket = requests.socket;
76
+
77
+ requests.on('stream', function stream(data) {
78
+ if (!slice) {
79
+ return requests.emit('data', data);
80
+ }
81
+
82
+ //
83
+ // Please note that we need to use a method here that works on both string
84
+ // as well as ArrayBuffer's as we have no certainty that we're receiving
85
+ // text.
86
+ //
87
+ var chunk = data.slice(requests.offset);
88
+ requests.offset = data.length;
89
+
90
+ requests.emit('data', chunk);
91
+ });
92
+
93
+ requests.on('end', function cleanup() {
94
+ delete Requests.active[requests.id];
95
+ });
96
+
97
+ if (this.timeout) {
98
+ socket.timeout = +this.timeout;
99
+ }
100
+
101
+ if ('cors' === this.mode.toLowerCase() && 'withCredentials' in socket) {
102
+ socket.withCredentials = true;
103
+ }
104
+
105
+ //
106
+ // ActiveXObject will throw an `Type Mismatch` exception when setting the to
107
+ // an null-value and to be consistent with all XHR implementations we're going
108
+ // to cast the value to a string.
109
+ //
110
+ // While we don't technically support the XDomainRequest of IE, we do want to
111
+ // double check that the setRequestHeader is available before adding headers.
112
+ //
113
+ // Chrome has a bug where it will actually append values to the header instead
114
+ // of overriding it. So if you do a double setRequestHeader(Content-Type) with
115
+ // text/plain and with text/plain again, it will end up as `text/plain,
116
+ // text/plain` as header value. This is why use a headers object as it
117
+ // already eliminates duplicate headers.
118
+ //
119
+ for (what in this.headers) {
120
+ if (this.headers[what] !== undefined && this.socket.setRequestHeader) {
121
+ this.socket.setRequestHeader(what, this.headers[what] +'');
122
+ }
123
+ }
124
+
125
+ //
126
+ // Set the correct responseType method.
127
+ //
128
+ if (requests.streaming) {
129
+ if (!this.body || 'string' === typeof this.body) {
130
+ if ('multipart' in socket) {
131
+ socket.multipart = true;
132
+ slice = false;
133
+ } else if (Requests.type.mozchunkedtext) {
134
+ socket.responseType = 'moz-chunked-text';
135
+ slice = false;
136
+ }
137
+ } else {
138
+ if (Requests.type.mozchunkedarraybuffer) {
139
+ socket.responseType = 'moz-chunked-arraybuffer';
140
+ } else if (Requests.type.msstream) {
141
+ socket.responseType = 'ms-stream';
142
+ }
143
+ }
144
+ }
145
+
146
+ listeners(socket, requests, requests.streaming);
147
+ requests.emit('before', socket);
148
+
149
+ send(socket, this.body, hang(function send(err) {
150
+ if (err) {
151
+ requests.emit('error', err);
152
+ requests.emit('end', err);
153
+ }
154
+
155
+ requests.emit('send');
156
+ }));
157
+ },
158
+
159
+ /**
160
+ * Completely destroy the running XHR and release of the internal references.
161
+ *
162
+ * @returns {Boolean} Successful destruction
163
+ * @api public
164
+ */
165
+ destroy: function destroy() {
166
+ if (!this.socket) return false;
167
+
168
+ this.emit('destroy');
169
+
170
+ this.socket.abort();
171
+ this.removeAllListeners();
172
+
173
+ this.headers = {};
174
+ this.socket = null;
175
+ this.body = null;
176
+
177
+ delete Requests.active[this.id];
178
+
179
+ return true;
180
+ }
181
+ });
182
+
183
+ /**
184
+ * Create a new XMLHttpRequest.
185
+ *
186
+ * @returns {XMLHttpRequest}
187
+ * @api private
188
+ */
189
+ Requests.XHR = function create() {
190
+ try { return new XMLHttpRequest(); }
191
+ catch (e) {}
192
+ };
193
+
194
+ /**
195
+ * Create a new ActiveXObject which can be used for XHR.
196
+ *
197
+ * @returns {ActiveXObject}
198
+ * @api private
199
+ */
200
+ Requests.AXO = function create() {
201
+ var ids = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', 'Microsoft.XMLHTTP']
202
+ , id;
203
+
204
+ while (ids.length) {
205
+ id = ids.shift();
206
+
207
+ try { return new AXO(id); }
208
+ catch (e) {}
209
+ }
210
+ };
211
+
212
+ /**
213
+ * Requests that are currently running.
214
+ *
215
+ * @type {Object}
216
+ * @private
217
+ */
218
+ Requests.active = {};
219
+
220
+ /**
221
+ * The type of technology we are using to establish a working Ajax connection.
222
+ * This can either be:
223
+ *
224
+ * - XHR: XMLHttpRequest
225
+ * - AXO: ActiveXObject
226
+ *
227
+ * This is also used as internal optimization so we can easily get the correct
228
+ * constructor as we've already feature detected it.
229
+ *
230
+ * @type {String}
231
+ * @public
232
+ */
233
+ Requests.method = !!Requests.XHR() ? 'XHR' : (!!Requests.AXO() ? 'AXO' : '');
234
+
235
+ /**
236
+ * Boolean indicating
237
+ *
238
+ * @type {Boolean}
239
+ * @public
240
+ */
241
+ Requests.supported = !!Requests.method;
242
+
243
+ /**
244
+ * The different type of `responseType` parsers that are supported in this XHR
245
+ * implementation.
246
+ *
247
+ * @type {Object}
248
+ * @public
249
+ */
250
+ Requests.type = 'XHR' === Requests.method ? (function detect() {
251
+ var types = 'arraybuffer,blob,document,json,text,moz-blob,moz-chunked-text,moz-chunked-arraybuffer,ms-stream'.split(',')
252
+ , supported = {}
253
+ , type, xhr, prop;
254
+
255
+ while (types.length) {
256
+ type = types.pop();
257
+ prop = type.replace(/-/g, '');
258
+ xhr = Requests.XHR();
259
+
260
+ //
261
+ // Older versions of Firefox/IE11 will throw an error because previous
262
+ // version of the specification do not support setting `responseType`
263
+ // before the request is opened. Thus, we open the request here.
264
+ //
265
+ // Note that `open()` does not actually open any connections; it just
266
+ // initializes the request object.
267
+ //
268
+ try {
269
+ // Try opening a request to current page.
270
+ xhr.open('get', '/', true);
271
+ } catch (e) {
272
+ // In JSDOM the above will fail because it only supports full URLs, so
273
+ // try opening a request to localhost.
274
+ try {
275
+ xhr.open('get', 'http://localhost/', true);
276
+ } catch (err) {
277
+ supported[prop] = false;
278
+ continue;
279
+ }
280
+ }
281
+
282
+ try {
283
+ xhr.responseType = type;
284
+ supported[prop] = 'response' in xhr && xhr.responseType === type;
285
+ } catch (e) {
286
+ supported[prop] = false;
287
+ }
288
+
289
+ xhr = null;
290
+ }
291
+
292
+ return supported;
293
+ }()) : {};
294
+
295
+ /**
296
+ * Do we support streaming response parsing.
297
+ *
298
+ * @type {Boolean}
299
+ * @private
300
+ */
301
+ Requests.streaming = 'XHR' === Requests.method && (
302
+ 'multipart' in XMLHttpRequest.prototype
303
+ || Requests.type.mozchunkedarraybuffer
304
+ || Requests.type.mozchunkedtext
305
+ || Requests.type.msstream
306
+ || Requests.type.mozblob
307
+ );
308
+
309
+ //
310
+ // IE has a bug which causes IE10 to freeze when close WebPage during an XHR
311
+ // request: https://support.microsoft.com/kb/2856746
312
+ //
313
+ // The solution is to completely clean up all active running requests.
314
+ //
315
+ if (global.attachEvent) global.attachEvent('onunload', function reap() {
316
+ for (var id in Requests.active) {
317
+ Requests.active[id].destroy();
318
+ }
319
+ });
320
+
321
+ //
322
+ // Expose the Requests library.
323
+ //
324
+ module.exports = Requests;
package/package.json CHANGED
@@ -1,6 +1,74 @@
1
1
  {
2
2
  "name": "random-transactions-sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.0",
4
+ "description": "An streaming XHR abstraction that works in browsers and node.js",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "100%": "istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100",
8
+ "wd": "node test/index.js --wd",
9
+ "test": "node test/index.js",
10
+ "static": "node test/static.js",
11
+ "node": "mocha test/requests.test.js",
12
+ "watch": "mocha --watch ./test/requests.test.js",
13
+ "all": "npm run test && npm run node",
14
+ "coverage": "istanbul cover ./node_modules/.bin/_mocha -- test/requests.test.js",
15
+ "test-node": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- test/requests.test.js",
16
+ "compile": "mkdir -p dist && browserify browser.js -o dist/requests.js --standalone Requests",
17
+ "pre-publish": "npm run compile",
18
+ "start": "node test/development.js"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/unshiftio/requests"
23
+ },
24
+ "keywords": [
25
+ "request",
26
+ "xhr",
27
+ "requests",
28
+ "http",
29
+ "xml",
30
+ "xmlhttp",
31
+ "xmlhttprequest"
32
+ ],
33
+ "author": "Arnout Kazemier",
34
+ "license": "MIT",
35
+ "bugs": {
36
+ "url": "https://github.com/unshiftio/requests/issues"
37
+ },
38
+ "homepage": "https://github.com/unshiftio/requests",
39
+ "dependencies": {
40
+ "axo": "0.0.x",
41
+ "eventemitter3": "~4.0.0",
42
+ "extendible": "0.1.x",
43
+ "hang": "1.0.x",
44
+ "loads": "0.0.x",
45
+ "node-http-xhr": "~1.3.0",
46
+ "xhr-send": "1.0.x"
47
+ },
48
+ "devDependencies": {
49
+ "argh": "0.1.x",
50
+ "assume": "~2.0.0",
51
+ "async-each": "~1.0.1",
52
+ "browserify": "^16.0.0",
53
+ "http-proxy": "~1.17.0",
54
+ "istanbul": "~0.4.5",
55
+ "mocha": "~3.5.0",
56
+ "mochify": "~2.18.1",
57
+ "pre-commit": "~1.2.0",
58
+ "setheader": "~1.0.0"
59
+ },
60
+ "testling": {
61
+ "files": "test/*.browser.js",
62
+ "harness": "mocha-bdd",
63
+ "browsers": [
64
+ "ie/6..latest",
65
+ "chrome/22..latest",
66
+ "firefox/16..latest",
67
+ "safari/latest",
68
+ "opera/11.0..latest",
69
+ "iphone/latest",
70
+ "ipad/latest",
71
+ "android-browser/latest"
72
+ ]
73
+ }
74
+ }
package/requested.js ADDED
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ var EventEmitter = require('eventemitter3');
4
+
5
+ function Requested(url, options) {
6
+ EventEmitter.call(this);
7
+
8
+ //
9
+ // All properties/options that should be introduced on the prototype.
10
+ //
11
+ this.merge(this, Requested.defaults, options || {});
12
+
13
+ //
14
+ // Private properties that should not be overridden by developers.
15
+ //
16
+ this.id = ++Requested.requested;
17
+
18
+ //
19
+ // We want to implement a stream like interface on top of this module so it
20
+ // can be used to read streaming data in node as well as through browserify.
21
+ //
22
+ this.readable = true;
23
+ this.writable = false;
24
+
25
+ if (this.initialize) this.initialize(url);
26
+ if (!this.manual && this.open) this.open(url);
27
+ }
28
+
29
+ Requested.extend = require('extendible');
30
+ Requested.prototype = new EventEmitter();
31
+ Requested.prototype.constructor = Requested;
32
+
33
+
34
+ /**
35
+ * Accurate type discovery.
36
+ *
37
+ * @param {Mixed} what What ever needs to be figured out.
38
+ * @returns {String} Name of the type.
39
+ * @api private
40
+ */
41
+ Requested.prototype.typeof = function type(what) {
42
+ return Object.prototype.toString.call(what).slice(8, -1).toLowerCase();
43
+ };
44
+
45
+ /**
46
+ * Deeply assign and merge objects together.
47
+ *
48
+ * @param {Object} target The target object that should receive the merged data.
49
+ * @returns {Object} The merged target object.
50
+ * @api private
51
+ */
52
+ Requested.prototype.merge = function merge(target) {
53
+ var i = 1
54
+ , arg, key;
55
+
56
+ for (; i < arguments.length; i++) {
57
+ arg = arguments[i];
58
+
59
+ for (key in arg) {
60
+ if (!Object.prototype.hasOwnProperty.call(arg, key)) continue;
61
+
62
+ if ('object' === this.typeof(arg[key])) {
63
+ target[key] = this.merge('object' === this.typeof(target[key]) ? target[key] : {}, arg[key]);
64
+ } else {
65
+ target[key] = arg[key];
66
+ }
67
+ }
68
+ }
69
+
70
+ return target;
71
+ };
72
+
73
+ /**
74
+ * The defaults for the Requests. These values will be used if no options object
75
+ * or matching key is provided. It can be override globally if needed but this
76
+ * is not advised as it can have some potential side affects for other libraries
77
+ * that use this module.
78
+ *
79
+ * @type {Object}
80
+ * @public
81
+ */
82
+ Requested.defaults = {
83
+ streaming: false,
84
+ manual: false,
85
+ method: 'GET',
86
+ mode: 'cors',
87
+ headers: {
88
+ //
89
+ // We're forcing text/plain mode by default to ensure that regular
90
+ // requests can benefit from CORS requests without an OPTIONS request. It's
91
+ // shared between server and client implementations to ensure that requests
92
+ // are handled in exactly the same way.
93
+ //
94
+ 'Content-Type': 'text/plain'
95
+ }
96
+ };
97
+
98
+ /**
99
+ * Unique id and also an indication on how many XHR requests we've made using
100
+ * this library.
101
+ *
102
+ * @type {Number}
103
+ * @private
104
+ */
105
+ Requested.requested = 0;
106
+
107
+ //
108
+ // Expose the module interface.
109
+ //
110
+ module.exports = Requested;