put stuff in same folder
npm install [email protected] bluebird
then run siotest.js
Should first error and then connect
put stuff in same folder
npm install [email protected] bluebird
then run siotest.js
Should first error and then connect
| // socket.io-1.2.1 | |
| // (from http://socket.io/download/) | |
| io = require('socket.io-client').connect; | |
| /** | |
| * sails.io.js | |
| * ------------------------------------------------------------------------ | |
| * JavaScript Client (SDK) for communicating with Sails. | |
| * | |
| * Note that this script is completely optional, but it is handy if you're | |
| * using WebSockets from the browser to talk to your Sails server. | |
| * | |
| * For tips and documentation, visit: | |
| * http://sailsjs.org/#!documentation/reference/BrowserSDK/BrowserSDK.html | |
| * ------------------------------------------------------------------------ | |
| * | |
| * This file allows you to send and receive socket.io messages to & from Sails | |
| * by simulating a REST client interface on top of socket.io. It models its API | |
| * after the $.ajax pattern from jQuery you might already be familiar with. | |
| * | |
| * So if you're switching from using AJAX to sockets, instead of: | |
| * `$.post( url, [data], [cb] )` | |
| * | |
| * You would use: | |
| * `socket.post( url, [data], [cb] )` | |
| */ | |
| (function() { | |
| // Save the URL that this script was fetched from for use below. | |
| // (skip this if this SDK is being used outside of the DOM, i.e. in a Node process) | |
| var urlThisScriptWasFetchedFrom = (function() { | |
| if ( | |
| typeof window !== 'object' || | |
| typeof window.document !== 'object' || | |
| typeof window.document.getElementsByTagName !== 'function' | |
| ) { | |
| return ''; | |
| } | |
| // Return the URL of the last script loaded (i.e. this one) | |
| // (this must run before nextTick; see http://stackoverflow.com/a/2976714/486547) | |
| var allScriptsCurrentlyInDOM = window.document.getElementsByTagName('script'); | |
| var thisScript = allScriptsCurrentlyInDOM[allScriptsCurrentlyInDOM.length - 1]; | |
| return thisScript.src; | |
| })(); | |
| // Constants | |
| var CONNECTION_METADATA_PARAMS = { | |
| version: '__sails_io_sdk_version', | |
| platform: '__sails_io_sdk_platform', | |
| language: '__sails_io_sdk_language' | |
| }; | |
| // Current version of this SDK (sailsDK?!?!) and other metadata | |
| // that will be sent along w/ the initial connection request. | |
| var SDK_INFO = { | |
| version: '0.11.0', // TODO: pull this automatically from package.json during build. | |
| platform: typeof module === 'undefined' ? 'browser' : 'node', | |
| language: 'javascript' | |
| }; | |
| SDK_INFO.versionString = | |
| CONNECTION_METADATA_PARAMS.version + '=' + SDK_INFO.version + '&' + | |
| CONNECTION_METADATA_PARAMS.platform + '=' + SDK_INFO.platform + '&' + | |
| CONNECTION_METADATA_PARAMS.language + '=' + SDK_INFO.language; | |
| // In case you're wrapping the socket.io client to prevent pollution of the | |
| // global namespace, you can pass in your own `io` to replace the global one. | |
| // But we still grab access to the global one if it's available here: | |
| var _io = (typeof io !== 'undefined') ? io : null; | |
| /** | |
| * Augment the `io` object passed in with methods for talking and listening | |
| * to one or more Sails backend(s). Automatically connects a socket and | |
| * exposes it on `io.socket`. If a socket tries to make requests before it | |
| * is connected, the sails.io.js client will queue it up. | |
| * | |
| * @param {SocketIO} io | |
| */ | |
| function SailsIOClient(io) { | |
| // Prefer the passed-in `io` instance, but also use the global one if we've got it. | |
| if (!io) { | |
| io = _io; | |
| } | |
| // If the socket.io client is not available, none of this will work. | |
| if (!io) throw new Error('`sails.io.js` requires a socket.io client, but `io` was not passed in.'); | |
| ////////////////////////////////////////////////////////////// | |
| ///// /////////////////////////// | |
| ///// PRIVATE METHODS/CONSTRUCTORS /////////////////////////// | |
| ///// /////////////////////////// | |
| ////////////////////////////////////////////////////////////// | |
| /** | |
| * A little logger for this library to use internally. | |
| * Basically just a wrapper around `console.log` with | |
| * support for feature-detection. | |
| * | |
| * @api private | |
| * @factory | |
| */ | |
| function LoggerFactory(options) { | |
| options = options || { | |
| prefix: true | |
| }; | |
| // If `console.log` is not accessible, `log` is a noop. | |
| if ( | |
| typeof console !== 'object' || | |
| typeof console.log !== 'function' || | |
| typeof console.log.bind !== 'function' | |
| ) { | |
| return function noop() {}; | |
| } | |
| return function log() { | |
| var args = Array.prototype.slice.call(arguments); | |
| // All logs are disabled when `io.sails.environment = 'production'`. | |
| if (io.sails.environment === 'production') return; | |
| // Add prefix to log messages (unless disabled) | |
| var PREFIX = ''; | |
| if (options.prefix) { | |
| args.unshift(PREFIX); | |
| } | |
| // Call wrapped logger | |
| console.log | |
| .bind(console) | |
| .apply(this, args); | |
| }; | |
| } | |
| // Create a private logger instance | |
| var consolog = LoggerFactory(); | |
| consolog.noPrefix = LoggerFactory({ | |
| prefix: false | |
| }); | |
| /** | |
| * What is the `requestQueue`? | |
| * | |
| * The request queue is used to simplify app-level connection logic-- | |
| * i.e. so you don't have to wait for the socket to be connected | |
| * to start trying to synchronize data. | |
| * | |
| * @api private | |
| * @param {SailsSocket} socket | |
| */ | |
| function runRequestQueue (socket) { | |
| var queue = socket.requestQueue; | |
| if (!queue) return; | |
| for (var i in queue) { | |
| // Double-check that `queue[i]` will not | |
| // inadvertently discover extra properties attached to the Object | |
| // and/or Array prototype by other libraries/frameworks/tools. | |
| // (e.g. Ember does this. See https://github.com/balderdashy/sails.io.js/pull/5) | |
| var isSafeToDereference = ({}).hasOwnProperty.call(queue, i); | |
| if (isSafeToDereference) { | |
| // Emit the request. | |
| _emitFrom(socket, queue[i]); | |
| } | |
| } | |
| // Now empty the queue to remove it as a source of additional complexity. | |
| queue = null; | |
| } | |
| /** | |
| * Send a JSONP request. | |
| * | |
| * @param {Object} opts [optional] | |
| * @param {Function} cb | |
| * @return {XMLHttpRequest} | |
| */ | |
| function jsonp(opts, cb) { | |
| opts = opts || {}; | |
| if (typeof window === 'undefined') { | |
| // TODO: refactor node usage to live in here | |
| return cb(); | |
| } | |
| var scriptEl = document.createElement('script'); | |
| window._sailsIoJSConnect = function(response) { | |
| scriptEl.parentNode.removeChild(scriptEl); | |
| cb(response); | |
| }; | |
| scriptEl.src = opts.url; | |
| document.getElementsByTagName('head')[0].appendChild(scriptEl); | |
| } | |
| /** | |
| * The JWR (JSON WebSocket Response) received from a Sails server. | |
| * | |
| * @api public | |
| * @param {Object} responseCtx | |
| * => :body | |
| * => :statusCode | |
| * => :headers | |
| * | |
| * @constructor | |
| */ | |
| function JWR(responseCtx) { | |
| this.body = responseCtx.body || responseCtx; | |
| this.headers = responseCtx.headers || {}; | |
| this.statusCode = responseCtx.statusCode || 200; | |
| if (this.statusCode < 200 || this.statusCode >= 400) { | |
| this.error = this.body || this.statusCode; | |
| } | |
| } | |
| JWR.prototype.toString = function() { | |
| return '[ResponseFromSails]' + ' -- ' + | |
| 'Status: ' + this.statusCode + ' -- ' + | |
| 'Headers: ' + this.headers + ' -- ' + | |
| 'Body: ' + this.body; | |
| }; | |
| JWR.prototype.toPOJO = function() { | |
| return { | |
| body: this.body, | |
| headers: this.headers, | |
| statusCode: this.statusCode | |
| }; | |
| }; | |
| JWR.prototype.pipe = function() { | |
| // TODO: look at substack's stuff | |
| return new Error('Client-side streaming support not implemented yet.'); | |
| }; | |
| /** | |
| * @api private | |
| * @param {SailsSocket} socket [description] | |
| * @param {Object} requestCtx [description] | |
| */ | |
| function _emitFrom(socket, requestCtx) { | |
| if (!socket._raw) { | |
| throw new Error('Failed to emit from socket- raw SIO socket is missing.'); | |
| } | |
| // Since callback is embedded in requestCtx, | |
| // retrieve it and delete the key before continuing. | |
| var cb = requestCtx.cb; | |
| delete requestCtx.cb; | |
| // Name of the appropriate socket.io listener on the server | |
| // ( === the request method or "verb", e.g. 'get', 'post', 'put', etc. ) | |
| var sailsEndpoint = requestCtx.method; | |
| socket._raw.emit(sailsEndpoint, requestCtx, function serverResponded(responseCtx) { | |
| // Send back (emulatedHTTPBody, jsonWebSocketResponse) | |
| if (cb && responseCtx) { | |
| cb(responseCtx.body, new JWR(responseCtx)); | |
| } | |
| }); | |
| } | |
| ////////////////////////////////////////////////////////////// | |
| ///// </PRIVATE METHODS/CONSTRUCTORS> //////////////////////// | |
| ////////////////////////////////////////////////////////////// | |
| // Version note: | |
| // | |
| // `io.SocketNamespace.prototype` doesn't exist in sio 1.0. | |
| // | |
| // Rather than adding methods to the prototype for the Socket instance that is returned | |
| // when the browser connects with `io.connect()`, we create our own constructor, `SailsSocket`. | |
| // This makes our solution more future-proof and helps us work better w/ the Socket.io team | |
| // when changes are rolled out in the future. To get a `SailsSocket`, you can run: | |
| // ``` | |
| // io.sails.connect(); | |
| // ``` | |
| /** | |
| * SailsSocket | |
| * | |
| * A wrapper for an underlying Socket instance that communicates directly | |
| * to the Socket.io server running inside of Sails. | |
| * | |
| * If no `socket` option is provied, SailsSocket will function as a mock. It will queue socket | |
| * requests and event handler bindings, replaying them when the raw underlying socket actually | |
| * connects. This is handy when we don't necessarily have the valid configuration to know | |
| * WHICH SERVER to talk to yet, etc. It is also used by `io.socket` for your convenience. | |
| * | |
| * @constructor | |
| */ | |
| function SailsSocket (opts){ | |
| var self = this; | |
| opts = opts||{}; | |
| // Absorb opts | |
| self.useCORSRouteToGetCookie = opts.useCORSRouteToGetCookie; | |
| self.url = opts.url; | |
| self.multiplex = opts.multiplex; | |
| self.transports = opts.transports; | |
| // Set up "eventQueue" to hold event handlers which have not been set on the actual raw socket yet. | |
| self.eventQueue = {}; | |
| // Listen for special `parseError` event sent from sockets hook on the backend | |
| // if an error occurs but a valid callback was not received from the client | |
| // (i.e. so the server had no other way to send back the error information) | |
| self.on('sails:parseError', function (err){ | |
| consolog('Sails encountered an error parsing a socket message sent from this client, and did not have access to a callback function to respond with.'); | |
| consolog('Error details:',err); | |
| }); | |
| // TODO: | |
| // Listen for a special private message on any connected that allows the server | |
| // to set the environment (giving us 100% certainty that we guessed right) | |
| // However, note that the `console.log`s called before and after connection | |
| // are still forced to rely on our existing heuristics (to disable, tack #production | |
| // onto the URL used to fetch this file.) | |
| } | |
| /** | |
| * Start connecting this socket. | |
| * | |
| * @api private | |
| */ | |
| SailsSocket.prototype._connect = function (){ | |
| var self = this; | |
| // Apply `io.sails` config as defaults | |
| // (now that at least one tick has elapsed) | |
| self.useCORSRouteToGetCookie = self.useCORSRouteToGetCookie||io.sails.useCORSRouteToGetCookie; | |
| self.url = self.url||io.sails.url; | |
| self.transports = self.transports || io.sails.transports; | |
| // Ensure URL has no trailing slash | |
| self.url = self.url ? self.url.replace(/(\/)$/, '') : undefined; | |
| // Mix the current SDK version into the query string in | |
| // the connection request to the server: | |
| if (typeof self.query !== 'string') self.query = SDK_INFO.versionString; | |
| else self.query += '&' + SDK_INFO.versionString; | |
| // Determine whether this is a cross-origin socket by examining the | |
| // hostname and port on the `window.location` object. | |
| var isXOrigin = (function (){ | |
| // If `window` doesn't exist (i.e. being used from node.js), then it's | |
| // always "cross-domain". | |
| if (typeof window === 'undefined' || typeof window.location === 'undefined') { | |
| return false; | |
| } | |
| // If `self.url` (aka "target") is falsy, then we don't need to worry about it. | |
| if (typeof self.url !== 'string') { return false; } | |
| // Get information about the "target" (`self.url`) | |
| var targetProtocol = (function (){ | |
| try { | |
| targetProtocol = self.url.match(/^([a-z]+:\/\/)/i)[1].toLowerCase(); | |
| } | |
| catch (e) {} | |
| targetProtocol = targetProtocol || 'http://'; | |
| return targetProtocol; | |
| })(); | |
| var isTargetSSL = !!self.url.match('^https'); | |
| var targetPort = (function (){ | |
| try { | |
| return self.url.match(/^[a-z]+:\/\/[^:]*:([0-9]*)/i)[1]; | |
| } | |
| catch (e){} | |
| return isTargetSSL ? '443' : '80'; | |
| })(); | |
| var targetAfterProtocol = self.url.replace(/^([a-z]+:\/\/)/i, ''); | |
| // If target protocol is different than the actual protocol, | |
| // then we'll consider this cross-origin. | |
| if (targetProtocol.replace(/[:\/]/g, '') !== window.location.protocol.replace(/[:\/]/g,'')) { | |
| return true; | |
| } | |
| // If target hostname is different than actual hostname, we'll consider this cross-origin. | |
| var hasSameHostname = targetAfterProtocol.search(window.location.hostname) !== 0; | |
| if (!hasSameHostname) { | |
| return true; | |
| } | |
| // If no actual port is explicitly set on the `window.location` object, | |
| // we'll assume either 80 or 443. | |
| var isLocationSSL = window.location.protocol.match(/https/i); | |
| var locationPort = (window.location.port+'') || (isLocationSSL ? '443' : '80'); | |
| // Finally, if ports don't match, we'll consider this cross-origin. | |
| if (targetPort !== locationPort) { | |
| return true; | |
| } | |
| // Otherwise, it's the same origin. | |
| return false; | |
| })(); | |
| // Prepare to start connecting the socket | |
| (function selfInvoking (cb){ | |
| // If this is an attempt at a cross-origin or cross-port | |
| // socket connection, send a JSONP request first to ensure | |
| // that a valid cookie is available. This can be disabled | |
| // by setting `io.sails.useCORSRouteToGetCookie` to false. | |
| // | |
| // Otherwise, skip the stuff below. | |
| if (!(self.useCORSRouteToGetCookie && isXOrigin)) { | |
| return cb(); | |
| } | |
| // Figure out the x-origin CORS route | |
| // (Sails provides a default) | |
| var xOriginCookieURL = self.url; | |
| if (typeof self.useCORSRouteToGetCookie === 'string') { | |
| xOriginCookieURL += self.useCORSRouteToGetCookie; | |
| } | |
| else { | |
| xOriginCookieURL += '/__getcookie'; | |
| } | |
| // Make the AJAX request (CORS) | |
| if (typeof window !== 'undefined') { | |
| jsonp({ | |
| url: xOriginCookieURL, | |
| method: 'GET' | |
| }, cb); | |
| return; | |
| } | |
| // If there's no `window` object, we must be running in Node.js | |
| // so just require the request module and send the HTTP request that | |
| // way. | |
| var mikealsReq = require('request'); | |
| mikealsReq.get(xOriginCookieURL, function(err, httpResponse, body) { | |
| if (err) { | |
| consolog( | |
| 'Failed to connect socket (failed to get cookie)', | |
| 'Error:', err | |
| ); | |
| return; | |
| } | |
| cb(); | |
| }); | |
| })(function goAheadAndActuallyConnect() { | |
| // Now that we're ready to connect, create a raw underlying Socket | |
| // using Socket.io and save it as `_raw` (this will start it connecting) | |
| self._raw = io(self.url, self); | |
| // Replay event bindings from the eager socket | |
| self.replay(); | |
| /** | |
| * 'connect' event is triggered when the socket establishes a connection | |
| * successfully. | |
| */ | |
| self.on('connect', function socketConnected() { | |
| consolog.noPrefix( | |
| '\n' + | |
| '\n' + | |
| // ' |> ' + '\n' + | |
| // ' \\___/ '+️ | |
| // '\n'+ | |
| ' |> Now connected to Sails.' + '\n' + | |
| '\\___/ For help, see: http://bit.ly/1DmTvgK' + '\n' + | |
| ' (using '+io.sails.sdk.platform+' SDK @v'+io.sails.sdk.version+')'+ '\n' + | |
| '\n'+ | |
| '\n'+ | |
| // '\n'+ | |
| '' | |
| // ' ⚓︎ (development mode)' | |
| // 'e.g. to send a GET request to Sails via WebSockets, run:'+ '\n' + | |
| // '`io.socket.get("/foo", function serverRespondedWith (body, jwr) { console.log(body); })`'+ '\n' + | |
| ); | |
| }); | |
| self.on('disconnect', function() { | |
| self.connectionLostTimestamp = (new Date()).getTime(); | |
| consolog('===================================='); | |
| consolog('Socket was disconnected from Sails.'); | |
| consolog('Usually, this is due to one of the following reasons:' + '\n' + | |
| ' -> the server ' + (self.url ? self.url + ' ' : '') + 'was taken down' + '\n' + | |
| ' -> your browser lost internet connectivity'); | |
| consolog('===================================='); | |
| }); | |
| self.on('reconnecting', function(numAttempts) { | |
| consolog( | |
| '\n'+ | |
| ' Socket is trying to reconnect to Sails...\n'+ | |
| '_-|>_- (attempt #' + numAttempts + ')'+'\n'+ | |
| '\n' | |
| ); | |
| }); | |
| self.on('reconnect', function(transport, numAttempts) { | |
| var msSinceConnectionLost = ((new Date()).getTime() - self.connectionLostTimestamp); | |
| var numSecsOffline = (msSinceConnectionLost / 1000); | |
| consolog( | |
| '\n'+ | |
| ' |> Socket reconnected successfully after'+'\n'+ | |
| '\\___/ being offline for ~' + numSecsOffline + ' seconds.'+'\n'+ | |
| '\n' | |
| ); | |
| }); | |
| // 'error' event is triggered if connection can not be established. | |
| // (usually because of a failed authorization, which is in turn | |
| // usually due to a missing or invalid cookie) | |
| self.on('error', function failedToConnect(err) { | |
| // TODO: | |
| // handle failed connections due to failed authorization | |
| // in a smarter way (probably can listen for a different event) | |
| // A bug in Socket.io 0.9.x causes `connect_failed` | |
| // and `reconnect_failed` not to fire. | |
| // Check out the discussion in github issues for details: | |
| // https://github.com/LearnBoost/socket.io/issues/652 | |
| // io.socket.on('connect_failed', function () { | |
| // consolog('io.socket emitted `connect_failed`'); | |
| // }); | |
| // io.socket.on('reconnect_failed', function () { | |
| // consolog('io.socket emitted `reconnect_failed`'); | |
| // }); | |
| consolog( | |
| 'Failed to connect socket (probably due to failed authorization on server)', | |
| 'Error:', err | |
| ); | |
| }); | |
| }); | |
| }; | |
| /** | |
| * Disconnect the underlying socket. | |
| * | |
| * @api public | |
| */ | |
| SailsSocket.prototype.disconnect = function (){ | |
| if (!this._raw) { | |
| throw new Error('Cannot disconnect- socket is already disconnected'); | |
| } | |
| return this._raw.disconnect(); | |
| }; | |
| /** | |
| * isConnected | |
| * | |
| * @api private | |
| * @return {Boolean} whether the socket is connected and able to | |
| * communicate w/ the server. | |
| */ | |
| SailsSocket.prototype.isConnected = function () { | |
| if (!this._raw) { | |
| return false; | |
| } | |
| return !!this._raw.socket.connected; | |
| }; | |
| /** | |
| * [replay description] | |
| * @return {[type]} [description] | |
| */ | |
| SailsSocket.prototype.replay = function (){ | |
| var self = this; | |
| // Pass events and a reference to the request queue | |
| // off to the self._raw for consumption | |
| for (var evName in self.eventQueue) { | |
| for (var i in self.eventQueue[evName]) { | |
| self._raw.on(evName, self.eventQueue[evName][i]); | |
| } | |
| } | |
| // Bind a one-time function to run the request queue | |
| // when the self._raw connects. | |
| if ( !self.isConnected() ) { | |
| var alreadyRanRequestQueue = false; | |
| self._raw.on('connect', function whenRawSocketConnects() { | |
| if (alreadyRanRequestQueue) return; | |
| runRequestQueue(self); | |
| alreadyRanRequestQueue = true; | |
| }); | |
| } | |
| // Or run it immediately if self._raw is already connected | |
| else { | |
| runRequestQueue(self); | |
| } | |
| return self; | |
| }; | |
| /** | |
| * Chainable method to bind an event to the socket. | |
| * | |
| * @param {String} evName [event name] | |
| * @param {Function} fn [event handler function] | |
| * @return {SailsSocket} | |
| */ | |
| SailsSocket.prototype.on = function (evName, fn){ | |
| // Bind the event to the raw underlying socket if possible. | |
| if (this._raw) { | |
| this._raw.on(evName, fn); | |
| return this; | |
| } | |
| // Otherwise queue the event binding. | |
| if (!this.eventQueue[evName]) { | |
| this.eventQueue[evName] = [fn]; | |
| } | |
| else { | |
| this.eventQueue[evName].push(fn); | |
| } | |
| return this; | |
| }; | |
| /** | |
| * Chainable method to unbind an event from the socket. | |
| * | |
| * @param {String} evName [event name] | |
| * @param {Function} fn [event handler function] | |
| * @return {SailsSocket} | |
| */ | |
| SailsSocket.prototype.off = function (evName, fn){ | |
| // Bind the event to the raw underlying socket if possible. | |
| if (this._raw) { | |
| this._raw.off(evName, fn); | |
| return this; | |
| } | |
| // Otherwise queue the event binding. | |
| if (this.eventQueue[evName] && this.eventQueue[evName].indexOf(fn) > -1) { | |
| this.eventQueue[evName].splice(this.eventQueue[evName].indexOf(fn), 1); | |
| } | |
| return this; | |
| }; | |
| /** | |
| * Chainable method to unbind all events from the socket. | |
| * | |
| * @return {SailsSocket} | |
| */ | |
| SailsSocket.prototype.removeAllListeners = function (){ | |
| // Bind the event to the raw underlying socket if possible. | |
| if (this._raw) { | |
| this._raw.removeAllListeners(); | |
| return this; | |
| } | |
| // Otherwise queue the event binding. | |
| this.eventQueue = {}; | |
| return this; | |
| }; | |
| /** | |
| * Simulate a GET request to sails | |
| * e.g. | |
| * `socket.get('/user/3', Stats.populate)` | |
| * | |
| * @api public | |
| * @param {String} url :: destination URL | |
| * @param {Object} params :: parameters to send with the request [optional] | |
| * @param {Function} cb :: callback function to call when finished [optional] | |
| */ | |
| SailsSocket.prototype.get = function(url, data, cb) { | |
| // `data` is optional | |
| if (typeof data === 'function') { | |
| cb = data; | |
| data = {}; | |
| } | |
| return this.request({ | |
| method: 'get', | |
| params: data, | |
| url: url | |
| }, cb); | |
| }; | |
| /** | |
| * Simulate a POST request to sails | |
| * e.g. | |
| * `socket.post('/event', newMeeting, $spinner.hide)` | |
| * | |
| * @api public | |
| * @param {String} url :: destination URL | |
| * @param {Object} params :: parameters to send with the request [optional] | |
| * @param {Function} cb :: callback function to call when finished [optional] | |
| */ | |
| SailsSocket.prototype.post = function(url, data, cb) { | |
| // `data` is optional | |
| if (typeof data === 'function') { | |
| cb = data; | |
| data = {}; | |
| } | |
| return this.request({ | |
| method: 'post', | |
| data: data, | |
| url: url | |
| }, cb); | |
| }; | |
| /** | |
| * Simulate a PUT request to sails | |
| * e.g. | |
| * `socket.post('/event/3', changedFields, $spinner.hide)` | |
| * | |
| * @api public | |
| * @param {String} url :: destination URL | |
| * @param {Object} params :: parameters to send with the request [optional] | |
| * @param {Function} cb :: callback function to call when finished [optional] | |
| */ | |
| SailsSocket.prototype.put = function(url, data, cb) { | |
| // `data` is optional | |
| if (typeof data === 'function') { | |
| cb = data; | |
| data = {}; | |
| } | |
| return this.request({ | |
| method: 'put', | |
| params: data, | |
| url: url | |
| }, cb); | |
| }; | |
| /** | |
| * Simulate a DELETE request to sails | |
| * e.g. | |
| * `socket.delete('/event', $spinner.hide)` | |
| * | |
| * @api public | |
| * @param {String} url :: destination URL | |
| * @param {Object} params :: parameters to send with the request [optional] | |
| * @param {Function} cb :: callback function to call when finished [optional] | |
| */ | |
| SailsSocket.prototype['delete'] = function(url, data, cb) { | |
| // `data` is optional | |
| if (typeof data === 'function') { | |
| cb = data; | |
| data = {}; | |
| } | |
| return this.request({ | |
| method: 'delete', | |
| params: data, | |
| url: url | |
| }, cb); | |
| }; | |
| /** | |
| * Simulate an HTTP request to sails | |
| * e.g. | |
| * ``` | |
| * socket.request({ | |
| * url:'/user', | |
| * params: {}, | |
| * method: 'POST', | |
| * headers: {} | |
| * }, function (responseBody, JWR) { | |
| * // ... | |
| * }); | |
| * ``` | |
| * | |
| * @api public | |
| * @option {String} url :: destination URL | |
| * @option {Object} params :: parameters to send with the request [optional] | |
| * @option {Object} headers:: headers to send with the request [optional] | |
| * @option {Function} cb :: callback function to call when finished [optional] | |
| * @option {String} method :: HTTP request method [optional] | |
| */ | |
| SailsSocket.prototype.request = function(options, cb) { | |
| var usage = | |
| 'Usage:\n'+ | |
| 'socket.request( options, [fnToCallWhenComplete] )\n\n'+ | |
| 'options.url :: e.g. "/foo/bar"'+'\n'+ | |
| 'options.method :: e.g. "get", "post", "put", or "delete", etc.'+'\n'+ | |
| 'options.params :: e.g. { emailAddress: "[email protected]" }'+'\n'+ | |
| 'options.headers :: e.g. { "x-my-custom-header": "some string" }'; | |
| // Old usage: | |
| // var usage = 'Usage:\n socket.'+(options.method||'request')+'('+ | |
| // ' destinationURL, [dataToSend], [fnToCallWhenComplete] )'; | |
| // Validate options and callback | |
| if (typeof options !== 'object' || typeof options.url !== 'string') { | |
| throw new Error('Invalid or missing URL!\n' + usage); | |
| } | |
| if (options.method && typeof options.method !== 'string') { | |
| throw new Error('Invalid `method` provided (should be a string like "post" or "put")\n' + usage); | |
| } | |
| if (options.headers && typeof options.headers !== 'object') { | |
| throw new Error('Invalid `headers` provided (should be an object with string values)\n' + usage); | |
| } | |
| if (options.params && typeof options.params !== 'object') { | |
| throw new Error('Invalid `params` provided (should be an object with string values)\n' + usage); | |
| } | |
| if (cb && typeof cb !== 'function') { | |
| throw new Error('Invalid callback function!\n' + usage); | |
| } | |
| // Build a simulated request object | |
| // (and sanitize/marshal options along the way) | |
| var requestCtx = { | |
| method: options.method.toLowerCase() || 'get', | |
| headers: options.headers || {}, | |
| data: options.params || options.data || {}, | |
| // Remove trailing slashes and spaces to make packets smaller. | |
| url: options.url.replace(/^(.+)\/*\s*$/, '$1'), | |
| cb: cb | |
| }; | |
| // If this socket is not connected yet, queue up this request | |
| // instead of sending it. | |
| // (so it can be replayed when the socket comes online.) | |
| if ( ! this.isConnected() ) { | |
| // If no queue array exists for this socket yet, create it. | |
| this.requestQueue = this.requestQueue || []; | |
| this.requestQueue.push(requestCtx); | |
| return; | |
| } | |
| // Otherwise, our socket is ok! | |
| // Send the request. | |
| _emitFrom(this, requestCtx); | |
| }; | |
| /** | |
| * Socket.prototype._request | |
| * | |
| * Simulate HTTP over Socket.io. | |
| * | |
| * @api private | |
| * @param {[type]} options [description] | |
| * @param {Function} cb [description] | |
| */ | |
| SailsSocket.prototype._request = function(options, cb) { | |
| throw new Error('`_request()` was a private API deprecated as of v0.11 of the sails.io.js client. Use `.request()` instead.'); | |
| }; | |
| // Set a `sails` object that may be used for configuration before the | |
| // first socket connects (i.e. to prevent auto-connect) | |
| io.sails = { | |
| // Whether to automatically connect a socket and save it as `io.socket`. | |
| autoConnect: true, | |
| // The route (path) to hit to get a x-origin (CORS) cookie | |
| // (or true to use the default: '/__getcookie') | |
| useCORSRouteToGetCookie: true, | |
| // The environment we're running in. | |
| // (logs are not displayed when this is set to 'production') | |
| // | |
| // Defaults to development unless this script was fetched from a URL | |
| // that ends in `*.min.js` or '#production' (may also be manually overridden.) | |
| // | |
| environment: urlThisScriptWasFetchedFrom.match(/(\#production|\.min\.js)/g) ? 'production' : 'development', | |
| // The version of this sails.io.js client SDK | |
| sdk: SDK_INFO, | |
| // Transports to use when communicating with the server, in the order they will be tried | |
| transports: ['polling', 'websocket'] | |
| }; | |
| /** | |
| * Add `io.sails.connect` function as a wrapper for the built-in `io()` aka `io.connect()` | |
| * method, returning a SailsSocket. This special function respects the configured io.sails | |
| * connection URL, as well as sending other identifying information (most importantly, the | |
| * current version of this SDK). | |
| * | |
| * @param {String} url [optional] | |
| * @param {Object} opts [optional] | |
| * @return {Socket} | |
| */ | |
| io.sails.connect = function(url, opts) { | |
| opts = opts || {}; | |
| // If explicit connection url is specified, save it to options | |
| opts.url = url || opts.url || undefined; | |
| // Instantiate and return a new SailsSocket- and try to connect immediately. | |
| var socket = new SailsSocket(opts); | |
| socket._connect(); | |
| return socket; | |
| }; | |
| // io.socket | |
| // | |
| // The eager instance of Socket which will automatically try to connect | |
| // using the host that this js file was served from. | |
| // | |
| // This can be disabled or configured by setting properties on `io.sails.*` within the | |
| // first cycle of the event loop. | |
| // | |
| // Build `io.socket` so it exists | |
| // (this does not start the connection process) | |
| io.socket = new SailsSocket(); | |
| // In the mean time, this eager socket will be queue events bound by the user | |
| // before the first cycle of the event loop (using `.on()`), which will later | |
| // be rebound on the raw underlying socket. | |
| // If configured to do so, start auto-connecting after the first cycle of the event loop | |
| // has completed (to allow time for this behavior to be configured/disabled | |
| // by specifying properties on `io.sails`) | |
| setTimeout(function() { | |
| // If autoConnect is disabled, delete the eager socket (io.socket) and bail out. | |
| if (!io.sails.autoConnect) { | |
| delete io.socket; | |
| return; | |
| } | |
| // consolog('Eagerly auto-connecting socket to Sails... (requests will be queued in the mean-time)'); | |
| io.socket._connect(); | |
| }, 0); // </setTimeout> | |
| // Return the `io` object. | |
| return io; | |
| } | |
| // Add CommonJS support to allow this client SDK to be used from Node.js. | |
| if (typeof module === 'object' && typeof module.exports !== 'undefined') { | |
| module.exports = SailsIOClient; | |
| return SailsIOClient; | |
| } | |
| // Otherwise, try to instantiate the client: | |
| // In case you're wrapping the socket.io client to prevent pollution of the | |
| // global namespace, you can replace the global `io` with your own `io` here: | |
| return SailsIOClient(); | |
| })(); |
| global.navigator = false; | |
| var Promise = require("bluebird"); | |
| var fs = require("fs"); | |
| var io = require("socket.io-client"); | |
| var sio = require("./sails.io.js"); | |
| var clientio = sio(); | |
| clientio.sails.url = "https://beam.pro"; | |
| var socket = clientio.socket; | |
| Promise.promisifyAll(socket); | |
| socket.on("connect", function () { | |
| console.log("connected"); | |
| socket.postAsync("/api/v1/users/login", {username: "<username>", password: "<password>"}) | |
| .then(function (data) { | |
| // Login response | |
| return socket.getAsync("/api/v1/channels/search", {scope: "names", query: "MindlessPuppetz"}); | |
| }).then(function (data) { | |
| // Search response | |
| var id = (JSON.parse(data.body)[0]).id; | |
| // console.log(JSON.parse(data.body)[0]) | |
| socket.on("channel:" + id + ":status", function (status) { | |
| console.log("Status changed", status); | |
| }); | |
| return socket.putAsync("/api/v1/live", {slug: "channel:" + id + ":status"}); | |
| }).then(function (data) { | |
| // Register response | |
| console.log(data); | |
| }).catch(function (err) { | |
| console.log("ERROR", err); | |
| }); | |
| }); |