getstream
Advanced tools
Comparing version 0.1.5 to 0.1.7
{ | ||
"name": "getstream", | ||
"version": "0.1.5", | ||
"version": "0.1.7", | ||
"main": "dist/js/getstream.js", | ||
@@ -5,0 +5,0 @@ "ignore": [ |
@@ -1,687 +0,1 @@ | ||
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.stream=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||
// Browser Request | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
var XHR = XMLHttpRequest | ||
if (!XHR) throw new Error('missing XMLHttpRequest') | ||
module.exports = request | ||
request.log = { | ||
'trace': noop, 'debug': noop, 'info': noop, 'warn': noop, 'error': noop | ||
} | ||
var DEFAULT_TIMEOUT = 3 * 60 * 1000 // 3 minutes | ||
// | ||
// request | ||
// | ||
function request(options, callback) { | ||
// The entry-point to the API: prep the options object and pass the real work to run_xhr. | ||
if(typeof callback !== 'function') | ||
throw new Error('Bad callback given: ' + callback) | ||
if(!options) | ||
throw new Error('No options given') | ||
var options_onResponse = options.onResponse; // Save this for later. | ||
if(typeof options === 'string') | ||
options = {'uri':options}; | ||
else | ||
options = JSON.parse(JSON.stringify(options)); // Use a duplicate for mutating. | ||
options.onResponse = options_onResponse // And put it back. | ||
if (options.verbose) request.log = getLogger(); | ||
if(options.url) { | ||
options.uri = options.url; | ||
delete options.url; | ||
} | ||
if(!options.uri && options.uri !== "") | ||
throw new Error("options.uri is a required argument"); | ||
if(typeof options.uri != "string") | ||
throw new Error("options.uri must be a string"); | ||
var unsupported_options = ['proxy', '_redirectsFollowed', 'maxRedirects', 'followRedirect'] | ||
for (var i = 0; i < unsupported_options.length; i++) | ||
if(options[ unsupported_options[i] ]) | ||
throw new Error("options." + unsupported_options[i] + " is not supported") | ||
options.callback = callback | ||
options.method = options.method || 'GET'; | ||
options.headers = options.headers || {}; | ||
options.body = options.body || null | ||
options.timeout = options.timeout || request.DEFAULT_TIMEOUT | ||
if(options.headers.host) | ||
throw new Error("Options.headers.host is not supported"); | ||
if(options.json) { | ||
options.headers.accept = options.headers.accept || 'application/json' | ||
if(options.method !== 'GET') | ||
options.headers['content-type'] = 'application/json' | ||
if(typeof options.json !== 'boolean') | ||
options.body = JSON.stringify(options.json) | ||
else if(typeof options.body !== 'string') | ||
options.body = JSON.stringify(options.body) | ||
} | ||
// If onResponse is boolean true, call back immediately when the response is known, | ||
// not when the full request is complete. | ||
options.onResponse = options.onResponse || noop | ||
if(options.onResponse === true) { | ||
options.onResponse = callback | ||
options.callback = noop | ||
} | ||
// XXX Browsers do not like this. | ||
//if(options.body) | ||
// options.headers['content-length'] = options.body.length; | ||
// HTTP basic authentication | ||
if(!options.headers.authorization && options.auth) | ||
options.headers.authorization = 'Basic ' + b64_enc(options.auth.username + ':' + options.auth.password); | ||
return run_xhr(options) | ||
} | ||
var req_seq = 0 | ||
function run_xhr(options) { | ||
var xhr = new XHR | ||
, timed_out = false | ||
, is_cors = is_crossDomain(options.uri) | ||
, supports_cors = ('withCredentials' in xhr) | ||
req_seq += 1 | ||
xhr.seq_id = req_seq | ||
xhr.id = req_seq + ': ' + options.method + ' ' + options.uri | ||
xhr._id = xhr.id // I know I will type "_id" from habit all the time. | ||
if(is_cors && !supports_cors) { | ||
var cors_err = new Error('Browser does not support cross-origin request: ' + options.uri) | ||
cors_err.cors = 'unsupported' | ||
return options.callback(cors_err, xhr) | ||
} | ||
xhr.timeoutTimer = setTimeout(too_late, options.timeout) | ||
function too_late() { | ||
timed_out = true | ||
var er = new Error('ETIMEDOUT') | ||
er.code = 'ETIMEDOUT' | ||
er.duration = options.timeout | ||
request.log.error('Timeout', { 'id':xhr._id, 'milliseconds':options.timeout }) | ||
return options.callback(er, xhr) | ||
} | ||
// Some states can be skipped over, so remember what is still incomplete. | ||
var did = {'response':false, 'loading':false, 'end':false} | ||
xhr.onreadystatechange = on_state_change | ||
xhr.open(options.method, options.uri, true) // asynchronous | ||
if(is_cors) | ||
xhr.withCredentials = !! options.withCredentials | ||
xhr.send(options.body) | ||
return xhr | ||
function on_state_change(event) { | ||
if(timed_out) | ||
return request.log.debug('Ignoring timed out state change', {'state':xhr.readyState, 'id':xhr.id}) | ||
request.log.debug('State change', {'state':xhr.readyState, 'id':xhr.id, 'timed_out':timed_out}) | ||
if(xhr.readyState === XHR.OPENED) { | ||
request.log.debug('Request started', {'id':xhr.id}) | ||
for (var key in options.headers) | ||
xhr.setRequestHeader(key, options.headers[key]) | ||
} | ||
else if(xhr.readyState === XHR.HEADERS_RECEIVED) | ||
on_response() | ||
else if(xhr.readyState === XHR.LOADING) { | ||
on_response() | ||
on_loading() | ||
} | ||
else if(xhr.readyState === XHR.DONE) { | ||
on_response() | ||
on_loading() | ||
on_end() | ||
} | ||
} | ||
function on_response() { | ||
if(did.response) | ||
return | ||
did.response = true | ||
request.log.debug('Got response', {'id':xhr.id, 'status':xhr.status}) | ||
clearTimeout(xhr.timeoutTimer) | ||
xhr.statusCode = xhr.status // Node request compatibility | ||
// Detect failed CORS requests. | ||
if(is_cors && xhr.statusCode == 0) { | ||
var cors_err = new Error('CORS request rejected: ' + options.uri) | ||
cors_err.cors = 'rejected' | ||
// Do not process this request further. | ||
did.loading = true | ||
did.end = true | ||
return options.callback(cors_err, xhr) | ||
} | ||
options.onResponse(null, xhr) | ||
} | ||
function on_loading() { | ||
if(did.loading) | ||
return | ||
did.loading = true | ||
request.log.debug('Response body loading', {'id':xhr.id}) | ||
// TODO: Maybe simulate "data" events by watching xhr.responseText | ||
} | ||
function on_end() { | ||
if(did.end) | ||
return | ||
did.end = true | ||
request.log.debug('Request done', {'id':xhr.id}) | ||
xhr.body = xhr.responseText | ||
if(options.json) { | ||
try { xhr.body = JSON.parse(xhr.responseText) } | ||
catch (er) { return options.callback(er, xhr) } | ||
} | ||
options.callback(null, xhr, xhr.body) | ||
} | ||
} // request | ||
request.withCredentials = false; | ||
request.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT; | ||
// | ||
// defaults | ||
// | ||
request.defaults = function(options, requester) { | ||
var def = function (method) { | ||
var d = function (params, callback) { | ||
if(typeof params === 'string') | ||
params = {'uri': params}; | ||
else { | ||
params = JSON.parse(JSON.stringify(params)); | ||
} | ||
for (var i in options) { | ||
if (params[i] === undefined) params[i] = options[i] | ||
} | ||
return method(params, callback) | ||
} | ||
return d | ||
} | ||
var de = def(request) | ||
de.get = def(request.get) | ||
de.post = def(request.post) | ||
de.put = def(request.put) | ||
de.head = def(request.head) | ||
return de | ||
} | ||
// | ||
// HTTP method shortcuts | ||
// | ||
var shortcuts = [ 'get', 'put', 'post', 'head' ]; | ||
shortcuts.forEach(function(shortcut) { | ||
var method = shortcut.toUpperCase(); | ||
var func = shortcut.toLowerCase(); | ||
request[func] = function(opts) { | ||
if(typeof opts === 'string') | ||
opts = {'method':method, 'uri':opts}; | ||
else { | ||
opts = JSON.parse(JSON.stringify(opts)); | ||
opts.method = method; | ||
} | ||
var args = [opts].concat(Array.prototype.slice.apply(arguments, [1])); | ||
return request.apply(this, args); | ||
} | ||
}) | ||
// | ||
// CouchDB shortcut | ||
// | ||
request.couch = function(options, callback) { | ||
if(typeof options === 'string') | ||
options = {'uri':options} | ||
// Just use the request API to do JSON. | ||
options.json = true | ||
if(options.body) | ||
options.json = options.body | ||
delete options.body | ||
callback = callback || noop | ||
var xhr = request(options, couch_handler) | ||
return xhr | ||
function couch_handler(er, resp, body) { | ||
if(er) | ||
return callback(er, resp, body) | ||
if((resp.statusCode < 200 || resp.statusCode > 299) && body.error) { | ||
// The body is a Couch JSON object indicating the error. | ||
er = new Error('CouchDB error: ' + (body.error.reason || body.error.error)) | ||
for (var key in body) | ||
er[key] = body[key] | ||
return callback(er, resp, body); | ||
} | ||
return callback(er, resp, body); | ||
} | ||
} | ||
// | ||
// Utility | ||
// | ||
function noop() {} | ||
function getLogger() { | ||
var logger = {} | ||
, levels = ['trace', 'debug', 'info', 'warn', 'error'] | ||
, level, i | ||
for(i = 0; i < levels.length; i++) { | ||
level = levels[i] | ||
logger[level] = noop | ||
if(typeof console !== 'undefined' && console && console[level]) | ||
logger[level] = formatted(console, level) | ||
} | ||
return logger | ||
} | ||
function formatted(obj, method) { | ||
return formatted_logger | ||
function formatted_logger(str, context) { | ||
if(typeof context === 'object') | ||
str += ' ' + JSON.stringify(context) | ||
return obj[method].call(obj, str) | ||
} | ||
} | ||
// Return whether a URL is a cross-domain request. | ||
function is_crossDomain(url) { | ||
var rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/ | ||
// jQuery #8138, IE may throw an exception when accessing | ||
// a field from window.location if document.domain has been set | ||
var ajaxLocation | ||
try { ajaxLocation = location.href } | ||
catch (e) { | ||
// Use the href attribute of an A element since IE will modify it given document.location | ||
ajaxLocation = document.createElement( "a" ); | ||
ajaxLocation.href = ""; | ||
ajaxLocation = ajaxLocation.href; | ||
} | ||
var ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [] | ||
, parts = rurl.exec(url.toLowerCase() ) | ||
var result = !!( | ||
parts && | ||
( parts[1] != ajaxLocParts[1] | ||
|| parts[2] != ajaxLocParts[2] | ||
|| (parts[3] || (parts[1] === "http:" ? 80 : 443)) != (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443)) | ||
) | ||
) | ||
//console.debug('is_crossDomain('+url+') -> ' + result) | ||
return result | ||
} | ||
// MIT License from http://phpjs.org/functions/base64_encode:358 | ||
function b64_enc (data) { | ||
// Encodes string using MIME base64 algorithm | ||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | ||
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = []; | ||
if (!data) { | ||
return data; | ||
} | ||
// assume utf8 data | ||
// data = this.utf8_encode(data+''); | ||
do { // pack three octets into four hexets | ||
o1 = data.charCodeAt(i++); | ||
o2 = data.charCodeAt(i++); | ||
o3 = data.charCodeAt(i++); | ||
bits = o1<<16 | o2<<8 | o3; | ||
h1 = bits>>18 & 0x3f; | ||
h2 = bits>>12 & 0x3f; | ||
h3 = bits>>6 & 0x3f; | ||
h4 = bits & 0x3f; | ||
// use hexets to index into b64, and append result to encoded string | ||
tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); | ||
} while (i < data.length); | ||
enc = tmp_arr.join(''); | ||
switch (data.length % 3) { | ||
case 1: | ||
enc = enc.slice(0, -2) + '=='; | ||
break; | ||
case 2: | ||
enc = enc.slice(0, -1) + '='; | ||
break; | ||
} | ||
return enc; | ||
} | ||
},{}],2:[function(_dereq_,module,exports){ | ||
},{}],3:[function(_dereq_,module,exports){ | ||
// GetStream client library for node and the browser | ||
// Author: Thierry Schellenbach | ||
// BSD License | ||
var StreamClient = _dereq_('./lib/client'); | ||
var errors = _dereq_('./lib/errors'); | ||
function connect(apiKey, apiSecret) { | ||
return new StreamClient(apiKey, apiSecret); | ||
} | ||
module.exports.connect = connect; | ||
module.exports.errors = errors; | ||
},{"./lib/client":4,"./lib/errors":5}],4:[function(_dereq_,module,exports){ | ||
var request = _dereq_('request'); | ||
var StreamFeed = _dereq_('./feed'); | ||
var signing = _dereq_('./signing'); | ||
var errors = _dereq_('./errors'); | ||
var crypto = _dereq_('crypto'); | ||
var StreamClient = function () { | ||
this.initialize.apply(this, arguments); | ||
}; | ||
StreamClient.prototype = { | ||
baseUrl: 'https://getstream.io', | ||
initialize: function (key, secret, fayeUrl) { | ||
/* | ||
* API key and secret | ||
* Secret is optional | ||
*/ | ||
this.key = key; | ||
this.secret = secret; | ||
this.fayeUrl = fayeUrl ? fayeUrl : 'https://getstream.io/faye'; | ||
}, | ||
feed: function(feedId, token, siteId) { | ||
/* | ||
* Returns a feed object for the given feed id and token | ||
* Example: | ||
* | ||
* client.feed('user1', 'token2'); | ||
*/ | ||
var match = feedId.match(/\:/g); | ||
if (match === null || match.length != 1) { | ||
throw new errors.FeedError('Wrong feed format ' + feedId + ' correct format is flat:1'); | ||
} | ||
if (crypto.createHash && this.secret && !token) { | ||
// we are server side, have a secret but no feed signature | ||
token = signing.sign(this.secret, feedId.replace(':', '')); | ||
} | ||
if (!token) { | ||
throw new errors.FeedError('Missing token, in client side mode please provide a feed secret'); | ||
} | ||
var feed = new StreamFeed(this, feedId, token, siteId); | ||
return feed; | ||
}, | ||
enrichUrl: function(relativeUrl) { | ||
var url = this.baseUrl + relativeUrl; | ||
if (url.indexOf('?') != -1) { | ||
url += '&api_key=' + this.key; | ||
} else { | ||
url += '?api_key=' + this.key; | ||
} | ||
return url; | ||
}, | ||
enrichKwargs: function(kwargs) { | ||
kwargs.url = this.enrichUrl(kwargs.url); | ||
kwargs.json = true; | ||
var secret = kwargs.secret || this.secret; | ||
kwargs.headers = {}; | ||
kwargs.headers.Authorization = secret; | ||
return kwargs; | ||
}, | ||
/* | ||
* Shortcuts for post, get and delete HTTP methods | ||
*/ | ||
get: function(kwargs, cb) { | ||
kwargs = this.enrichKwargs(kwargs); | ||
kwargs.method = 'GET'; | ||
return request.get(kwargs, cb); | ||
}, | ||
post: function(kwargs, cb) { | ||
kwargs = this.enrichKwargs(kwargs); | ||
kwargs.method = 'POST'; | ||
return request(kwargs, cb); | ||
}, | ||
delete: function(kwargs, cb) { | ||
kwargs = this.enrichKwargs(kwargs); | ||
kwargs.method = 'DELETE'; | ||
return request(kwargs, cb); | ||
} | ||
}; | ||
module.exports = StreamClient; | ||
},{"./errors":5,"./feed":6,"./signing":7,"crypto":2,"request":1}],5:[function(_dereq_,module,exports){ | ||
var errors = module.exports; | ||
var canCapture = (typeof Error.captureStackTrace === 'function'); | ||
var canStack = !!(new Error()).stack; | ||
function ErrorAbstract(msg, constructor) { | ||
this.message = msg; | ||
Error.call(this, this.message); | ||
if (canCapture) { | ||
Error.captureStackTrace(this, constructor); | ||
} | ||
else if (canStack) { | ||
this.stack = (new Error()).stack; | ||
} | ||
else { | ||
this.stack = ''; | ||
} | ||
} | ||
errors._Abstract = ErrorAbstract; | ||
ErrorAbstract.prototype = new Error(); | ||
/** | ||
* Connection Error | ||
* @param {String} [msg] - An error message that will probably end up in a log. | ||
*/ | ||
errors.FeedError = function FeedError(msg) { | ||
ErrorAbstract.call(this, msg); | ||
}; | ||
errors.FeedError.prototype = new ErrorAbstract(); | ||
},{}],6:[function(_dereq_,module,exports){ | ||
var StreamFeed = function () { | ||
this.initialize.apply(this, arguments); | ||
}; | ||
StreamFeed.prototype = { | ||
/* | ||
* The feed object contains convenience functions such add activity | ||
* remove activity etc | ||
* | ||
*/ | ||
initialize: function(client, feed, token, siteId) { | ||
this.client = client; | ||
this.feed = feed; | ||
this.token = token; | ||
this.feedUrl = feed.replace(':', '/'); | ||
this.feedTogether = feed.replace(':', ''); | ||
this.feedToken = this.feedTogether + ' ' + this.token; | ||
this.fayeClient = null; | ||
this.notificationChannel = 'site-' + siteId + '-feed-' + this.feedTogether; | ||
}, | ||
addActivity: function(activity, callback) { | ||
/* | ||
* Adds the given activity to the feed and | ||
* calls the specified callback | ||
*/ | ||
var xhr = this.client.post({ | ||
'url': '/api/feed/'+ this.feedUrl + '/', | ||
'form': activity, | ||
'secret': this.feedToken | ||
}, callback); | ||
return xhr; | ||
}, | ||
removeActivity: function(activityId, callback) { | ||
var xhr = this.client.delete({ | ||
'url': '/api/feed/'+ this.feedUrl + '/' + activityId + '/', | ||
'secret': this.feedToken | ||
}, callback); | ||
return xhr; | ||
}, | ||
follow: function(target, callback) { | ||
var xhr = this.client.post({ | ||
'url': '/api/feed/'+ this.feedUrl + '/follows/', | ||
'form': {'target': target}, | ||
'secret': this.feedToken | ||
}, callback); | ||
return xhr; | ||
}, | ||
unfollow: function(target, callback) { | ||
var xhr = this.client.delete({ | ||
'url': '/api/feed/'+ this.feedUrl + '/follows/' + target + '/', | ||
'secret': this.feedToken | ||
}, callback); | ||
return xhr; | ||
}, | ||
get: function(argumentHash, callback) { | ||
var xhr = this.client.get({ | ||
'url': '/api/feed/'+ this.feedUrl + '/', | ||
'qs': argumentHash, | ||
'secret': this.feedToken | ||
}, callback); | ||
return xhr; | ||
}, | ||
getFayeAuthorization: function(){ | ||
var api_key = this.client.key; | ||
var user_id = this.notificationChannel; | ||
var signature = this.token; | ||
return { | ||
incoming: function(message, callback) { | ||
callback(message); | ||
}, | ||
outgoing: function(message, callback) { | ||
message.ext = {'user_id': user_id, 'api_key':api_key, 'signature': signature}; | ||
callback(message); | ||
} | ||
}; | ||
}, | ||
getFayeClient: function(){ | ||
if (this.fayeClient === null){ | ||
this.fayeClient = new Faye.Client(this.client.fayeUrl); | ||
var authExtension = this.getFayeAuthorization(); | ||
this.fayeClient.addExtension(authExtension); | ||
} | ||
return this.fayeClient; | ||
}, | ||
subscribe: function(callback){ | ||
return this.getFayeClient().subscribe('/'+this.notificationChannel, callback); | ||
} | ||
}; | ||
module.exports = StreamFeed; | ||
},{}],7:[function(_dereq_,module,exports){ | ||
var crypto = _dereq_('crypto'); | ||
function urlsafe_b64_encode(s) { | ||
var escaped = s.replace('+', '-').replace('/', '_'); | ||
return escaped.replace(/^=+/, '').replace(/=+$/, ''); | ||
} | ||
exports.sign = function(secret, value) { | ||
/* | ||
* Setup sha1 based on the secret | ||
* Get the digest of the value | ||
* Base64 encode the result | ||
* | ||
* Also see | ||
* https://github.com/tbarbugli/stream-ruby/blob/master/lib/stream/signer.rb | ||
* https://github.com/tschellenbach/stream-python/blob/master/stream/signing.py | ||
* | ||
* Steps | ||
* secret: tfq2sdqpj9g446sbv653x3aqmgn33hsn8uzdc9jpskaw8mj6vsnhzswuwptuj9su | ||
* value: flat1 | ||
* digest: Q\xb6\xd5+\x82\xd58\xdeu\x80\xc5\xe3\xb8\xa5bL1\xf1\xa3\xdb | ||
* result: UbbVK4LVON51gMXjuKViTDHxo9s | ||
*/ | ||
var key = new crypto.createHash('sha1').update(secret).digest(); | ||
var hmac = crypto.createHmac('sha1', key); | ||
var signature = hmac.update(value).digest('base64'); | ||
var urlsafe = urlsafe_b64_encode(signature); | ||
return urlsafe; | ||
}; | ||
},{"crypto":2}]},{},[3]) | ||
(3) | ||
}); | ||
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.stream=e()}}(function(){return function e(t,r,n){function o(s,a){if(!r[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);throw new Error("Cannot find module '"+s+"'")}var c=r[s]={exports:{}};t[s][0].call(c.exports,function(e){var r=t[s][1][e];return o(r?r:e)},c,c.exports,e,t,r,n)}return r[s].exports}for(var i="function"==typeof require&&require,s=0;s<n.length;s++)o(n[s]);return o}({1:[function(e,t){function r(e,t){if("function"!=typeof t)throw new Error("Bad callback given: "+t);if(!e)throw new Error("No options given");var s=e.onResponse;if(e="string"==typeof e?{uri:e}:JSON.parse(JSON.stringify(e)),e.onResponse=s,e.verbose&&(r.log=i()),e.url&&(e.uri=e.url,delete e.url),!e.uri&&""!==e.uri)throw new Error("options.uri is a required argument");if("string"!=typeof e.uri)throw new Error("options.uri must be a string");for(var a=["proxy","_redirectsFollowed","maxRedirects","followRedirect"],c=0;c<a.length;c++)if(e[a[c]])throw new Error("options."+a[c]+" is not supported");if(e.callback=t,e.method=e.method||"GET",e.headers=e.headers||{},e.body=e.body||null,e.timeout=e.timeout||r.DEFAULT_TIMEOUT,e.headers.host)throw new Error("Options.headers.host is not supported");e.json&&(e.headers.accept=e.headers.accept||"application/json","GET"!==e.method&&(e.headers["content-type"]="application/json"),"boolean"!=typeof e.json?e.body=JSON.stringify(e.json):"string"!=typeof e.body&&(e.body=JSON.stringify(e.body)));var d=function(e){var t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(encodeURIComponent(r)+"="+encodeURIComponent(e[r]));return t.join("&")};if(e.qs){var f="string"==typeof e.qs?e.qs:d(e.qs);e.uri=-1!==e.uri.indexOf("?")?e.uri+"&"+f:e.uri+"?"+f}var l=function(e){var t={};t.boundry="-------------------------------"+Math.floor(1e9*Math.random());var r=[];for(var n in e)e.hasOwnProperty(n)&&r.push("--"+t.boundry+'\nContent-Disposition: form-data; name="'+n+'"\n\n'+e[n]+"\n");return r.push("--"+t.boundry+"--"),t.body=r.join(""),t.length=t.body.length,t.type="multipart/form-data; boundary="+t.boundry,t};if(e.form){if("string"==typeof e.form)throw"form name unsupported";if("POST"===e.method){var h=(e.encoding||"application/x-www-form-urlencoded").toLowerCase();switch(e.headers["content-type"]=h,h){case"application/x-www-form-urlencoded":e.body=d(e.form).replace(/%20/g,"+");break;case"multipart/form-data":var p=l(e.form);e.body=p.body,e.headers["content-type"]=p.type;break;default:throw new Error("unsupported encoding:"+h)}}}return e.onResponse=e.onResponse||o,e.onResponse===!0&&(e.onResponse=t,e.callback=o),!e.headers.authorization&&e.auth&&(e.headers.authorization="Basic "+u(e.auth.username+":"+e.auth.password)),n(e)}function n(e){function t(){d=!0;var t=new Error("ETIMEDOUT");return t.code="ETIMEDOUT",t.duration=e.timeout,r.log.error("Timeout",{id:u._id,milliseconds:e.timeout}),e.callback(t,u)}function n(){if(d)return r.log.debug("Ignoring timed out state change",{state:u.readyState,id:u.id});if(r.log.debug("State change",{state:u.readyState,id:u.id,timed_out:d}),u.readyState===c.OPENED){r.log.debug("Request started",{id:u.id});for(var t in e.headers)u.setRequestHeader(t,e.headers[t])}else u.readyState===c.HEADERS_RECEIVED?o():u.readyState===c.LOADING?(o(),i()):u.readyState===c.DONE&&(o(),i(),s())}function o(){if(!y.response){if(y.response=!0,r.log.debug("Got response",{id:u.id,status:u.status}),clearTimeout(u.timeoutTimer),u.statusCode=u.status,l&&0==u.statusCode){var t=new Error("CORS request rejected: "+e.uri);return t.cors="rejected",y.loading=!0,y.end=!0,e.callback(t,u)}e.onResponse(null,u)}}function i(){y.loading||(y.loading=!0,r.log.debug("Response body loading",{id:u.id}))}function s(){if(!y.end){if(y.end=!0,r.log.debug("Request done",{id:u.id}),u.body=u.responseText,e.json)try{u.body=JSON.parse(u.responseText)}catch(t){return e.callback(t,u)}e.callback(null,u,u.body)}}var u=new c,d=!1,l=a(e.uri),h="withCredentials"in u;if(f+=1,u.seq_id=f,u.id=f+": "+e.method+" "+e.uri,u._id=u.id,l&&!h){var p=new Error("Browser does not support cross-origin request: "+e.uri);return p.cors="unsupported",e.callback(p,u)}u.timeoutTimer=setTimeout(t,e.timeout);var y={response:!1,loading:!1,end:!1};return u.onreadystatechange=n,u.open(e.method,e.uri,!0),l&&(u.withCredentials=!!e.withCredentials),u.send(e.body),u}function o(){}function i(){var e,t,r={},n=["trace","debug","info","warn","error"];for(t=0;t<n.length;t++)e=n[t],r[e]=o,"undefined"!=typeof console&&console&&console[e]&&(r[e]=s(console,e));return r}function s(e,t){function r(r,n){return"object"==typeof n&&(r+=" "+JSON.stringify(n)),e[t].call(e,r)}return r}function a(e){var t,r=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/;try{t=location.href}catch(n){t=document.createElement("a"),t.href="",t=t.href}var o=r.exec(t.toLowerCase())||[],i=r.exec(e.toLowerCase()),s=!(!i||i[1]==o[1]&&i[2]==o[2]&&(i[3]||("http:"===i[1]?80:443))==(o[3]||("http:"===o[1]?80:443)));return s}function u(e){var t,r,n,o,i,s,a,u,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d=0,f=0,l="",h=[];if(!e)return e;do t=e.charCodeAt(d++),r=e.charCodeAt(d++),n=e.charCodeAt(d++),u=t<<16|r<<8|n,o=u>>18&63,i=u>>12&63,s=u>>6&63,a=63&u,h[f++]=c.charAt(o)+c.charAt(i)+c.charAt(s)+c.charAt(a);while(d<e.length);switch(l=h.join(""),e.length%3){case 1:l=l.slice(0,-2)+"==";break;case 2:l=l.slice(0,-1)+"="}return l}var c=XMLHttpRequest;if(!c)throw new Error("missing XMLHttpRequest");r.log={trace:o,debug:o,info:o,warn:o,error:o};var d=18e4,f=0;r.withCredentials=!1,r.DEFAULT_TIMEOUT=d,r.defaults=function(e){var t=function(t){var r=function(r,n){r="string"==typeof r?{uri:r}:JSON.parse(JSON.stringify(r));for(var o in e)void 0===r[o]&&(r[o]=e[o]);return t(r,n)};return r},n=t(r);return n.get=t(r.get),n.post=t(r.post),n.put=t(r.put),n.head=t(r.head),n};var l=["get","put","post","head"];l.forEach(function(e){var t=e.toUpperCase(),n=e.toLowerCase();r[n]=function(e){"string"==typeof e?e={method:t,uri:e}:(e=JSON.parse(JSON.stringify(e)),e.method=t);var n=[e].concat(Array.prototype.slice.apply(arguments,[1]));return r.apply(this,n)}}),r.couch=function(e,t){function n(e,r,n){if(e)return t(e,r,n);if((r.statusCode<200||r.statusCode>299)&&n.error){e=new Error("CouchDB error: "+(n.error.reason||n.error.error));for(var o in n)e[o]=n[o];return t(e,r,n)}return t(e,r,n)}"string"==typeof e&&(e={uri:e}),e.json=!0,e.body&&(e.json=e.body),delete e.body,t=t||o;var i=r(e,n);return i},t.exports=r},{}],2:[function(){},{}],3:[function(e,t){function r(e,t){return new n(e,t)}var n=e("./lib/client"),o=e("./lib/errors"),i=e("request");t.exports.connect=r,t.exports.errors=o,t.exports.request=i},{"./lib/client":4,"./lib/errors":5,request:1}],4:[function(e,t){var r=e("request"),n=e("./feed"),o=e("./signing"),i=e("./errors"),s=e("crypto"),a=function(){this.initialize.apply(this,arguments)};a.prototype={baseUrl:"https://getstream.io",initialize:function(e,t,r){this.key=e,this.secret=t,this.fayeUrl=r?r:"https://getstream.io/faye"},feed:function(e,t,r){var a=e.match(/\:/g);if(null===a||1!=a.length)throw new i.FeedError("Wrong feed format "+e+" correct format is flat:1");if(s.createHash&&this.secret&&!t&&(t=o.sign(this.secret,e.replace(":",""))),!t)throw new i.FeedError("Missing token, in client side mode please provide a feed secret");var u=new n(this,e,t,r);return u},enrichUrl:function(e){var t=this.baseUrl+e;return t+=-1!=t.indexOf("?")?"&api_key="+this.key:"?api_key="+this.key},enrichKwargs:function(e){e.url=this.enrichUrl(e.url),e.json=!0;var t=e.secret||this.secret;return e.headers={},e.headers.Authorization=t,e},get:function(e,t){return e=this.enrichKwargs(e),e.method="GET",r.get(e,t)},post:function(e,t){return e=this.enrichKwargs(e),e.method="POST",r(e,t)},"delete":function(e,t){return e=this.enrichKwargs(e),e.method="DELETE",r(e,t)}},t.exports=a},{"./errors":5,"./feed":6,"./signing":7,crypto:2,request:1}],5:[function(e,t){function r(e,t){this.message=e,Error.call(this,this.message),o?Error.captureStackTrace(this,t):this.stack=i?(new Error).stack:""}var n=t.exports,o="function"==typeof Error.captureStackTrace,i=!!(new Error).stack;n._Abstract=r,r.prototype=new Error,n.FeedError=function(e){r.call(this,e)},n.FeedError.prototype=new r},{}],6:[function(e,t){var r=function(){this.initialize.apply(this,arguments)};r.prototype={initialize:function(e,t,r,n){this.client=e,this.feed=t,this.token=r,this.feedUrl=t.replace(":","/"),this.feedTogether=t.replace(":",""),this.feedToken=this.feedTogether+" "+this.token,this.fayeClient=null,this.notificationChannel="site-"+n+"-feed-"+this.feedTogether},addActivity:function(e,t){var r=this.client.post({url:"/api/feed/"+this.feedUrl+"/",body:e,secret:this.feedToken},t);return r},removeActivity:function(e,t){var r=this.client.delete({url:"/api/feed/"+this.feedUrl+"/"+e+"/",secret:this.feedToken},t);return r},follow:function(e,t){var r=this.client.post({url:"/api/feed/"+this.feedUrl+"/follows/",body:{target:e},secret:this.feedToken},t);return r},unfollow:function(e,t){var r=this.client.delete({url:"/api/feed/"+this.feedUrl+"/follows/"+e+"/",secret:this.feedToken},t);return r},get:function(e,t){var r=this.client.get({url:"/api/feed/"+this.feedUrl+"/",qs:e,secret:this.feedToken},t);return r},getFayeAuthorization:function(){var e=this.client.key,t=this.notificationChannel,r=this.token;return{incoming:function(e,t){t(e)},outgoing:function(n,o){n.ext={user_id:t,api_key:e,signature:r},o(n)}}},getFayeClient:function(){if(null===this.fayeClient){this.fayeClient=new Faye.Client(this.client.fayeUrl);var e=this.getFayeAuthorization();this.fayeClient.addExtension(e)}return this.fayeClient},subscribe:function(e){return this.getFayeClient().subscribe("/"+this.notificationChannel,e)}},t.exports=r},{}],7:[function(e,t,r){function n(e){var t=e.replace("+","-").replace("/","_");return t.replace(/^=+/,"").replace(/=+$/,"")}var o=e("crypto");r.sign=function(e,t){var r=new o.createHash("sha1").update(e).digest(),i=o.createHmac("sha1",r),s=i.update(t).digest("base64"),a=n(s);return a}},{crypto:2}]},{},[3])(3)}); |
@@ -7,4 +7,5 @@ var gulp = require('gulp'); | ||
var shell = require('gulp-shell'); | ||
var uglify = require('gulp-uglify'); | ||
var bump = require('gulp-bump'); | ||
gulp.task('default', function() { | ||
@@ -37,5 +38,5 @@ // watch for JS changes and run tests | ||
gulp.task('cov', function () { | ||
return gulp.src('./test/integration/index.js', {read: false}) | ||
return gulp.src('./test/integration/cov.js', {read: false}) | ||
.pipe(mocha({reporter: 'html-cov'})) | ||
.pipe(gulp.dest('./build/')); | ||
.pipe(gulp.dest('./dist/')); | ||
@@ -64,5 +65,17 @@ }); | ||
})) | ||
.pipe(uglify()) | ||
.pipe(gulp.dest('./dist/js')); | ||
}); | ||
gulp.task('bump', function () { | ||
return gulp.src(['./package.json']) | ||
.pipe(bump()) | ||
.pipe(gulp.dest('./')); | ||
}); | ||
gulp.task('npm', function (done) { | ||
require('child_process').spawn('npm', ['publish'], { stdio: 'inherit' }) | ||
.on('close', done); | ||
}); | ||
// release to bower | ||
@@ -79,3 +92,5 @@ gulp.task('release', function () { | ||
var version = packageJSON.version; | ||
var message = 'Released version ' + versionName; | ||
var versionName = 'v' + version; | ||
console.log('Releasing version ' + versionName); | ||
@@ -88,9 +103,13 @@ console.log(process.cwd()); | ||
// push to github (which also impacts bower) | ||
console.log('Git tagging'); | ||
shell.task(['git tag ' + version]); | ||
shell.task(['git push origin master --tags']); | ||
//git.tag(version, 'release of version ' + packageJSON.version); | ||
git.push('origin', 'master', {args: '--tags'}); | ||
console.log('Releasing to npm'); | ||
shell.task(['npm publish .']); | ||
console.log('Git tagging and releasing'); | ||
return gulp.src('./', {read: false}) | ||
.pipe(shell.task(['npm publish .'])) | ||
.pipe(gulp.dest('./')); | ||
return gulp.src('./', {read: false}) | ||
.pipe(git.commit(message)) | ||
.pipe(git.tag(versionName, message)) | ||
.pipe(git.push('origin', 'master', '--tags')) | ||
.pipe(gulp.dest('./')); | ||
//.pipe(); | ||
}); | ||
@@ -97,0 +116,0 @@ |
@@ -10,6 +10,6 @@ { | ||
"homepage": "https://getstream.io/", | ||
"version": "0.1.5", | ||
"version": "0.1.7", | ||
"config": { | ||
"blanket": { | ||
"pattern": "specified in test/integration/coverage.js" | ||
"pattern": "src" | ||
} | ||
@@ -24,6 +24,10 @@ }, | ||
"bluebird": "^2.1.3", | ||
"browser-request": "git://github.com/iriscouch/browser-request", | ||
"browserify": "~4.1.11", | ||
"connect": "^3.0.1", | ||
"coveralls": "~2.10.1", | ||
"expect.js": "~0.3.1", | ||
"gulp": "^3.8.1", | ||
"gulp-browserify": "^0.5.0", | ||
"gulp-bump": "^0.1.8", | ||
"gulp-git": "^0.4.3", | ||
@@ -33,3 +37,7 @@ "gulp-jshint": "^1.6.3", | ||
"gulp-shell": "^0.2.7", | ||
"mocha": "^1.20.1" | ||
"gulp-uglify": "~0.3.1", | ||
"mocha": "^1.20.1", | ||
"mocha-lcov-reporter": "0.0.1", | ||
"mocha-sauce": "git://github.com/pbakaus/mocha-sauce.git", | ||
"serve-static": "^1.2.3" | ||
}, | ||
@@ -36,0 +44,0 @@ "license": "BSD", |
@@ -5,2 +5,4 @@ stream-node | ||
[![Build Status](https://travis-ci.org/tschellenbach/stream-js.svg?branch=master)](https://travis-ci.org/tschellenbach/stream-js) | ||
[![Coverage Status](https://coveralls.io/repos/tschellenbach/stream-js/badge.png?branch=master)](https://coveralls.io/r/tschellenbach/stream-js?branch=master) | ||
[![Dependencies up to date](https://david-dm.org/tschellenbach/stream-js.png)](https://david-dm.org/tschellenbach/stream-js) | ||
@@ -65,2 +67,6 @@ stream-node is a Node/Javascript client for [Stream][]. | ||
mocha test/integration/index.js | ||
# browser version | ||
test/browser/test.html | ||
# coverage | ||
mocha test/integration/cov.js -R html-cov > cov.html | ||
``` | ||
@@ -67,0 +73,0 @@ |
@@ -8,4 +8,4 @@ | ||
var errors = require('./lib/errors'); | ||
var request = require('request'); | ||
function connect(apiKey, apiSecret) { | ||
@@ -17,1 +17,2 @@ return new StreamClient(apiKey, apiSecret); | ||
module.exports.errors = errors; | ||
module.exports.request = request; |
@@ -29,3 +29,3 @@ | ||
'url': '/api/feed/'+ this.feedUrl + '/', | ||
'form': activity, | ||
'body': activity, | ||
'secret': this.feedToken | ||
@@ -45,3 +45,3 @@ }, callback); | ||
'url': '/api/feed/'+ this.feedUrl + '/follows/', | ||
'form': {'target': target}, | ||
'body': {'target': target}, | ||
'secret': this.feedToken | ||
@@ -48,0 +48,0 @@ }, callback); |
@@ -79,2 +79,3 @@ | ||
it('follow', function (done) { | ||
var activityId = null; | ||
function add() { | ||
@@ -99,2 +100,3 @@ var activity = {'actor': 1, 'verb': 'add', 'object': 1}; | ||
it('unfollow', function (done) { | ||
var activityId = null; | ||
function add() { | ||
@@ -115,4 +117,4 @@ var activity = {'actor': 1, 'verb': 'add', 'object': 1}; | ||
expect(response.statusCode).to.eql(200); | ||
firstResult = body['results'][0]; | ||
activityFound = (firstResult) ? firstResult['activities'][0]['id'] : null; | ||
var firstResult = body['results'][0]; | ||
var activityFound = (firstResult) ? firstResult['activities'][0]['id'] : null; | ||
expect(activityFound).to.not.eql(activityId); | ||
@@ -129,43 +131,56 @@ done(); | ||
//TODO find a library to make async testing easier on the eye | ||
var activityIdOne = null; | ||
var activityIdTwo = null; | ||
var activityIdThree = null; | ||
function add() { | ||
var activity = {'actor': 1, 'verb': 'add', 'object': 1}; | ||
user1.addActivity(activity, add2); | ||
} | ||
var activity = {'actor': 1, 'verb': 'add', 'object': 1}; | ||
user1.addActivity(activity, add2); | ||
} | ||
function add2(error, response, body) { | ||
activityIdOne = body['id']; | ||
var activity = {'actor': 2, 'verb': 'watch', 'object': 2}; | ||
user1.addActivity(activity, add3); | ||
} | ||
function add3(error, response, body) { | ||
var activity = {'actor': 2, 'verb': 'watch', 'object': 2}; | ||
user1.addActivity(activity, add3); | ||
} | ||
function add3(error, response, body) { | ||
activityIdTwo = body['id']; | ||
var activity = {'actor': 3, 'verb': 'run', 'object': 2}; | ||
user1.addActivity(activity, get); | ||
} | ||
function get(error, response, body) { | ||
activityIdThree = body['id']; | ||
user1.get({'limit': 2}, check); | ||
} | ||
// no filtering | ||
function check(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdThree); | ||
expect(body['results'][1]['id']).to.eql(activityIdTwo); | ||
user1.get({limit:2, offset:1}, check2); | ||
} | ||
// offset based | ||
function check2(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdTwo); | ||
expect(body['results'][1]['id']).to.eql(activityIdOne); | ||
user1.get({limit:2, id_lt:activityIdTwo}, check3); | ||
} | ||
// try id_lt based | ||
function check3(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdOne); | ||
done(); | ||
} | ||
var activity = {'actor': 3, 'verb': 'run', 'object': 2}; | ||
user1.addActivity(activity, get); | ||
} | ||
function get(error, response, body) { | ||
activityIdThree = body['id']; | ||
user1.get({'limit': 2}, check); | ||
} | ||
// no filtering | ||
function check(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdThree); | ||
expect(body['results'][1]['id']).to.eql(activityIdTwo); | ||
user1.get({limit:2, offset:1}, check2); | ||
} | ||
// offset based | ||
function check2(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdTwo); | ||
expect(body['results'][1]['id']).to.eql(activityIdOne); | ||
user1.get({limit:2, id_lt:activityIdTwo}, check3); | ||
} | ||
// try id_lt based | ||
function check3(error, response, body) { | ||
expect(body['results'].length).to.eql(2); | ||
expect(body['results'][0]['id']).to.eql(activityIdOne); | ||
done(); | ||
} | ||
add(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
23
0
74
200374
19
6619
2